{"id":15063272,"url":"https://github.com/loilo/node-symfony-style-console","last_synced_at":"2025-04-10T10:42:55.379Z","repository":{"id":20487122,"uuid":"90048038","full_name":"loilo/node-symfony-style-console","owner":"loilo","description":"🎼 Use the style and utilities of the Symfony Console in Node.js","archived":false,"fork":false,"pushed_at":"2022-07-06T07:04:54.000Z","size":446,"stargazers_count":19,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T19:43:12.333Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/loilo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-02T15:20:46.000Z","updated_at":"2023-03-27T09:33:44.000Z","dependencies_parsed_at":"2022-09-15T21:41:20.872Z","dependency_job_id":null,"html_url":"https://github.com/loilo/node-symfony-style-console","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fnode-symfony-style-console","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fnode-symfony-style-console/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fnode-symfony-style-console/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fnode-symfony-style-console/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loilo","download_url":"https://codeload.github.com/loilo/node-symfony-style-console/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247847611,"owners_count":21006100,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T23:54:19.978Z","updated_at":"2025-04-10T10:42:55.359Z","avatar_url":"https://github.com/loilo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# symfony-style-console\n\nUse the style and utilities of the [Symfony Console](https://symfony.com/doc/current/console/style.html) in Node.js.\n\n![Example of Symfony Style console output](symf-opener.png)\n\n## Important Note\nSince *Symfony* is, for good reason, a registered trademark, please take note that I'm in no way associated with [the Symfony brand](https://symfony.com/) or the [SensioLabs](https://sensiolabs.com/) organization. Therefore I don't represent or speak for any of them.\n\n## Reasoning\nWhile developing a PHP project using the *Symfony* framework, I found myself in the need of writing some Composer `post-install-cmd` scripts in Node.js.\n\nSadly, they did not visually align to the output from PHP which was using the `Symfony\\Component\\Console\\Style\\SymfonyStyle` class. So I decided to port that class and its environment to [TypeScript](https://typescriptlang.org) to be able to use that style in Node.js.\n\nSince style is always more or less closely coupled to different features, this package actually contains some nice utility the Symfony folks built into their console.\n\n## Usage\nFirst, of course, you need to install this package:\n```bash\n# With Yarn\nyarn add symfony-style-console\n\n# With npm\nnpm install --save symfony-style-console\n```\n\nThen, pull the `SymfonyStyle` class from the package and instantiate it:\n```javascript\nconst { SymfonyStyle } = require('symfony-style-console')\n\n// Or the more verbose way, in case you use Node.js v4:\nconst SymfonyStyle = require('symfony-style-console').SymfonyStyle\n\nconst io = new SymfonyStyle()\n```\n\n### `import`/`export`\nSince ES modules are coming [to more and more engines](http://caniuse.com/#feat=es6-module), this package offers an alternative build using ES2015 modules.\n\nYou can use it like this (note that you'll currently still need a Babel-like build chain to resolve those modules):\n\n```javascript\nimport { SymfonyStyle } from 'symfony-style-console/modern'\n\nconst io = new SymfonyStyle()\n```\n\n### Basics\nThe `io` instance now offers several different methods. If you know the Symfony console—Since this package aims to get as close to 100% API compatibility with the original PHP class as it can get—you may already be familiar with them.\n\n**Protip:** Because this package is written in TypeScript, you can get type hints for the `io` instance if you use an editor with support für `*.d.ts` declaration files.\n\nBack to topic, the available methods on the `io` instance are:\n```javascript\n// Put out a stylish title\nio.title('Symfony Style')\n\n// Similar to `title`, but less showy\nio.section('Subsection title')\n\n// The plain old `writeln` method. Does what you'd expect it to do.\nio.writeln([\n  'Just write some text.',\n  'You might, just like in this example, provide an array of\\n\\\nstrings to put multiple things.',\n  'But you don\\'t have to. A simple string will suffice.',\n  'Same goes for the write(), text(), block(), comment(),\\n\\\nsuccess(), caution(), warning() and error() methods.'\n])\n\n// Equivalent to `writeln`, but doesn't put a line break after\nio.write([\n  'Write multiple things without ',\n  'a line break between or after them.'\n])\n\n// Put 2 blank lines on the screen.\n// The argument is optional and defaults to 1\nio.newLine(2)\n\n// `text` blocks get indented by one character.\nio.text('This gets indented by one character.')\n\n// `comment` blocks are also indented and preceded\n// by a double slash \"//\"\nio.comment('In case you need additional information.')\n\n// `block` serves to group content, with a certain styling.\nio.block([\n  'This gets indented as well.',\n  'Use this to indent a bunch of text next to a keyword.'\n], 'INFO', 'fg=black;bg=blue', ' i ', true)\n\n// `success`, `warning`, `caution` and `error` are really\n// just predefined `block` statements.\n// Doesn't make them less useful though.\nio.success('You\\'ve done this correctly.')\nio.warning('Be aware of this problem.')\nio.caution('I really need some attention!')\nio.error('This somehow went wrong.')\n\n\n// Questions\n\n// Please do gently ignore the fact that I haven't added\n// an `async` wrapper function to the following methods.\n// I just wanted to omit the visual noise. Also note that\n// async/await is only available in Node.js 7.6 and above.\n\n// Ask for strings\nconst name = await io.ask('Give me a name!', 'John Smith')\n\n// Ask for strings without showing them\nconst passwd = await io.askHidden('Give me a password!')\n\n// Ask for picking from a collection\nconst language = await io.choice('Pick a language!', {\n  php: 'PHP',\n  js: 'JavaScript',\n  other: 'Other'\n})\n\n// Ask for confirmation\nconst submit = await io.confirm('Submit?')\n\n// Last but not least: Progress bars!\n\n// Create one!\nio.progressStart(10)\n\n// Advance it!\nio.progressAdvance(6)\n\n// Set it!\nio.progressSet(3)\n\n// Finish it!\nio.progressFinish()\n```\n\nA screenshot of the result is below. Look at this beautiful terminal.\n\n![Comprehensive example output](symf-example.png)\n\n\n### Advanced\n#### Verbosity\nYou can set the verbosity of the `io` instance to only print what you need:\n\n```javascript\nconst {\n  SymfonyStyle,\n  VERBOSITY_NORMAL,\n  VERBOSITY_VERBOSE,\n  VERBOSITY_DEBUG\n} = require('symfony-style-console')\n\n// Default verbosity is VERBOSITY_NORMAL...\nconst io = new SymfonyStyle()\n\n// ...so this won't be printed:\nio.writeln('This is a more verbose message', VERBOSITY_VERBOSE)\n\n// Set the verbosity real high\nio.setVerbosity(VERBOSITY_DEBUG)\n\n// Now the same message will suddenly appear:\nio.writeln('This is a more verbose message', VERBOSITY_VERBOSE)\n```\n\nThe available verbosity options are (in this order, from least to most verbose):\n\n* `VERBOSITY_QUIET` (no output at all)\n* `VERBOSITY_NORMAL` (default)\n* `VERBOSITY_VERBOSE`\n* `VERBOSITY_VERY_VERBOSE`\n* `VERBOSITY_DEBUG`\n\n##### Using verbosity programmatically\n\nNote that the verbosity options are only available on the `write()` and `writeln()` methods.\n\nHowever, those `VERBOSITY_*` constants are just numbers and you can compare them as you need:\n\n```javascript\n// Verbosity setting is at least VERBOSITY_VERBOSE\nif (io.getVerbosity() \u003e VERBOSITY_NORMAL) {\n  io.success('You have a verbose console!')\n}\n```\n\nOr to make that even more comfortable, use the builtin methods:\n```javascript\n// Checks if output is completely turned off\nio.isQuiet()\n\n// The following do always read as \"is AT LEAST ****\"\nio.isVerbose()\nio.isVeryVerbose()\nio.isDebug()\n```\n\n##### Setting verbosity via command line flags\nSymfony itself ties those verbosity levels to certain command line flags (`-q`, `-v`, `-vv` and `-vvv`).\n\nThis package does not aim to be a CLI framework though, so if you want to use those flags, you'd have to bind them to the verbosity manually.\n\nThe following code would mimic Symfony's behaviour:\n\n```javascript\nconst {\n  SymfonyStyle,\n  VERBOSITY_QUIET,\n  VERBOSITY_VERBOSE,\n  VERBOSITY_VERY_VERBOSE,\n  VERBOSITY_DEBUG\n} = require('symfony-style-console')\n\nconst io = new SymfonyStyle()\n\nconst flagMap = {\n  '-q': VERBOSITY_QUIET,\n  '--quiet': VERBOSITY_QUIET,\n  '-v': VERBOSITY_VERBOSE,\n  '-vv': VERBOSITY_VERY_VERBOSE,\n  '-vvv': VERBOSITY_DEBUG\n}\n\nconst argv = process.argv.slice(2)\nfor (const flag in flagMap) {\n  if (argv.indexOf(flag) !== -1) {\n    io.setVerbosity(flagMap[flag])\n    break\n  }\n}\n```\n\n#### Styling\nYou can style your console output in a markup-like fashion:\n\n```javascript\nio.writeln('This is \u003cfg=blue\u003eblue\u003c/\u003e text!')\n```\n\nStyles can be a combination of foreground (`fg`) and background color (`bg`) as well as a comma-separated list of additional `options`.\n\nWant a fully fledged example? Observe:\n\n```javascript\nio.writeln([\n  'Give it a crazy style:'\n  '\u003cfg=green;bg=magenta;options=underscore,bold\u003eYeah!\u003c/\u003e'\n])\n```\n\nNote that you can nest stylings, but nested styling markup will not inherit parent styles.\n\nThe following code block does explain what that means:\n\n```javascript\n// Style the phrase: \"This text is green with an underlined word.\"\nio.write([\n  // This part is green\n  '\u003cfg=green\u003eThis text is green with an ',\n\n  // This part is underlined but not green\n  '\u003coptions=underscore\u003eunderlined\u003c/\u003e',\n\n  // This part is green again\n  ' word.\u003c/\u003e'\n])\n```\n\n##### Colors\nThe following colors are available: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white` and `default`\n\n##### Styles\nSupported styles include (support for each may vary): `bold`, `underscore`, `blink`, `reverse`, `dim` and `conceal`\n\n##### Blocks\nStyles are escaped in `block()` output and in all output derived from `blocks` (`success`, `warning`, `caution` and `error`). This is a design decision by the Symfony team and I'm not going to interfere with that.\n\n### API variations\nThere are some small things that differ from Symfony's original API.\n\n#### Dropped method: `askQuestion`\nSince the questions part is not actually a port of the original code but a completely custom implementation, there are no `Question` objects and thus no need or functionality for an `askQuestion` method on the `SymfonyStyle` class.\n\n#### Privatized method: `createProgressBar`\nAs opposed to the original, this package's `SymfonyStyle` class has no public `createProgressBar` method.\n\nThat method is integrated more deeply into the Symfony ecosystem than this project aims to support, and it's not necessary for the *user facing* API.\n\nIt still exists though, could be called and provide the same functionality, but it has been marked as `private` in source code so it doesn't appear in the TypeScript Definition files.\n\n#### Added method: `progressSet`\nI was missing a method to set the value of a progress bar to a certain step instead of just advancing it.\n\nThat's why I added the `progressSet(step)` method. This is not present in the original `SymfonyStyle` class.\n\n#### The `dim` style option\nI personally find the `dim` style pretty appealing, so I added it to the style options.\n\nHowever, be aware that support is not too widespread (does not work on Windows as far as I know).\n\n#### Return type: Questions\nThe interactive `ask`, `askHidden`, `choice` and `confirm` methods on the original `SymfonyStyle` class do return their results directly.\n\nSince JavaScript is asynchronous in its nature, Promises are returned that resolve to the resulting values.\n\nAlso, the original class allows numeric values for the `choice` question type. This is technically possible in this library but since JavaScript object literals only support strings as keys, numeric values will be returned as strings.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floilo%2Fnode-symfony-style-console","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floilo%2Fnode-symfony-style-console","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floilo%2Fnode-symfony-style-console/lists"}