[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[{*.json, *.yml}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior.\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Technical Info (please complete the following information)**\n - OS:\n - Signale Version:\n - Node.js Version:\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is.\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!--\n\nThank you for taking the time to contribute to Signale!\n\nFor more info on how to contribute to the project, please read the [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md).\n\nWe are always excited about pull requests!\nIf the pull request fixes any open issues, reference the corresponding issues in the following fashion: `Fixes #321`.\nIncluding test results/screenshots/.gifs (if applicable/possible) alongside new features and bug fixes is something that we strongly encourage.\n\nThank you so much again for all of your time invested in the project!\n\nNote: You can optionally use the template below to organize your commits as you develop your Pull Request.\n\n-->\n\n## Squashed commits\n\n-\n\n## Changelog in detail\n\n-\n\n## All changes\n\n- [klaudiosinani/signale@`commitHash1...commitHash2`](https://github.com/klaudiosinani/signale/compare/commitHash1...commitHash2)\n"
  },
  {
    "path": ".gitignore",
    "content": "# dependencies\nnode_modules\nyarn.lock\n\n# logs\n*.log\n\n# OS\n.DS_Store\n\n# IDE\n.vscode\n.idea\n*.swp\n*.swo\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - 10\n  - 8\n  - 6\nbefore_install:\n  - npm install --global npm@6.4.0\n  - npm --version\ngit:\n  depth: 5\ncache:\n  directories:\n    - node_modules\n"
  },
  {
    "path": "_config.yml",
    "content": "remote_theme: klaudiosinani/re@v0.4.0\nplugins:\n  - jekyll-github-metadata\n  - jekyll-remote-theme\n  - jekyll-sitemap\n\nre:\n  favicon: https://raw.githubusercontent.com/klaudiosinani/klaudiosinani.github.io/refs/heads/master/public/favicon.png\n  simpleanalytics:\n    enabled: true\n"
  },
  {
    "path": "code-of-conduct.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at klaussinani@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "contributing.md",
    "content": "# Contributing to Signale\n\nThank you for taking the time to contribute to Signale!\n\nPlease note that this project is released with a [Contributor Code of Conduct](code-of-conduct.md). By participating in this project you agree to abide by its terms.\n\n## How to contribute\n\n### Improve documentation\n\nTypo corrections, error fixes, better explanations, more examples etc. Open an issue regarding anything that you think it could be improved! You can use the [`docs` label](https://github.com/klaudiosinani/signale/labels/docs) to find out what others have suggested!\n\n### Improve issues\n\nSometimes reported issues lack information, are not reproducible, or are even plain invalid. Help us out to make them easier to resolve. Handling issues takes a lot of time that we could rather spend on fixing bugs and adding features.\n\n### Give feedback on issues\n\nWe're always looking for more opinions on discussions in the issue tracker. It's a good opportunity to influence the future direction of the project.\n\nThe [`question` label](https://github.com/klaudiosinani/signale/labels/question) is a good place to find ongoing discussions.\n\n### Write code\n\nYou can use issue labels to discover issues you could help us out with!\n\n- [`feature request` issues](https://github.com/klaudiosinani/signale/labels/feature%20request) are features we are open to including\n- [`bug` issues](https://github.com/klaudiosinani/signale/labels/bug) are known bugs we would like to fix\n- [`future` issues](https://github.com/klaudiosinani/signale/labels/future) are those that we'd like to get to, but not anytime soon. Please check before working on these since we may not yet want to take on the burden of supporting those features\n- on the [`help wanted`](https://github.com/klaudiosinani/signale/labels/help%20wanted) label you can always find something exciting going on\n\nYou may find an issue is assigned, or has the [`assigned` label](https://github.com/klaudiosinani/signale/labels/assigned). Please double-check before starting on this issue because somebody else is likely already working on it\n\n### Translating Documentation\n\n#### Create a Translation\n\n- Visit the [`translations' index`](https://github.com/klaudiosinani/signale/tree/master/docs/readme.md) file to ensure that the document is not already translated in your target language. \n- Add the name of the language to the document as an extension, e.g: `readme.JP.md`\n- Place the translated document inside the [`docs`](https://github.com/klaudiosinani/signale/tree/master/docs) directory.\n- Add your github profile and the translated document at the [`translations' index`](https://github.com/klaudiosinani/signale/tree/master/docs/readme.md) file.\n- Create a Pull Request including the language in the title, e.g: `Readme: Japanese Translation`\n\n#### Improve a Translation\n\n- Include your github profile next to the translation you improved at the [`translations' index`](https://github.com/klaudiosinani/signale/tree/master/docs/readme.md) file.\n- Create a Pull Request that delivers the improvements and include the language in the title, e.g: `Readme: Improvements for the Japanese Translation`\n\n### Submitting an issue\n\n- Search the issue tracker before opening an issue\n- Ensure you're using the latest version of Signale\n- Use a descriptive title\n- Include as much information as possible;\n  - Steps to reproduce the issue\n  - Error message\n  - Signale version\n  - Operating system **etc**\n\n### Submitting a pull request\n\n- Non-trivial changes are often best discussed in an issue first, to prevent you from doing unnecessary work\n- Try making the pull request from a [topic branch](https://github.com/dchelimsky/rspec/wiki/Topic-Branches) if it is of crucial importance\n- Use a descriptive title for the pull request and commits\n- You might be asked to do changes to your pull request, you can do that by just [updating the existing one](https://github.com/RichardLitt/docs/blob/master/amending-a-commit-guide.md)\n"
  },
  {
    "path": "docs/readme.AL.md",
    "content": "<h1 align=\"center\">\n  Signale\n</h1>\n\n<h4 align=\"center\">\n  Librari regjistrimi shumë e konfigurueshëme\n</h4>\n\n<div align=\"center\">\n  <img alt=\"Header\" src=\"../media/header.png\" width=\"88%\">\n</div>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/signale\">\n    <img alt=\"Shkarkime NPM\" src=\"https://img.shields.io/npm/dt/signale.svg\">\n  </a>\n</p>\n\n<div align=\"center\">\n  <br>\n  <sup><b>Sponsorizuar nga:</b></sup>\n  <br>\n  <a href=\"https://betterstack.com\">\n    <div>\n      <img src=\"https://github.com/Seldaek/monolog/assets/183678/7de58ce0-2fa2-45c0-b3e8-e60cebb3c4cf\" width=\"200\" alt=\"Better Stack\">\n    </div>\n    <sup>\n      Zbulo, Zgjidh dhe Parandaloni Kohën e Pushimit.\n    </sup>\n  </a>\n</div>\n\n## Përshkrimi\n\nPlotësisht i modifikueshëm dhe i konfigurueshëm deri në thelb, signale mund të përdoret për qëllime regjistrimi, raportim statusi, si dhe për menaxhimin e procesit të shfaqjes së output-it të moduleve dhe aplikacioneve të tjera të node.\n\nLexoni këtë dokument në: [English](https://github.com/klaudiosinani/signale/blob/master/readme.md), [German - Deutsch](https://github.com/klaudiosinani/signale/blob/master/docs/readme.DE.md), [简体中文 - Simplified Chinese](https://github.com/klaudiosinani/signale/blob/master/docs/readme.zh_CN.md).\n\nTani mund të mbështetni procesin e zhvillimit përmes [GitHub Sponsors](https://github.com/sponsors/klaudiosinani).\n\nVizitoni [udhëzimet e kontributit](https://github.com/klaudiosinani/signale/blob/master/contributing.md#translating-documentation) për të mësuar më shumë se si të përktheni këtë dokument në më shumë gjuhë.\n\n## Pikat Kryesore\n\n- 19 regjistrues të gatshëm për përdorim\n- Mund të modifikohet dhe personalizohet në çdo aspekt\n- Output i pastër dhe estetikisht i bukur\n- Kohëmatës të integruar\n- Regjistrues të personalizueshëm\n- Mbështetje për TypeScript\n- Modalitete interaktive dhe të rregullta\n- Filtrim sekretesh dhe informacioni të ndjeshëm\n- Mbështetje për emra skedarësh, data dhe kohë\n- Regjistrues dhe kohëmatës të fokusuar (scoped)\n- Mekanizëm i niveleve të shkallëzuara të regjistrimit\n- Mbështetje për interpolim string-jesh\n- Shumë flukse të regjistrueshme të ndryshueshme\n- Sintaksë e thjeshtë dhe minimale\n- Konfigurim global përmes `package.json`\n- Konfigurim i tejkalueshëm sipas skedari apo regjistruesi\n\n## Përmbajtja\n\n- [Përshkrimi](#përshkrimi)\n- [Pikat Kryesore](#pikat-kryesore)\n- [Instalimi](#instalimi)\n- [Përdorimi](#përdorimi)\n- [Konfigurimi](#konfigurimi)\n- [API](#api)\n- [Zhvillimi](#zhvillimi)\n- [Të Lidhura](#të-lidhura)\n- [Kush e përdor?](#kush-e-përdor)\n- [Ekipi](#ekipi)\n- [Sponsorët](#sponsorët)\n- [Licenca](#licenca)\n\n## Instalimi\n\n### Yarn\n\n```bash\nyarn add signale\n```\n\n### NPM\n\n```bash\nnpm install signale\n```\n\n## Përdorimi\n\n### Regjistruesit e Paracaktuar\n\nImportoni signale dhe filloni të përdorni ndonjërin nga regjistruesit e paracaktuar.\n\n<details>\n<summary>Shikoni të gjithë regjistruesit e disponueshëm.</summary>\n\n<br/>\n\n- `await`\n- `complete`\n- `error`\n- `debug`\n- `fatal`\n- `fav`\n- `info`\n- `note`\n- `pause`\n- `pending`\n- `star`\n- `start`\n- `success`\n- `wait`\n- `warn`\n- `watch`\n- `log`\n\n</details>\n\n<br/>\n\n```js\nconst signale = require('signale');\n\nsignale.success('Operacioni u përfundua me sukses');\nsignale.debug('Përshëndetje', 'nga', 'L59');\nsignale.pending('Shkruaj shënime për versionin %s', '1.2.0');\nsignale.fatal(new Error('Nuk mund të merret pranga'));\nsignale.watch('Po monitorohet në mënyrë rekursive direktoria e ndërtimit...');\nsignale.complete({prefix: '[detyrë]', message: 'Rregullo çështjen #59', suffix: '(@klaudiosinani)'});\n```\n\n<div align=\"center\">\n  <img alt=\"Regjistrues të Paracaktuar\" src=\"../media/default-loggers.png\" width=\"65%\">\n</div>\n\n### Regjistrues të Personalizuar\n\nPër të krijuar një regjistrues të personalizuar, përcaktoni një objekt `options` që përmban fushën `types` me të dhënat e regjistruesit, dhe kalojeni si argument tek një instancë e re e signale.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  disabled: false,\n  interactive: false,\n  logLevel: 'info',\n  scope: 'custom',\n  secrets: [],\n  stream: process.stdout,\n  types: {\n    remind: {\n      badge: '**',\n      color: 'yellow',\n      label: 'kujtesë',\n      logLevel: 'info'\n    },\n    santa: {\n      badge: '🎅',\n      color: 'red',\n      label: 'santa',\n      logLevel: 'info'\n    }\n  }\n};\n\nconst custom = new Signale(options);\ncustom.remind('Përmirësoni dokumentacionin.');\ncustom.santa('Hoho! Ke një variabël të papërdorur në L45.');\n```\n\n<div align=\"center\">\n  <img alt=\"Regjistrues të Personalizuar\" src=\"../media/custom-loggers.png\" width=\"70%\">\n</div>\n\nKëtu është një shembull se si të tejkaloni regjistruesit `error` dhe `success` të paracaktuar.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  types: {\n    error: {\n      badge: '!!',\n      label: 'gabim fatal'\n    },\n    success: {\n      badge: '++',\n      label: 'sukses i madh'\n    }\n  }\n};\n\nconst signale = new Signale();\nsignale.error('Regjistrimi i gabimit të paracaktuar');\nsignale.success('Regjistrimi i suksesit të paracaktuar');\n\nconst custom = new Signale(options);\ncustom.error('Regjistrimi i gabimit të personalizuar');\ncustom.success('Regjistrimi i suksesit të personalizuar');\n```\n\n<div align=\"center\">\n  <img alt=\"Regjistrues të Paracaktuar\" src=\"../media/override-defaults.png\" width=\"65%\">\n</div>\n\nObjekti `options` mund të përmbajë secilën nga vetitë: `disabled`, `interactive`, `logLevel`, `secrets`, `stream`, `scope` dhe `types`.\n\n##### `disabled`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nÇaktivizon funksionalitetin e regjistrimit për të gjithë regjistruesit që i përkasin instancës së krijuar.\n\n##### `interactive`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nKallon të gjithë regjistruesit në modalitet interaktiv.\n\n##### `logLevel`\n\n- Tipi: `String`\n- Parazgjedhur: `'info'`\n\nVendos nivelin e përgjithshëm të regjistrimit të instancës së krijuar. Mund të jetë një nga sa vijon:\n\n- `'info'` - Shfaq të gjitha mesazhet nga të gjithë regjistruesit.\n- `'timer'` - Shfaq mesazhet vetëm nga regjistruesit `time`, `timeEnd`, `debug`, `warn`, `error` & `fatal`.\n- `'debug'` - Shfaq mesazhet vetëm nga regjistruesit `debug`, `warn`, `error` & `fatal`.\n- `'warn'` - Shfaq mesazhet vetëm nga regjistruesit `warn`, `error` & `fatal`.\n- `'error'` - Shfaq mesazhet vetëm nga regjistruesit `error` & `fatal`.\n\n##### `secrets`\n\n- Tipi: `(String|Number)[]`\n- Parazgjedhur: `[]`\n\nNjë varg që përmban sekrete/informacion të ndjeshëm për t'u hequr nga trupi dhe metadata e mesazheve që do regjistrohen dhe do të zëvendësohet me '[secure]'.\n\n##### `stream`\n\n- Tipi: `stream.Writable|stream.Writable[]`\n- Parazgjedhur: `process.stdout`\n\nDestinacioni ku të dhënat shkruhen, mund të jetë një [Writable stream](https://nodejs.org/api/stream.html#stream_writable_streams) ose një varg me më shumë flukse të tilla.\n\n##### `scope`\n\n- Tipi: `String|String[]`\n\nEmri i kontekstit (scope) nga ku raporton regjistruesi.\n\n##### `types`\n\n- Tipi: `Object`\n\nPërmban konfigurimin e regjistruesve të personalizuar ose paracaktuar.\n\nGjithashtu, objekti konfigurues i çdo tipi regjistruesi të personalizuar ose paracaktuar, mund të mbajë çdo nga këto veti: `badge`, `label`, `color`, `logLevel` & `stream`.\n\n##### `badge`\n\n- Tipi: `String`\n\nIkona që i përket regjistruesit.\n\n##### `label`\n\n- Tipi: `String`\n\nEtiketa që identifikon llojin e regjistruesit.\n\n##### `color`\n\n- Tipi: `String`\n\nNgjyra e etiketës, mund të jetë çdo nga ngjyrat e mbështetura nga [chalk](https://github.com/chalk/chalk#colors).\n\n##### `logLevel`\n\n- Tipi: `String`\n- Parazgjedhur: `'info'`\n\nNiveli që i takon regjistruesit. Mesazhet shfaqen vetëm nëse niveli i tyre është më i lartë apo i barabartë me nivelin e përgjithshëm të instancës.\n\n##### `stream`\n\n- Tipi: `stream.Writable|stream.Writable[]`\n- Parazgjedhur: `process.stdout`\n\nDestinacioni ku të dhënat shkruhen, mund të jetë një stream i vetëm apo një varg streams.\n\n### Regjistrues Me Scope\n\nPër të krijuar një regjistrues me scope nga e para, përcaktoni fushën `scope` brenda objektit `options` dhe kalojeni tek një instancë e re të signale.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  scope: 'scope global'\n};\n\nconst global = new Signale(options);\nglobal.success('Operacioni i suksesshëm');\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Vanilla\" src=\"../media/scope-vanilla.png\" width=\"65%\">\n</div>\n\nPër të krijuar një regjistrues me scope të bazuar mbi një ekzistues, përdorni funksionin `scope()`, i cili do të kthejë një instancë të re signale, duke trashëguar të gjithë regjistruesit e personalizuar, kohëmatësit, sekretet, fluret, konfigurimin, nivelin e regjistrimit, mënyrën interaktive dhe statuset e çaktivuara nga ai fillestar.\n\n```js\nconst signale = require('signale');\n\nconst global = signale.scope('scope global');\nglobal.success('Përshëndetje nga scope-i global');\n\nfunction foo() {\n  const outer = global.scope('outer', 'scope');\n  outer.success('Përshëndetje nga scope-i i jashtëm');\n  \n  setTimeout(() => {\n    const inner = outer.scope('inner', 'scope'); \n    inner.success('Përshëndetje nga scope-i i brendshëm');\n  }, 500);\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Existing\" src=\"../media/scope-existing.png\" width=\"65%\">\n</div>\n\n### Regjistrues Interaktivë\n\nPër të inicializuar një regjistrues interaktiv, krijoni një instancë të re signale me atributin [`interactive`](#interactive) të vendosur në `true`. Kur jeni në mënyrën interaktive, mesazhet e mëparshme të regjistuar nga një regjistrues interaktiv, do të tejkalohen vetëm nga të reja që vijnë nga i njëjti ose një regjistrues tjetër interaktiv. Vini re se mesazhet e rregullta nga regjistruesit e rregullt nuk tejkalohen nga ata interaktivë.\n\n```js\nconst {Signale} = require('signale');\n\nconst interactive = new Signale({interactive: true, scope: 'interactive'});\n\ninteractive.await('[%d/4] - Procesi A', 1);\n\nsetTimeout(() => {\n  interactive.success('[%d/4] - Procesi A', 2);\n  setTimeout(() => {\n    interactive.await('[%d/4] - Procesi B', 3);\n    setTimeout(() => {\n      interactive.error('[%d/4] - Procesi B', 4);\n      setTimeout(() => {}, 1000);\n    }, 1000);\n  }, 1000);\n}, 1000);\n```\n\n<div align=\"center\">\n  <img alt=\"Modaliteti Interaktiv\" src=\"../media/interactive-mode.gif\" width=\"65%\">\n</div>\n\n### Flukse të Shkrueshme\n\nNë mënyrë të parazgjedhur, të gjitha instancat signale regjistrojnë mesazhet e tyre në fluksin `process.stdout`. Kjo mund të modifikohet, për t'u përshtatur me preferencën tuaj, përmes vetisë [`stream`](#stream), ku mund të përcaktoni një ose më shumë flukse të vlefshme të Shkrueshme, të cilat do të përdoren nga të gjithë llojet e regjistruesve për të regjistruar të dhënat tuaja. Gjithashtu, është e mundur të përcaktohet një ose më shumë flukse të Shkrueshme ekskluzivisht për një lloj specifik regjistruesi, duke shkruar kështu të dhëna në mënyrë të pavarur nga llojet e tjera të regjistruesve.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  stream: process.stderr, // Të gjithë regjistruesit do të shkruajnë tek `process.stderr`\n  types: {\n    error: {\n      // Vetëm `error` do të shkruajë tek të dy `process.stdout` & `process.stderr`\n      stream: [process.stdout, process.stderr]\n    }\n  }\n};\n\nconst signale = new Signale(options);\nsignale.success('Mesazhi do të shfaqet në `process.stderr`');\nsignale.error('Mesazhi do të shfaqet në të dy `process.stdout` & `process.stderr`');\n```\n\n<div align=\"center\">\n  <img alt=\"Flukse të Shkrueshme\" src=\"../media/writable-streams.png\" width=\"73%\">\n</div>\n\n### Filtrim Sekretesh\n\nDuke shfrytëzuar opsionin `secrets`, sekretet dhe informacione të tjera të ndjeshme mund të filtrohen nga trupi si dhe metadata, p.sh. emrat e scope-ve etj, të mesazheve për t'u regjistruar. Opsioni është pjesë e objektit të konfigurimit që kalon tek një instancë `Signale` gjatë inicializimit të saj, dhe është i tipit `Array<String|Number>`. Vargu mund të mbajë shumë sekrete, të gjitha këto hiqen, nëse janë të pranishme, nga mesazhet për t'u regjistruar dhe zëvendësohen me string-un e parazgjedhur `'[secure]'`. Gjithashtu, kur përdoret funksioni unary `signale.scope(name)`, instanca e kthyer `Signale` trashëgon të gjitha sekretet që i përkasin prindit të saj. Procesi i kontrollit të sekreteve kryhet në mënyrë **case-sensitive**. Gjithashtu, funksioni unary [`signale.addSecrets()`](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md#signaleaddsecretssecrets) dhe ai nullary [`signale.clearSecrets()`](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md#signaleclearsecrets) janë të disponueshme përmes API-së për shtim dhe pastrimin e sekreteve përkatësisht.\n\nËshtë **kritike** dhe **shumë e rekomanduar** të **mos i shkruani drejtpërdrejt sekretet në kodin tuaj**, kështu që shembulli në vijim shërben **vetëm** si një demonstrim përdorimi i thjeshtë dhe lehtësisht i riprodhuar.\n\n```js\nconst {Signale} = require('signale');\n\n// Në realitet sekretet mund të merren/deshkriptohen në mënyrë të sigurt përmes API-së së dedikuar \nconst [USERNAME, TOKEN] = ['klaudiosinani', 'token'];\n\nconst logger1 = new Signale({\n  secrets: [USERNAME, TOKEN]\n});\n\nlogger1.log('$ exporting USERNAME=%s', USERNAME);\nlogger1.log('$ exporting TOKEN=%s', TOKEN);\n\n// `logger2` trashëgon të gjitha sekretet nga prindi i tij `logger1`\nconst logger2 = logger1.scope('parent');\n\nlogger2.log('$ exporting USERNAME=%s', USERNAME);\nlogger2.log('$ exporting TOKEN=%s', TOKEN);\n```\n\n<div align=\"center\">\n  <img alt=\"Filtrim Sekretesh\" src=\"../media/filter-secrets.png\" width=\"73%\">\n</div>\n\n### Kohëmatës\n\nKohëmatësit menaxhohen nga funksionet `time()` dhe `timeEnd()`. Një etiketë unike mund të përdoret për të identifikuar një kohëmatës në inicializim, megjithëse nëse asnjë nuk jepet, kohëmatësi do të marrë një automatikisht. Përveç kësaj, thirrja e funksionit `timeEnd()` pa një etiketë të specifikuar do të ketë si efekt terminimin e kohëmatësit më të rishtëm, që u krijua pa dhënë etiketë.\n\n```js\nconst signale = require('signale');\n\nsignale.time('test');\nsignale.time();\nsignale.time();\n\nsetTimeout(() => {\n  signale.timeEnd();\n  signale.timeEnd();\n  signale.timeEnd('test');\n}, 500);\n```\n\n<div align=\"center\">\n  <img alt=\"Kohëmatës\" src=\"../media/timers.png\" width=\"60%\">\n</div>\n\n## Konfigurimi\n\n### Global\n\nPër të aktivizuar konfigurimin global përcaktoni opsionet nën namespace-in `signale` në `package.json` tuaj.\n\nSa në vijim ilustron të gjitha opsionet e disponueshme me vlerat e tyre përkatëse të parazgjedhura.\n\n```json\n{\n  \"signale\": {\n    \"displayScope\": true,\n    \"displayBadge\": true,\n    \"displayDate\": false,\n    \"displayFilename\": false,\n    \"displayLabel\": true,\n    \"displayTimestamp\": false,\n    \"underlineLabel\": true,\n    \"underlineMessage\": false,\n    \"underlinePrefix\": false,\n    \"underlineSuffix\": false,\n    \"uppercaseLabel\": false\n  }\n}\n```\n\n<details>\n<summary>Shikoni të gjitha opsionet e disponueshme në detaj.</summary>\n\n##### `displayScope`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `true`\n\nShfaq emrin e scope-it të regjistruesit.\n\n##### `displayBadge`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `true`\n\nShfaq stemën e regjistruesit.\n\n##### `displayDate`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nShfaq datën aktuale lokale në formatin `YYYY-MM-DD`.\n\n##### `displayFilename`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nShfaq emrin e skedarit nga i cili raporton regjistruesi.\n\n##### `displayLabel`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `true`\n\nShfaq etiketën e regjistruesit.\n\n##### `displayTimestamp`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nShfaq kohën aktuale lokale në formatin `HH:MM:SS`.\n\n##### `underlineLabel`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `true`\n\nNënvizon etiketën e regjistruesit.\n\n##### `underlineMessage`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nNënvizon mesazhin e regjistruesit.\n\n##### `underlinePrefix`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nNënvizon parashtesën e regjistruesit.\n\n##### `underlineSuffix`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nNënvizon prapashtesën e regjistruesit.\n\n##### `uppercaseLabel`\n\n- Tipi: `Boolean`\n- Parazgjedhur: `false`\n\nShfaq etiketën e regjistruesit me shkronja të mëdha.\n\n</details>\n\n### Lokal\n\nPër të aktivizuar konfigurimin lokal thirrni funksionin `config()` në instancën tuaj signale. Konfigurimet lokale do të tejkalojnë gjithmonë çdo konfigurim të mëparshëm të trashëguar nga `package.json`.\n\nNë shembullin vijues, regjistruesit në skedarin `foo.js` do të ekzekutohen nën konfigurimin e tyre, duke tejkaluar atë në `package.json`.\n\n```js\n// foo.js\nconst signale = require('signale');\n\n// Tejkalon çdo konfigurim ekzistues `package.json`\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n}); \n\nsignale.success('Përshëndetje nga Scope-i Global');\n```\n\n<div align=\"center\">\n  <img alt=\"Konfigurim Lokal\" src=\"../media/local-config.png\" width=\"65%\">\n</div>\n\nGjithashtu, regjistruesit me scope mund të kenë konfigurimin e tyre të pavarur, duke tejkaluar atë të trashëguar nga instanca prind ose `package.json`.\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n});\n\nsignale.success('Përshëndetje nga Scope-i Global');\n\nfunction foo() {\n  // `fooLogger` trashëgon konfigurimin e `signale`\n  const fooLogger = signale.scope('foo scope');\n\n  // Tejkalon të dy konfigurimet `signale` dhe `package.json`\n  fooLogger.config({\n    displayFilename: true,\n    displayTimestamp: false,\n    displayDate: true\n  });\n\n  fooLogger.success('Përshëndetje nga Scope-i Lokal');\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Konfigurim Scope\" src=\"../media/scope-config.png\" width=\"65%\">\n</div>\n\n## API\n\n#### signale.`<logger>(message[, message]|messageObj|errorObj)`\n\n##### **`logger`**\n\n- Tipi: `Function`\n\nMund të jetë çdo regjistrues i paracaktuar ose i personalizuar.\n\n##### **`message`**\n\n- Tipi: `String`\n\nMund të jetë një ose më shumë string-e të ndarë me presje.\n\n```js\nconst signale = require('signale');\n\nsignale.success('Operacion i suksesshëm');\n//=> ✔  success  Operacion i suksesshëm\n\nsignale.success('Operacion', 'i suksesshëm');\n//=> ✔  success  Operacion i suksesshëm\n\nsignale.success('Operacion i %s', 'suksesshëm');\n//=> ✔  success  Operacion i suksesshëm\n```\n\n##### **`errorObj`**\n\n- Tipi: `Error Object`\n\nMund të jetë çdo objekt gabimi.\n\n```js\nconst signale = require('signale');\n\nsignale.error(new Error('Operacion i pasuksesshëm'));\n//=> ✖  error  Error: Operacion i pasuksesshëm\n//        at Module._compile (module.js:660:30)\n//        at Object.Module._extensions..js (module.js:671:10)\n//        ...\n```\n\n##### **`messageObj`**\n\n- Tipi: `Object`\n\nMund të jetë një objekt që përmban atributet `prefix`, `message` dhe `suffix`, me `prefix` dhe `suffix` gjithmonë të shtuar përpara dhe pas `message`-it përkatësisht.\n\n```js\nconst signale = require('signale');\n\nsignale.complete({prefix: '[detyrë]', message: 'Rregullo çështjen #59', suffix: '(@klaudiosinani)'});\n//=> [detyrë] ☒  complete  Rregullo çështjen #59 (@klaudiosinani)\n\nsignale.complete({prefix: '[detyrë]', message: ['Rregullo çështjen #%d', 59], suffix: '(@klaudiosinani)'});\n//=> [detyrë] ☒  complete  Rregullo çështjen #59 (@klaudiosinani)\n```\n\n#### signale.`scope(name[, name])`\n\nPërcakton emrin e scope-it të regjistruesit.\n\n##### **`name`**\n\n- Tipi: `String`\n\nMund të jetë një ose më shumë string-e të ndarë me presje.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \nconst fooBar = signale.scope('foo', 'bar');\n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfooBar.success('foo bar');\n//=> [foo] [bar] › ✔  success  foo bar\n```\n\n#### signale.`unscope()`\n\nPastron emrin e scope-it të regjistruesit.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfoo.unscope();\n\nfoo.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`config(settingsObj)`\n\nVendos konfigurimin e një instance duke tejkaluar çdo konfigurim global ose lokal ekzistues.\n\n##### **`settingsObj`**\n\n- Tipi: `Object`\n\nMund të mbajë çdo nga [opsionet](#global) e dokumentuara.\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: true\n});\n\nsignale.success('Operacione të suksesshme');\n//=> [2018-5-15] [11:12:38] [foo.js] › ✔  success  Operacione të suksesshme\n```\n\n#### signale.`time([, label])`\n\n- Tipi i Kthimit: `String`\n\nVendos një kohëmatës dhe pranon një etiketë opsionale. Nëse asnjë nuk jepet, kohëmatësi do të marrë një etiketë unike automatikisht.\n\nKthen një string që korrespondon me etiketën e kohëmatësit.\n\n##### **`label`**\n\n- Tipi: `String`\n\nEtiketa që korrespondon me kohëmatësin. Çdo kohëmatës duhet të ketë etiketën e tij unike.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Inicializua kohëmatësi...\n\nsignale.time();\n//=> ▶  timer_1  Inicializua kohëmatësi...\n\nsignale.time('etiketa');\n//=> ▶  etiketa    Inicializua kohëmatësi...\n```\n\n#### signale.`timeEnd([, label])`\n\n- Tipi i Kthimit: `Object`\n\nÇaktivizon kohëmatësin të cilit i korrespondon etiketa e dhënë. Nëse nuk jepet etiketë, kohëmatësi më i fundit, që u krijua pa dhënë etiketë, do të çaktivizohet.\n\nKthen një objekt `{label, span}` që përmban etiketën e kohëmatësit dhe kohën totale të ekzekutimit.\n\n##### **`label`**\n\n- Tipi: `String`\n\nEtiketa që korrespondon me kohëmatësin, çdo kohëmatës ka etiketën e tij unike.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Inicializua kohëmatësi...\n\nsignale.time();\n//=> ▶  timer_1  Inicializua kohëmatësi...\n\nsignale.time('etiketa');\n//=> ▶  etiketa    Inicializua kohëmatësi...\n\nsignale.timeEnd();\n//=> ◼  timer_1  Kohëmatësi funksionoi për: 2ms\n\nsignale.timeEnd();\n//=> ◼  timer_0  Kohëmatësi funksionoi për: 2ms\n\nsignale.timeEnd('etiketa');\n//=> ◼  etiketa    Kohëmatësi funksionoi për: 2ms\n```\n\n#### signale.`disable()`\n\nÇaktivizon funksionalitetin e regjistrimit të të gjithë regjistruesve që i përkasin një instance specifike.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n```\n\n#### signale.`enable()`\n\nAktivizon funksionalitetin e regjistrimit të të gjithë regjistruesve që i përkasin një instance specifike.\n\n```js\nconst signale = require('signale');\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.enable();\n\nsignale.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`isEnabled()`\n\nKontrollon nëse funksionaliteti i regjistrimit të një instance specifike është i aktivizuar.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.isEnabled();\n// => true\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.isEnabled();\n// => false\n```\n\n#### signale.`addSecrets(secrets)`\n\nShton sekrete/informacione të ndjeshme të reja në instancën e synuar Signale.\n\n##### **`secrets`**\n\n- Tipi: `(String|Number)[]`\n\nVarg që përmban sekretet/informacionin e ndjeshëm për t'u filtruar.\n\n```js\nconst signale = require('signale');\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n```\n\n#### signale.`clearSecrets()`\n\nHeq të gjitha sekretet/informacionin e ndjeshëm nga instanca e synuar Signale.\n\n```js\nconst signale = require('signale');\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n\nsignale.clearSecrets();\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n```\n\n## Zhvillimi\n\nPër më shumë informacion se si të kontribuoni në projekt, ju lutemi lexoni [udhëzimet e kontributit](https://github.com/klaudiosinani/signale/blob/master/contributing.md).\n\n- Bëni fork të repository dhe klonojeni në makinën tuaj\n- Navigoni në fork-un tuaj lokal: `cd signale`\n- Instaloni varësitë e projektit: `npm install` ose `yarn install`\n- Kontrolloni kodin për gabime: `npm test` ose `yarn test`\n\n## Të Lidhura\n\n- [qoa](https://github.com/klaudiosinani/qoa) - Porosi minimale interaktive të linjës së komandës\n- [taskbook](https://github.com/klaudiosinani/taskbook) - Detyra, panele dhe shënime për mjedisin e linjës së komandës\n- [hyperocean](https://github.com/klaudiosinani/hyperocean) - Temë e thellë blu oqeanike për terminalin Hyper\n\n## Kush e përdor?\n\n- [Boostnote](https://github.com/BoostIO/Boostnote)\n- [Docz](https://github.com/pedronauck/docz)\n- [Remix by Ethereum](https://github.com/ethereum/remix)\n- [Semantic Release](https://github.com/semantic-release/semantic-release)\n- [Shower](https://github.com/shower/shower)\n- [Taskbook](https://github.com/klaudiosinani/taskbook)\n- [Vant](https://github.com/youzan/vant)\n\nShikoni në detaj të gjitha paketat dhe repository që përdorin Signale [këtu](https://github.com/klaudiosinani/signale/network/dependents).\n\n## Ekipi\n\n- Klaudio Sinani [(@klaudiosinani)](https://github.com/klaudiosinani)\n- Mario Sinani [(@mariosinani)](https://github.com/mariosinani)\n\n## Sponsorët\n\nFalëminderit të madh të gjithë njerëzve dhe kompanive që mbështesin punën tonë të Kodit të Hapur:\n\n- [Better Stack: Zbulo, Zgjidh dhe Parandaloni Kohën e Pushimit.](https://betterstack.com/)\n\n## Licenca\n\n[MIT](https://github.com/klaudiosinani/signale/blob/master/license.md)\n"
  },
  {
    "path": "docs/readme.DE.md",
    "content": "<h1 align=\"center\">\n  Signale\n</h1>\n\n<h4 align=\"center\">\n  Hochgradig konfigurierbares Loggingprogramm\n</h4>\n\n<div align=\"center\">\n  <img alt=\"Header\" src=\"../media/header.png\" width=\"88%\">\n</div>\n\n<p align=\"center\">\n  <a href=\"https://travis-ci.com/klaudiosinani/signale\">\n    <img alt=\"Build Status\" src=\"https://travis-ci.com/klaudiosinani/signale.svg?branch=master\">\n  </a>\n  <a href=\"https://www.npmjs.com/package/signale\">\n    <img alt=\"NPM Downloads\" src=\"https://img.shields.io/npm/dt/signale.svg\">\n  </a>\n</p>\n\n## Beschreibung\n\nSignale ist bis ins letzte hack- und konfigurierbar. Es kann für Logging und Statusreports als auch für das Handling des Output Rendering Process von anderen Node Modulen und Anwendungen verwendet werden.\n\nDiese Dokument in [Albanian - Shqip](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md), [English](https://github.com/klaudiosinani/signale/blob/master/readme.md), [简体中文 - Simplified Chinese](https://github.com/klaudiosinani/signale/blob/master/docs/readme.zh_CN.md) lesen.\n\nLies die [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md#translating-documentation) um zu lernen, wie du dieses Dokument in mehr Sprachen übersetzen kannst.\n\n## Höhepunkte\n\n- 19 out-of-the-box loggers\n- durch und durch hackbar\n- sauberer, schöner Output\n- intergrierte Timer\n- benutzerdefinierte Logger\n- TypeScript Unterstützung\n- Interaktive und reguläre Modi\n- Geheimnisse & sensitives Filtern von Informationen\n- Unterstützung von Filename, Datum und timestamp \n- gezielte Logger und Timer\n- skaliert Loglevel\n- Unterstützugn von String interpolation\n- mehrere konfigurierbare beschreibbare Streams\n- einfache, minimalistische Syntax\n- Global konfigurierbar durch `package.json`\n- Konfiguration kann per File und Logger überschrieben werden\n\n## Inhalt\n\n- [Beschreibung](#beschreibung)\n- [Höhepunkte](#höhepunkte)\n- [Installation](#installation)\n- [Verwendung](#verwendung)\n- [Konfiguration](#konfiguration)\n- [API](#api)\n- [Development](#development)\n- [Related](#related)\n- [Wer verwendet es?](#wer-verwendet-es)\n- [Team](#team)\n- [License](#license)\n\n## Installation\n\n### Yarn\n\n```bash\nyarn add signale\n```\n\n### NPM\n\n```bash\nnpm install signale\n```\n\n## Verwendung\n\n### Default Loggers\n\nSignale importieren und einen der default Logger verwenden.\n\n\n<details>\n<summary>All verfügbaren Logger anzeigen.</summary>\n\n<br/>\n\n- `await`\n- `complete`\n- `error`\n- `debug`\n- `fatal`\n- `fav`\n- `info`\n- `note`\n- `pause`\n- `pending`\n- `star`\n- `start`\n- `success`\n- `wait`\n- `warn`\n- `watch`\n- `log`\n\n</details>\n\n<br/>\n\n```js\nconst signale = require('signale');\n\nsignale.success('Operation successful');\nsignale.debug('Hello', 'from', 'L59');\nsignale.pending('Write release notes for %s', '1.2.0');\nsignale.fatal(new Error('Unable to acquire lock'));\nsignale.watch('Recursively watching build directory...');\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"../media/default-loggers.png\" width=\"65%\">\n</div>\n\n### Benutzerdefinierte Logger\n\nUm einen benutzerdefinierten Logger zu erzeugen, wird ein `options` Objekt mit einem `types` field mit dem Logger definiert. Als argument wird eine neue Signale Instanz übergeben.\n\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  disabled: false,\n  interactive: false,\n  logLevel: 'info',\n  scope: 'custom',\n  secrets: [],\n  stream: process.stdout,\n  types: {\n    remind: {\n      badge: '**',\n      color: 'yellow',\n      label: 'reminder',\n      logLevel: 'info'\n    },\n    santa: {\n      badge: '🎅',\n      color: 'red',\n      label: 'santa',\n      logLevel: 'info'\n    }\n  }\n};\n\nconst custom = new Signale(options);\ncustom.remind('Improve documentation.');\ncustom.santa('Hoho! You have an unused variable on L45.');\n```\n\n<div align=\"center\">\n  <img alt=\"Custom Loggers\" src=\"../media/custom-loggers.png\" width=\"70%\">\n</div>\nEin Beispiel, wo die voreingestellten `error` und `success` Logger überschrieben werden.\n\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  types: {\n    error: {\n      badge: '!!',\n      label: 'fatal error'\n    },\n    success: {\n      badge: '++',\n      label: 'huge success'\n    }\n  }\n};\n\nconst signale = new Signale();\nsignale.error('Default Error Log');\nsignale.success('Default Success Log');\n\nconst custom = new Signale(options);\ncustom.error('Custom Error Log');\ncustom.success('Custom Success Log');\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"../media/override-defaults.png\" width=\"65%\">\n</div>\n\nDas `options` Objekt kann jedes der folgenden Attribute erhalten: `disabled`, `interactive`, `logLevel`, `secrets`, `stream`, `scope` und `types`. \n\n##### `disabled`\n\n- Type: `Boolean`\n- Default: `false`\n\nVerhindert das Logging aller Logger, die zur der Instanz gehören.\n\n##### `interactive`\n\n- Type: `Boolean`\n- Default: `false`\n\nSchaltet alle Logger, die zu der Instanz gehören, in den interaktiven Modus.\n\n##### `logLevel`\n\n- Type: `String`\n- Default: `'info'`\n\nSetzte den Loglevel der erstellten Instanz. Es kann einer der folgenden Level gewählt werden:\n\n- `'info'` - Zeigt alle Benachrichtigungen von allen Loggern.\n- `'timer'` -  Zeigt Benachrichtigungen von den `time`, `timeEnd`, `debug`, `warn`, `error` & `fatal` Loggern.\n- `'debug'` - Zeigt Benachrichtigungen von den `debug`, `warn`, `error` & `fatal` Loggern.\n- `'warn'` - Zeigt Benachrichtigungen von den `warn`, `error` & `fatal` Loggern.\n- `'error'` - Zeigt Benachrichtigungen von den `error` & `fatal` Loggern.\n\n##### `secrets`\n\n- Type: `(String|Number)[]`\n- Default: `[]`\n\nEin Array, in dem geheime/sensitive Informationen angegeben werden können. Diese werden vom Body und den Metadaten der Benachtichtigungen entfernt und mit dem voreingestellten `'[secure]'` String ersetzt.\n\n##### `stream`\n\n- Type: `stream.Writable|stream.Writable[]`\n- Default: `process.stdout`\n\nDie Daten werden in dieses Ziel geschrieben. Es kann ein einzelner, gültiger [Writable stream](https://nodejs.org/api/stream.html#stream_writable_streams) oder ein Array mit mehreren Writable streams sein.\n\n##### `scope`\n\n- Type: `String|String[]`\n\nName des Bereichs für den geloggt wird.\n\n##### `types`\n\n- Type: `Object`\n\nEnthält die Konfiguration der benutzerdefinierten und voreingestellten Logger.\n\nZusätzlich kann das configuration object von jedem Logger-Type, das in der `types` Option definiert wird, folgende Attibute erhalten: `badge`, `label`, `color`, `logLevel` & `stream`. \n\n##### `badge`\n\n- Type: `String`\n\nIcon, der zum Logger gehört.\n\n\n##### `label`\n\n- Type: `String`\n\nLabel, das verwendet wird, um den Typ des Loggers zu erkennen.\n\n##### `color`\n\n- Type: `String`\n\nFarbe des Labels. Kann eine der von [chalk](https://github.com/chalk/chalk#colors) unterstützten Farben sein.\n\n\n##### `logLevel`\n\n- Type: `String`\n- Default: `'info'`\n\nDas passende Loglevel für den Logger. Nachrichten vom Logger werden angezeigt, wenn der Loglevel größer oder gleich zum oben beschriebenen generellen Loglevel `logLevel` der `Signale` Instanz ist.\n\n### Zielgerichtete Logger\n\nUm einen neuen Logger für einen bestimmten Bereich zu erstellen, wird das `scope` Feld im `options` Objekt definiert und als Argument an die neue Signale Instanz übergeben.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  scope: 'global scope'\n};\n\nconst global = new Signale(options);\nglobal.success('Successful Operation');\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Vanilla\" src=\"../media/scope-vanilla.png\" width=\"65%\">\n</div>\n\nUm einen Logger für einen besteimmten Bereich, basierend auf einem bereits existierenden Logger, zu erstellen wird die `scope()` Funktion verwendet. Sie retourniert eine neue signale Instanz, die alle benutzerdefinierten Logger, Timer, Geheimnisse, Streams, Konfiguation, Loglevel, Interaktiven Modi und deaktivierten Stati erbt.\n\n```js\nconst signale = require('signale');\n\nconst global = signale.scope('global scope');\nglobal.success('Hello from the global scope');\n\nfunction foo() {\n  const outer = global.scope('outer', 'scope');\n  outer.success('Hello from the outer scope');\n  \n  setTimeout(() => {\n    const inner = outer.scope('inner', 'scope'); \n    inner.success('Hello from the inner scope');\n  }, 500);\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Existing\" src=\"../media/scope-existing.png\" width=\"65%\">\n</div>\n\n### Interaktive Loggers\n\nUm einen intaktiven Logger zu initialisieren, wird eine neue signale Instanz mit dem Wert `true` im [`interactive`](#interactive) Attribute erzeugt. Während man sich im interaktiven Modus befindet, werden zuvor geloggte Nachrichten von einem anderen interaktiven Logger von den neuen, die von dem gleichen oder einem neuen interaktiven Logger kommen, überschrieben. Reguläre Nachrichten von regulären Loggern werden von interaktiven nicht überschrieben.\n\n```js\nconst {Signale} = require('signale');\n\nconst interactive = new Signale({interactive: true, scope: 'interactive'});\n\ninteractive.await('[%d/4] - Process A', 1);\n\nsetTimeout(() => {\n  interactive.success('[%d/4] - Process A', 2);\n  setTimeout(() => {\n    interactive.await('[%d/4] - Process B', 3);\n    setTimeout(() => {\n      interactive.error('[%d/4] - Process B', 4);\n      setTimeout(() => {}, 1000);\n    }, 1000);\n  }, 1000);\n}, 1000);\n```\n\n<div align=\"center\">\n  <img alt=\"Interactive Mode\" src=\"../media/interactive-mode.gif\" width=\"65%\">\n</div>\n\n### Writable Streams\n\nStandardmäßig loggen alle Signale Instanzen die Nachrichten in den `process.stdout` stream. Der Ziel-Stream kann durch die [`stream`](#stream) property angepasst werden. Hier kann ein einzelner oder mehrere gütlige Writable streams angegeben werden, welche dann von allen Loggertypen verwendet werden. Zusätzlich ist es möglich einen oder mehrere Wirtable Streams exklusiv für einen spezifischen Loggertypen zu definieren - also Daten unabhängig von den restlichen Loggertypen zu schreiben.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  stream: process.stderr, // All loggers will now write to `process.stderr`\n  types: {\n    error: {\n      // Only `error` will write to both `process.stdout` & `process.stderr`\n      stream: [process.stdout, process.stderr]\n    }\n  }\n};\n\nconst signale = new Signale(options);\nsignale.success('Message will appear on `process.stderr`');\nsignale.error('Message will appear on both `process.stdout` & `process.stderr`');\n```\n\n<div align=\"center\">\n  <img alt=\"Writable Streams\" src=\"../media/writable-streams.png\" width=\"73%\">\n</div>\n\n### Secrets Filtering\n\nDurch das Verwenden der `secrets` Option werden geheime/sensitive Informationen, wie Scopenamen,  aus den Nachrichten (Body und Metadaten) herausgefiltert. Diese Option ist Teil des configuration-Objects, dass einer `Signale`-Instanz oder Initialisierung übergeben wird und hat den Typ `Array<String|Number>`. Das Array kann mehrere Geheimnisse enthalten. Alle werden, wenn sie vorkommen, entfernt und durch den standardmäßigen `'[secure]'` string ersetzt. Wenn die unäre `signale.scope(name)` Funktion verwendet wird, dann erbt die erzeugte `Signale` Instanz alle Geheimnisse des Parents. Die Geheimnisse werden **case-sensitive** überprüft. Die unäre [`signale.addSecrets()`](https://github.com/klaudiosinani/signale#signaleaddsecretssecrets) und die nullstellige [`signale.clearSecrets()`](https://github.com/klaudiosinani/signale#signaleclearsecrets) Funktion sind über die API verfügbar um die Geheimnisse hinzuzufügen/zu löschen.\n\nEs ist **entscheidende** und **stark befürwortete** Praxis, sensitive Informationen **nicht direkt im Quellcode zu speichern**. Das Beispiel ist **alleinig** zur die Demonstration gedacht:\n\n```js\nconst {Signale} = require('signale');\n\n// In reality secrets could be securely fetched/decrypted through a dedicated API \nconst [USERNAME, TOKEN] = ['klaudiosinani', 'token'];\n\nconst logger1 = new Signale({\n  secrets: [USERNAME, TOKEN]\n});\n\nlogger1.log('$ exporting USERNAME=%s', USERNAME);\nlogger1.log('$ exporting TOKEN=%s', TOKEN);\n\n// `logger2` inherits all secrets from its parent `logger1`\nconst logger2 = logger1.scope('parent');\n\nlogger2.log('$ exporting USERNAME=%s', USERNAME);\nlogger2.log('$ exporting TOKEN=%s', TOKEN);\n```\n\n<div align=\"center\">\n  <img alt=\"Secrets Filtering\" src=\"../media/filter-secrets.png\" width=\"73%\">\n</div>\n\n### Timers\n\nTimer werden von den `time()` und `timeEnd()`  Funktionen verwaltet. Zur Identifikation eines Timers oder einer Initialisierung kann ein einzigartiges Label vewrendet werden. Wenn keines bereitgestellt wird, dann wird eines automatisch generiert. Wenn die `timeEnd()` Funktion ohne ein Label aufgerufen wird, dann wird der als letztes initialisierte Timer terminiert, der ohne Label erstellt wurde.\n\n```js\nconst signale = require('signale');\n\nsignale.time('test');\nsignale.time();\nsignale.time();\n\nsetTimeout(() => {\n  signale.timeEnd();\n  signale.timeEnd();\n  signale.timeEnd('test');\n}, 500);\n```\n\n<div align=\"center\">\n  <img alt=\"Timers\" src=\"../media/timers.png\" width=\"60%\">\n</div>\n\n## Konfiguration\n\n### Global\n\nUm die gloabel Konfiguration zu ermöglichen, müssen die Optionen unter dem`signale` namespace im `package.json` defniert werden.\n\nDas folgende Beispiel zeigt alle verfügbaren Optionen mit den zugehörigen voreingestellten Werten.\n\n```json\n{\n  \"signale\": {\n    \"displayScope\": true,\n    \"displayBadge\": true,\n    \"displayDate\": false,\n    \"displayFilename\": false,\n    \"displayLabel\": true,\n    \"displayTimestamp\": false,\n    \"underlineLabel\": true,\n    \"underlineMessage\": false,\n    \"underlinePrefix\": false,\n    \"underlineSuffix\": false,\n    \"uppercaseLabel\": false\n  }\n}\n```\n\n<details>\n<summary>Alle verfügbaren Optionen im Detail ansehen.</summary>\n\n##### `displayScope`\n\n- Type: `Boolean`\n- Default: `true`\n\nZeigt den Bereichsnamen des Loggers.\n\n##### `displayBadge`\n\n- Type: `Boolean`\n- Default: `true`\n\nZeigt den Badge des Loggers.\n\n##### `displayDate`\n\n- Type: `Boolean`\n- Default: `false`\n\nZeugt das aktuelle lokale Datum im `YYYY-MM-DD` Format. \n\n##### `displayFilename`\n\n- Type: `Boolean`\n- Default: `false`\n\nZeigt den Dateinamen vom File, für das der Logger loggt.\n\n##### `displayLabel`\n\n- Type: `Boolean`\n- Default: `true`\n\nZeigt das Label des Loggers.\n\n##### `displayTimestamp`\n\n- Type: `Boolean`\n- Default: `false`\n\nZeigt die lokale Zeit im `HH:MM:SS` Format.\n\n##### `underlineLabel`\n\n- Type: `Boolean`\n- Default: `true`\n\nUnterstreicht das Logger-Label.\n\n##### `underlineMessage`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnterstreicht die Logger Nachricht.\n\n##### `underlinePrefix`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnterstreicht die Logger Prefix.\n\n##### `underlineSuffix`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnterstreicht die Logger Suffix.\n\n##### `uppercaseLabel`\n\n- Type: `Boolean`\n- Default: `false`\n\nZeigt das Label des Loggers in Großbuchstaben.\n\n</details>\n\n### Local\n\nUm die lokale Konfiguration zu ermöglichen muss die `config()` Funktion der Signale Instanz aufgerufen werden. Lokale Konfigurationen überschreiben immer die geerbte Konfiguration von `package.json`.\n\nDas folgende Beispiel zeigt wie Logger in der `foo.js`-Datei unter einer eigenen Konfiguation laufen, die die `package.json`-Konfiguration überschreibt.\n\n```js\n// foo.js\nconst signale = require('signale');\n\n// Overrides any existing `package.json` config\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n}); \n\nsignale.success('Hello from the Global scope');\n```\n\n<div align=\"center\">\n  <img alt=\"Local Config\" src=\"../media/local-config.png\" width=\"65%\">\n</div>\n\nLogger für bestimmte Bereiche können eine unabhängige, eigene Konfiguration erhalten, die die vom Parent oder vom `package.json` vererbte Konfiguation überschreibt.\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n});\n\nsignale.success('Hello from the Global scope');\n\nfunction foo() {\n  // `fooLogger` inherits the config of `signale`\n  const fooLogger = signale.scope('foo scope');\n\n  // Overrides both `signale` and `package.json` configs\n  fooLogger.config({\n    displayFilename: true,\n    displayTimestamp: false,\n    displayDate: true\n  });\n\n  fooLogger.success('Hello from the Local scope');\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Config\" src=\"../media/scope-config.png\" width=\"65%\">\n</div>\n\n## API\n\n#### signale.`<logger>(message[, message]|messageObj|errorObj)`\n\n##### **`logger`**\n\n- Type: `Function`\n\nKann jeder vereingestellte oder benutzerdefinierte Logger sein.\n\n##### **`message`**\n\n- Type: `String`\n\nKann ein oder mehrere durch Kommas getrennte Strings sein.\n\n```js\nconst signale = require('signale');\n\nsignale.success('Successful operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful', 'operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful %s', 'operation');\n//=> ✔  success  Successful operation\n```\n\n##### **`errorObj`**\n\n- Type: `Error Object`\n\nKann jedes Error Objekt sein.\n\n```js\nconst signale = require('signale');\n\nsignale.error(new Error('Unsuccessful operation'));\n//=> ✖  error  Error: Unsuccessful operation\n//        at Module._compile (module.js:660:30)\n//        at Object.Module._extensions..js (module.js:671:10)\n//        ...\n```\n\n##### **`messageObj`**\n\n- Type: `Object`\n\nKann jedes Objet sein, dass die Attribute `prefix`, `message` und `suffix` enthält, wobei `prefix` und `suffix` immer vor bzw. nach der `message` eingefügt werden.\n\n```js\nconst signale = require('signale');\n\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n\nsignale.complete({prefix: '[task]', message: ['Fix issue #%d', 59], suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n```\n\n#### signale.`scope(name[, name])`\n\nDefiniert den Namen des Loggers.\n\n##### **`name`**\n\n- Type: `String`\n\nKann ein oder mehrere durch Kommas getrennte Strings sein.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \nconst fooBar = signale.scope('foo', 'bar');\n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfooBar.success('foo bar');\n//=> [foo] [bar] › ✔  success  foo bar\n```\n\n#### signale.`unscope()`\n\nLöscht den Bereichsnamen des Loggers.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfoo.unscope();\n\nfoo.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`config(settingsObj)`\n\nDie Konfiguration der Instanz wird gesestzt und überschreibt die existierende lokale oder globale Konfiguration.\n\n##### **`settingsObj`**\n\n- Type: `Object`\n\nKann jede der dokumentierten [options](#global) enthalten.\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: true\n});\n\nsignale.success('Successful operations');\n//=> [2018-5-15] [11:12:38] [foo.js] › ✔  success  Successful operations\n```\n\n#### signale.`time([, label])`\n\n- Return Type: `String`\n\nSetzt einen Timer und aktzeptiert ein optionales Label. Wenn kein Label übergeben wird, dann erhält der Timer automatisch eines.\n\nRetourniert einen String, der das Timerlabel repräsentiert.\n\n##### **`label`**\n\n- Type: `String`\n\nLabel, dass zum Timer gehört. Jeder Timer braucht ein einzigartiges Label.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n```\n\n#### signale.`timeEnd([, label])`\n\n- Return Type: `Object`\n\nDeaktiviert den Timer, der zu dem Label gehört. Wenn kein Label angegeben wird, dann wird der letzte Timer, der ohne Label erzeugt wurde, deaktiviert.\n\nRetourniert ein Objekt `{label, span}`, welches das Label und die Laufzeit enthält.\n\n##### **`label`**\n\n- Type: `String`\n\nLabel, dass zu dem Timer gehört. Jeder Timer hat ein einzigartiges label.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n\nsignale.timeEnd();\n//=> ◼  timer_1  Timer run for: 2ms\n\nsignale.timeEnd();\n//=> ◼  timer_0  Timer run for: 2ms\n\nsignale.timeEnd('label');\n//=> ◼  label    Timer run for: 2ms\n```\n\n#### signale.`disable()`\n\nDeaktiviert das Logging für alle Logger die zu einer spezifischen Instanz gehören.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n```\n\n#### signale.`enable()`\n\nAktiviert das Logging für alle Logger die zu einer spezifischen Instanz gehören.\n```js\nconst signale = require('signale');\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.enable();\n\nsignale.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`isEnabled()`\n\nÜberprüft, ob Logging für die spezifische Instanz aktiviert ist.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.isEnabled();\n// => true\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.isEnabled();\n// => false\n```\n\n#### signale.`addSecrets(secrets)`\n\nFügt neue geheime/sensitive Informatioen hinzu.\n\n##### **`secrets`**\n\n- Type: `(String|Number)[]`\n\nArray, dass die geheime/sensitive Information enthält, die herausgefiltert werden soll.\n\n```js\nconst signale = require('signale');\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n```\n\n#### signale.`clearSecrets()`\n\nEntfernt alle geheimen/sensitiven Informationen der spezifischen Signale Instanz.\n\n```js\nconst signale = require('signale');\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n\nsignale.clearSecrets();\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n```\n\n## Development\n\nMehr Informationen im Bezug auf Beiträge zum Projekt finden sich in den [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md).\n\n- Das Repository forken und auf deine Maschine klonen\n- Zum lokalen Fork navigieren: `cd signale`\n- Die dependencies installieren: `npm install` oder `yarn install`\n- Den Code für Fehler linten: `npm test` or `yarn test`\n## Related\n\n- [qoa](https://github.com/klaudiosinani/qoa) - Minimal interactive command-line prompts\n- [taskbook](https://github.com/klaudiosinani/taskbook) - Tasks, boards & notes for the command-line habitat\n- [hyperocean](https://github.com/klaudiosinani/hyperocean) - Deep oceanic blue Hyper terminal theme\n\n## Who's Using It?\n\n- [Boostnote](https://github.com/BoostIO/Boostnote)\n- [Docz](https://github.com/pedronauck/docz)\n- [Remix by Ethereum](https://github.com/ethereum/remix)\n- [Semantic Release](https://github.com/semantic-release/semantic-release)\n- [Shower](https://github.com/shower/shower)\n- [Taskbook](https://github.com/klaudiosinani/taskbook)\n- [Vant](https://github.com/youzan/vant)\n\nRepositories, die Signale verwenden im Detail ansehen: [hier](https://github.com/klaudiosinani/signale/network/dependents).\n\n## Team\n\n- Klaudio Sinani [(@klaudiosinani)](https://github.com/klaudiosinani)\n- Mario Sinani [(@mariosinani)](https://github.com/mariosinani)\n\n## License\n\n[MIT](https://github.com/klaudiosinani/signale/blob/master/license.md)\n"
  },
  {
    "path": "docs/readme.md",
    "content": "## Signale Translated Documentation\n\n- [Albanian - Shqip](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md) by [@klaudiosinani](https://github.com/klaudiosinani)\n- [简体中文 - Simplified Chinese](https://github.com/klaudiosinani/signale/blob/master/docs/readme.zh_CN.md) by [@hardo](https://github.com/hardo)\n- [German - Deutsch](https://github.com/klaudiosinani/signale/blob/master/docs/readme.DE.md) by [@villabunterkunt](https://github.com/villabunterkunt)\n\n## Contributing\n\nVisit the [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md#translating-documentation) to learn more on how to get involved in the translating process.\n\n## Thanks\n\nTons of thank you to the amazing people that help out with the creation and maintenance of the translations, your contributions make Signale available to everyone around the world!\n\n"
  },
  {
    "path": "docs/readme.zh_CN.md",
    "content": "<h1 align=\"center\">\n  Signale\n</h1>\n\n<h4 align=\"center\">\n  👋 可扩展的日志记录器\n</h4>\n\n<div align=\"center\">\n  <img alt=\"Header\" src=\"../media/header.png\" width=\"88%\">\n</div>\n\n<p align=\"center\">\n  <a href=\"https://travis-ci.org/klaudiosinani/signale\">\n    <img alt=\"Build Status\" src=\"https://travis-ci.com/klaudiosinani/signale.svg?branch=master\">\n  </a>\n</p>\n\n## 描述\n\nSignale 的核心是可扩展和可配置的，可将其用于日志记录、状态报告以及处理其他 Node 模块和应用的输出渲染方式。\n\n您可以使用以下语言阅读本文档 [Albanian - Shqip](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md), [English](https://github.com/klaudiosinani/signale/blob/master/readme.md), [German - Deutsch](https://github.com/klaudiosinani/signale/blob/master/docs/readme.DE.md).\n\n浏览 [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md#translating-documentation) 以了解如何将该文档翻译成其他语言。\n\n## 亮点\n\n- 16个开箱即用的记录器\n- 可扩展的核心\n- 简洁漂亮的输出\n- 集成了计时器\n- 自定义可插拔记录器\n- 交互模式和常规模式\n- 文件名，日期和时间戳支持\n- 局部记录器和计时器\n- 字符串插值支持\n- 多个可配置的输出流\n- 简单且简洁的语法\n- 可通过 `package.json` 进行全局配置\n- 可覆盖每个文件和记录器的配置\n\n## 目录\n\n- [描述](#描述)\n- [亮点](#亮点)\n- [安装](#安装)\n- [使用](#使用)\n- [配置](#配置)\n- [API](#api)\n- [开发](#开发)\n- [相关项目](#相关项目)\n- [团队](#团队)\n- [许可](#许可)\n\n## 安装\n\n```bash\nnpm install signale\n```\n\n## 使用\n\n### 默认记录器\n\n导入 signale 即可开始用任意的默认记录器。\n\n<details>\n<summary>查看所有可用的默认记录器。</summary>\n\n<br/>\n\n- `await`\n- `complete`\n- `error`\n- `debug`\n- `fatal`\n- `fav`\n- `info`\n- `note`\n- `pause`\n- `pending`\n- `star`\n- `start`\n- `success`\n- `warn`\n- `watch`\n- `log`\n\n</details>\n\n<br/>\n\n```js\nconst signale = require('signale');\n\nsignale.success('Operation successful');\nsignale.debug('Hello', 'from', 'L59');\nsignale.pending('Write release notes for %s', '1.2.0');\nsignale.fatal(new Error('Unable to acquire lock'));\nsignale.watch('Recursively watching build directory...');\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"../media/default-loggers.png\" width=\"65%\">\n</div>\n\n### 自定义记录器 \n\n要创建自定义记录器，先定义一个 `options` 对象，在其 `types` 属性中填入记录器相关数据，然后将该对象作为参数传递给新的 signale 实例。\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  disabled: false,\n  interactive: false,\n  stream: process.stdout,\n  scope: 'custom',\n  types: {\n    remind: {\n      badge: '**',\n      color: 'yellow',\n      label: 'reminder'\n    },\n    santa: {\n      badge: '🎅',\n      color: 'red',\n      label: 'santa'\n    }\n  }\n};\n\nconst custom = new Signale(options);\ncustom.remind('Improve documentation.');\ncustom.santa('Hoho! You have an unused variable on L45.');\n```\n\n<div align=\"center\">\n  <img alt=\"Custom Loggers\" src=\"../media/custom-loggers.png\" width=\"70%\">\n</div>\n\n下面是一个覆盖默认记录器 `error` 和 `success` 的例子\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  types: {\n    error: {\n      badge: '!!',\n      label: 'fatal error'\n    },\n    success: {\n      badge: '++',\n      label: 'huge success'\n    }\n  }\n};\n\nconst signale = new Signale();\nsignale.error('Default Error Log');\nsignale.success('Default Success Log');\n\nconst custom = new Signale(options);\ncustom.error('Custom Error Log');\ncustom.success('Custom Success Log');\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"../media/override-defaults.png\" width=\"65%\">\n</div>\n\n`options` 对象可以包含以下任何属性： `disabled`, `interactive`, `stream`, `scope` and `types`. \n\n##### `disabled`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n禁用所创建实例的所有日志记录功能。\n\n##### `interactive`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n将所创建实例的所有记录器切换到交互模式\n\n##### `stream`\n\n- 类型: `Writable stream` (输出流) 或 `Array of Writable streams` (包含输出流的数组)\n- 默认: `process.stdout`\n\n写入数据的目标可以是单个有效的 [输出流(Writable stream)](https://nodejs.org/api/stream.html#stream_writable_streams) 或包含多个有效输出流的数组。\n\n##### `scope`\n\n- 类型: `String` 或 `Array of Strings`\n\n记录器的作用域名称。\n\n##### `types`\n\n- 类型: `Object`\n\n持有自定义记录器和默认记录器的配置。\n\n##### `badge`\n\n- 类型: `String`\n\n与记录器对应的徽章图标。\n\n##### `label`\n\n- 类型: `String`\n\n用于标识记录器类型的标签。\n\n##### `color`\n\n- 类型: `String`\n\n标签的颜色，可以是 [chalk](https://github.com/chalk/chalk#colors) 支持的任何前景色。\n\n### 局部记录器\n\n要从头创建局部记录器，需在 `options` 对象的 `scope` 属性中定义作用域名，然后将其作为一个参数传递给新的 signale 实例。\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  scope: 'global scope'\n};\n\nconst global = new Signale(options);\nglobal.success('Successful Operation');\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Vanilla\" src=\"../media/scope-vanilla.png\" width=\"65%\">\n</div>\n\n可以使用 `scope()` 函数基于现有的记录器创建局部记录器，该函数将返回新的signale实例，该实例继承已有实例的所有自定义记录器、计时器、流、配置、禁用状态和交互模式信息。\n\n```js\nconst signale = require('signale');\n\nconst global = signale.scope('global scope');\nglobal.success('Hello from the global scope');\n\nfunction foo() {\n  const outer = global.scope('outer', 'scope');\n  outer.success('Hello from the outer scope');\n  \n  setTimeout(() => {\n    const inner = outer.scope('inner', 'scope'); \n    inner.success('Hello from the inner scope');\n  }, 500);\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Existing\" src=\"../media/scope-existing.png\" width=\"65%\">\n</div>\n\n### 交互式记录器 \n\n要初始化交互式记录器，请创建一个新的 signale 实例，并将 [`interactive`](#interactive) 属性设置为 `true`。 进入交互模式时，之前来自交互式记录器的消息，会被后面来自相同实例中相同或不同的记录器的消息所覆盖。 请注意来自常规记录器的常规消息不会被交互式记录器覆盖。\n\n```js\nconst {Signale} = require('signale');\n\nconst interactive = new Signale({interactive: true, scope: 'interactive'});\n\ninteractive.await('[%d/4] - Process A', 1);\n\nsetTimeout(() => {\n  interactive.success('[%d/4] - Process A', 2);\n  setTimeout(() => {\n    interactive.await('[%d/4] - Process B', 3);\n    setTimeout(() => {\n      interactive.error('[%d/4] - Process B', 4);\n      setTimeout(() => {}, 1000);\n    }, 1000);\n  }, 1000);\n}, 1000);\n```\n\n<div align=\"center\">\n  <img alt=\"Interactive Mode\" src=\"../media/interactive-mode.gif\" width=\"65%\">\n</div>\n\n\n### 输出流\n\n默认情况下，所有 signale 实例都将其消息记录到 `process.stdout` 输出流。 可以通过 stream 属性进行修改以匹配您自己的选项，你可以在其中定义单个或多个有效的输出流，所有类型的记录器都将使用这些流来记录您的数据。 此外，可以专门为特定记录器类型定义一个或多个可写流，从而独立于其余记录器类型写入数据。\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  stream: process.stderr, // 所有的记录器现在都会将数据写入 `process.stderr`\n  types: {\n    error: {\n      // 只有 `error` 记录器会将数据同时写入 `process.stdout` 和 `process.stderr`\n      stream: [process.stdout, process.stderr]\n    }\n  }\n};\n\nconst signale = new Signale(options);\nsignale.success('Message will appear on `process.stderr`');\nsignale.error('Message will appear on both `process.stdout` & `process.stderr`');\n```\n\n<div align=\"center\">\n  <img alt=\"Writable Streams\" src=\"../media/writable-streams.png\" width=\"73%\">\n</div>\n\n### 计时器\n\n计时器由 `time()` 和 `timeEnd()` 函数管理。 可以使用标签在初始化时唯一标识一个计时器，如果没有提供则计时器将自动分配一个。 此外，调用没有指定标签的 `timeEnd()` 函数将终止最近一个初始化时没有指定标签的计时器。\n\n```js\nconst signale = require('signale');\n\nsignale.time('test');\nsignale.time();\nsignale.time();\n\nsetTimeout(() => {\n  signale.timeEnd();\n  signale.timeEnd();\n  signale.timeEnd('test');\n}, 500);\n```\n\n<div align=\"center\">\n  <img alt=\"Timers\" src=\"../media/timers.png\" width=\"60%\">\n</div>\n\n## 配置\n\n### 全局\n\n在 `package.json` 中的 `signale` 命名空间下定义选项以启用全局配置。\n\n以下说明了所有可用选项及其各自的默认值。\n\n```json\n{\n  \"signale\": {\n    \"coloredInterpolation\": false,\n    \"displayScope\": true,\n    \"displayBadge\": true,\n    \"displayDate\": false,\n    \"displayFilename\": false,\n    \"displayLabel\": true,\n    \"displayTimestamp\": false,\n    \"underlineLabel\": true,\n    \"underlineMessage\": false,\n    \"underlinePrefix\": false,\n    \"underlineSuffix\": false,\n    \"uppercaseLabel\": false\n  }\n}\n```\n\n<details>\n<summary>浏览所有可用选项的详细信息。</summary>\n\n##### `coloredInterpolation`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n以彩色的方式显示用于替换字符串插值上的占位符标记参数。\n\n##### `displayScope`\n\n- 类型: `Boolean`\n- 默认值: `true`\n\n显示记录器的作用域名称。\n\n##### `displayBadge`\n\n- 类型: `Boolean`\n- 默认值: `true`\n\n显示记录器的徽章图标。\n\n##### `displayDate`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n以 `YYYY-MM-DD` 的格式显示当前本地日期。\n\n##### `displayFilename`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n显示记录器消息来源的文件名。\n\n##### `displayLabel`\n\n- 类型: `Boolean`\n- 默认值: `true`\n\n显示记录器的标签。\n\n##### `displayTimestamp`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n以 `HH:MM:SS` 的格式显示当前本地时间。\n\n##### `underlineLabel`\n\n- 类型: `Boolean`\n- 默认值: `true`\n\n给记录器的标签添加下划线。\n\n##### `underlineMessage`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n给记录器的消息内容添加下划线。\n\n##### `underlinePrefix`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n给记录器的前缀添加下划线。\n\n##### `underlineSuffix`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n给记录器的后缀添加下划线。\n\n##### `uppercaseLabel`\n\n- 类型: `Boolean`\n- 默认值: `false`\n\n以大写的方式显示记录器的标签。\n\n</details>\n\n### 本地\n\n要启用本地配置，请在您的 signale 实例上调用 `config()` 函数。本地配置将始终覆盖从 `package.json` 继承的任何预先存在的配置。\n\n在以下示例中， `foo.js` 文件中的记录器将在其自己的配置下运行，从而覆盖 `package.json` 文件中的配置。\n\n```js\n// foo.js\nconst signale = require('signale');\n\n// 覆盖任何存在于 `package.json` 的配置\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n}); \n\nsignale.success('Hello from the Global scope');\n```\n\n<div align=\"center\">\n  <img alt=\"Local Config\" src=\"../media/local-config.png\" width=\"65%\">\n</div>\n\n此外，局部记录器可以拥有自己的独立配置，以覆盖父实例或继承自 `package.json` 的配置。\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n});\n\nsignale.success('Hello from the Global scope');\n\nfunction foo() {\n  // `fooLogger` 继承了 `signale` 的配置\n  const fooLogger = signale.scope('foo scope');\n\n  // 同时覆盖 `signale` 和 `package.json` 的配置\n  fooLogger.config({\n    displayFilename: true,\n    displayTimestamp: false,\n    displayDate: true\n  });\n\n  fooLogger.success('Hello from the Local scope');\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Config\" src=\"../media/scope-config.png\" width=\"65%\">\n</div>\n\n## API\n\n#### signale.`<logger>(message[, message]|messageObj|errorObj)`\n\n##### **`logger`**\n\n- 类型: `Function`\n\n可以是任何默认或自定义记录器。\n\n##### **`message`**\n\n- 类型: `String`\n\n可以是一个或多个逗号分隔的字符串。\n\n```js\nconst signale = require('signale');\n\nsignale.success('Successful operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful', 'operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful %s', 'operation');\n//=> ✔  success  Successful operation\n```\n\n##### **`errorObj`**\n\n- 类型: `Error Object`\n\n可以是任意错误 (error) 对象。\n\n```js\nconst signale = require('signale');\n\nsignale.error(new Error('Unsuccessful operation'));\n//=> ✖  error  Error: Unsuccessful operation\n//        at Module._compile (module.js:660:30)\n//        at Object.Module._extensions..js (module.js:671:10)\n//        ...\n```\n\n##### **`messageObj`**\n\n- 类型: `Object`\n\n可以是包含 `prefix` 、 `message` 和 `suffix` 属性的对象，`prefix` (前缀)和 `suffix` (后缀) 始终预先添加并附加到记录的 `message` (消息)里。\n\n```js\nconst signale = require('signale');\n\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n\nsignale.complete({prefix: '[task]', message: ['Fix issue #%d', 59], suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n```\n\n#### signale.`scope(name[, name])`\n\n定义记录器的作用域名称。\n\n##### **`name`**\n\n- 类型: `String`\n\n可以是一个或多个用逗号分隔的字符串。\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \nconst fooBar = signale.scope('foo', 'bar');\n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfooBar.success('foo bar');\n//=> [foo] [bar] › ✔  success  foo bar\n```\n\n#### signale.`unscope()`\n\n清除记录器的作用域名称。\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfoo.unscope();\n\nfoo.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`config(settingsObj)`\n\n设置实例的配置项以覆盖任意已存在的全局或本地配置。\n\n##### **`settingsObj`**\n\n- 类型: `Object`\n\n可以持有任意[配置选项](#全局)。\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: true\n});\n\nsignale.success('Successful operations');\n//=> [2018-5-15] [11:12:38] [foo.js] › ✔  success  Successful operations\n```\n\n#### signale.`time([, label])`\n\n- 返回类型: `String`\n\n激活一个计时器并接受一个可选的标签。如果没有提供参数，计时器将自动生成一个唯一的标签。\n\n返回与计时器标签相对应的字符串。\n\n##### **`label`**\n\n- 类型: `String`\n\n与计时器对应的标签。每个计时器必须有自己独有的标签。\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n```\n\n#### signale.`timeEnd([, label])`\n\n- 返回类型: `Object`\n\n取消激活给定标签对应的计时器。如果未提供标签，则将取消激活在未提供标签的情况下创建的最新的计时器。\n\n返回一个 `{label, span}` 对象，该对象持有计时器的标签与总共运行时间。\n\n##### **`label`**\n\n- 类型: `String`\n\n与计时器对应的标签。每个计时器必须有自己独有的标签。\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n\nsignale.timeEnd();\n//=> ◼  timer_1  Timer run for: 2ms\n\nsignale.timeEnd();\n//=> ◼  timer_0  Timer run for: 2ms\n\nsignale.timeEnd('label');\n//=> ◼  label    Timer run for: 2ms\n```\n\n#### signale.`disable()`\n\n禁用特定实例包含的所有记录器的记录功能。\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n```\n\n#### signale.`enable()`\n\n启用特定实例包含的所有记录器的记录功能。\n\n```js\nconst signale = require('signale');\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.enable();\n\nsignale.success('foo');\n//=> ✔  success  foo\n```\n\n## 开发\n\n想知道如何参与到该项目的更多信息, 请阅读 [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md) 。\n\n- Fork 该仓库并 clone 到你的本地机器上\n- 进入你的本地仓库: `cd signale`\n- 安装项目依赖: `npm install` or `yarn install`\n- 测试代码: `npm test` or `yarn test`\n\n## 相关项目\n\n- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right\n- [figures](https://github.com/sindresorhus/figures) - Unicode symbols\n\n## 团队\n\n- Klaudio Sinani [(@klaudiosinani)](https://github.com/klaudiosinani)\n\n## 许可\n\n[MIT](https://github.com/klaudiosinani/signale/blob/master/license.md)\n"
  },
  {
    "path": "index.js",
    "content": "'use strict';\nconst Signale = require('./src/signale');\n\nmodule.exports = Object.assign(new Signale(), {Signale});\n"
  },
  {
    "path": "license.md",
    "content": "MIT License\n\nCopyright (c) 2018 - present Klaudio Sinani <klaudiosinani@protonmail.ch>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"signale\",\n  \"version\": \"1.4.0\",\n  \"description\": \"Highly configurable logging utility\",\n  \"license\": \"MIT\",\n  \"repository\": \"klaudiosinani/signale\",\n  \"author\": {\n    \"name\": \"Klaudio Sinani\",\n    \"email\": \"klaudiosinani@protonmail.ch\",\n    \"url\": \"https://klaudiosinani.com\"\n  },\n  \"maintainers\": [\n    {\n      \"name\": \"Mario Sinani\",\n      \"email\": \"mariosinani@protonmail.ch\",\n      \"url\": \"https://mariocfhq.github.io\"\n    }\n  ],\n  \"engines\": {\n    \"node\": \">=6\"\n  },\n  \"files\": [\n    \"src\",\n    \"types\",\n    \"index.js\"\n  ],\n  \"types\": \"./types/signale.d.ts\",\n  \"keywords\": [\n    \"log\",\n    \"cli\",\n    \"logger\",\n    \"logging\",\n    \"hackable\",\n    \"colorful\",\n    \"console\"\n  ],\n  \"scripts\": {\n    \"lint\": \"xo\",\n    \"test:ts\": \"tsc --noEmit -p test\",\n    \"test\": \"npm run lint && npm run test:ts\"\n  },\n  \"dependencies\": {\n    \"chalk\": \"^2.3.2\",\n    \"figures\": \"^2.0.0\",\n    \"pkg-conf\": \"^2.1.0\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^11.11.3\",\n    \"typescript\": \"^3.3.3333\",\n    \"xo\": \"*\"\n  },\n  \"options\": {\n    \"default\": {\n      \"displayScope\": true,\n      \"displayBadge\": true,\n      \"displayDate\": false,\n      \"displayFilename\": false,\n      \"displayLabel\": true,\n      \"displayTimestamp\": false,\n      \"underlineLabel\": true,\n      \"underlineMessage\": false,\n      \"underlinePrefix\": false,\n      \"underlineSuffix\": false,\n      \"uppercaseLabel\": false\n    }\n  },\n  \"xo\": {\n    \"space\": 2\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "<h1 align=\"center\">\n  Signale\n</h1>\n\n<h4 align=\"center\">\n  Highly configurable logging library\n</h4>\n\n<div align=\"center\">\n  <img alt=\"Header\" src=\"media/header.png\" width=\"88%\">\n</div>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/signale\">\n    <img alt=\"NPM Downloads\" src=\"https://img.shields.io/npm/dt/signale.svg\">\n  </a>\n</p>\n\n<div align=\"center\">\n  <br>\n  <sup><b>Sponsored by:</b></sup>\n  <br>\n  <a href=\"https://betterstack.com\">\n    <div>\n      <img src=\"https://github.com/Seldaek/monolog/assets/183678/7de58ce0-2fa2-45c0-b3e8-e60cebb3c4cf\" width=\"200\" alt=\"Better Stack\">\n    </div>\n    <sup>\n      Spot, Resolve, and Prevent Downtime.\n    </sup>\n  </a>\n</div>\n\n## Description\n\nHackable and configurable to the core, signale can be used for logging purposes, status reporting, as well as for handling the output rendering process of other node modules and applications.\n\nRead this document in: [Albanian - Shqip](https://github.com/klaudiosinani/signale/blob/master/docs/readme.AL.md), [简体中文 - Simplified Chinese](https://github.com/klaudiosinani/signale/blob/master/docs/readme.zh_CN.md), [German - Deutsch](https://github.com/klaudiosinani/signale/blob/master/docs/readme.DE.md).\n\nYou can now support the development process through [GitHub Sponsors](https://github.com/sponsors/klaudiosinani).\n\nVisit the [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md#translating-documentation) to learn more on how to translate this document into more languages.\n\n## Highlights\n\n- 19 out-of-the-box loggers\n- Hackable to the core\n- Clean and beautiful output\n- Integrated timers\n- Custom pluggable loggers\n- TypeScript support\n- Interactive and regular modes\n- Secrets & sensitive information filtering\n- Filename, date and timestamp support\n- Scoped loggers and timers\n- Scaled logging levels mechanism\n- String interpolation support\n- Multiple configurable writable streams\n- Simple and minimal syntax\n- Globally configurable through `package.json`\n- Overridable configuration per file and logger\n\n## Contents\n\n- [Description](#description)\n- [Highlights](#highlights)\n- [Install](#install)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [API](#api)\n- [Development](#development)\n- [Related](#related)\n- [Who's Using It?](#whos-using-it)\n- [Team](#team)\n- [Sponsors](#sponsors)\n- [License](#license)\n\n## Install\n\n### Yarn\n\n```bash\nyarn add signale\n```\n\n### NPM\n\n```bash\nnpm install signale\n```\n\n## Usage\n\n### Default Loggers\n\nImport signale and start using any of the default loggers.\n\n<details>\n<summary>View all of the available loggers.</summary>\n\n<br/>\n\n- `await`\n- `complete`\n- `error`\n- `debug`\n- `fatal`\n- `fav`\n- `info`\n- `note`\n- `pause`\n- `pending`\n- `star`\n- `start`\n- `success`\n- `wait`\n- `warn`\n- `watch`\n- `log`\n\n</details>\n\n<br/>\n\n```js\nconst signale = require('signale');\n\nsignale.success('Operation successful');\nsignale.debug('Hello', 'from', 'L59');\nsignale.pending('Write release notes for %s', '1.2.0');\nsignale.fatal(new Error('Unable to acquire lock'));\nsignale.watch('Recursively watching build directory...');\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"media/default-loggers.png\" width=\"65%\">\n</div>\n\n### Custom Loggers\n\nTo create a custom logger define an `options` object yielding a `types` field with the logger data and pass it as argument to a new signale instance.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  disabled: false,\n  interactive: false,\n  logLevel: 'info',\n  scope: 'custom',\n  secrets: [],\n  stream: process.stdout,\n  types: {\n    remind: {\n      badge: '**',\n      color: 'yellow',\n      label: 'reminder',\n      logLevel: 'info'\n    },\n    santa: {\n      badge: '🎅',\n      color: 'red',\n      label: 'santa',\n      logLevel: 'info'\n    }\n  }\n};\n\nconst custom = new Signale(options);\ncustom.remind('Improve documentation.');\ncustom.santa('Hoho! You have an unused variable on L45.');\n```\n\n<div align=\"center\">\n  <img alt=\"Custom Loggers\" src=\"media/custom-loggers.png\" width=\"70%\">\n</div>\n\nHere is an example where we override the default `error` and `success` loggers.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  types: {\n    error: {\n      badge: '!!',\n      label: 'fatal error'\n    },\n    success: {\n      badge: '++',\n      label: 'huge success'\n    }\n  }\n};\n\nconst signale = new Signale();\nsignale.error('Default Error Log');\nsignale.success('Default Success Log');\n\nconst custom = new Signale(options);\ncustom.error('Custom Error Log');\ncustom.success('Custom Success Log');\n```\n\n<div align=\"center\">\n  <img alt=\"Default Loggers\" src=\"media/override-defaults.png\" width=\"65%\">\n</div>\n\nThe `options` object can hold any of the following attributes: `disabled`, `interactive`, `logLevel`, `secrets`, `stream`, `scope` and `types`. \n\n##### `disabled`\n\n- Type: `Boolean`\n- Default: `false`\n\nDisables the logging functionality of all loggers belonging to the created instance.\n\n##### `interactive`\n\n- Type: `Boolean`\n- Default: `false`\n\nSwitches all loggers belonging to the created instance into the interactive mode.\n\n##### `logLevel`\n\n- Type: `String`\n- Default: `'info'`\n\nSets the general logging level of the created instance. Can be one of the following:\n\n- `'info'` - Displays all messages from all loggers.\n- `'timer'` -  Displays messages only from the `time`, `timeEnd`, `debug`, `warn`, `error` & `fatal` loggers.\n- `'debug'` - Displays messages only from the `debug`, `warn`, `error` & `fatal` loggers.\n- `'warn'` - Displays messages only from the `warn`, `error` & `fatal` loggers.\n- `'error'` - Displays messages only from the `error` & `fatal` loggers.\n\n##### `secrets`\n\n- Type: `(String|Number)[]`\n- Default: `[]`\n\nAn array holding secrets/sensitive-information to be removed from the body and metadata of to-be-logged messages and replaced with the default `'[secure]'` string.\n\n##### `stream`\n\n- Type: `stream.Writable|stream.Writable[]`\n- Default: `process.stdout`\n\nDestination to which the data is written, can be a single valid [Writable stream](https://nodejs.org/api/stream.html#stream_writable_streams) or an array holding multiple valid Writable streams.\n\n##### `scope`\n\n- Type: `String|String[]`\n\nName of the scope the logger is reporting from.\n\n##### `types`\n\n- Type: `Object`\n\nHolds the configuration of the custom and default loggers.\n\nAdditionally, the configuration object of each custom/default logger type, defined in the `types` option, can hold any of the following attributes: `badge`, `label`, `color`, `logLevel` & `stream`. \n\n##### `badge`\n\n- Type: `String`\n\nThe icon corresponding to the logger.\n\n##### `label`\n\n- Type: `String`\n\nThe label used to identify the type of the logger.\n\n##### `color`\n\n- Type: `String`\n\nThe color of the label, can be any of the foreground colors supported by [chalk](https://github.com/chalk/chalk#colors).\n\n##### `logLevel`\n\n- Type: `String`\n- Default: `'info'`\n\nThe log level corresponding to the logger. Messages originating from the logger are displayed only if the log level is greater or equal to the above described general logging level `logLevel` of the `Signale` instance.\n\n##### `stream`\n\n- Type: `stream.Writable|stream.Writable[]`\n- Default: `process.stdout`\n\nDestination to which the data is written, can be a single valid [Writable stream](https://nodejs.org/api/stream.html#stream_writable_streams) or an array holding multiple valid Writable streams.\n\n### Scoped Loggers\n\nTo create a scoped logger from scratch, define the `scope` field inside the `options` object and pass it as argument to a new signale instance.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  scope: 'global scope'\n};\n\nconst global = new Signale(options);\nglobal.success('Successful Operation');\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Vanilla\" src=\"media/scope-vanilla.png\" width=\"65%\">\n</div>\n\nTo create a scoped logger based on an already existing one, use the `scope()` function, which will return a new signale instance, inheriting all custom loggers, timers, secrets, streams, configuration, log level, interactive mode & disabled statuses from the initial one.\n\n```js\nconst signale = require('signale');\n\nconst global = signale.scope('global scope');\nglobal.success('Hello from the global scope');\n\nfunction foo() {\n  const outer = global.scope('outer', 'scope');\n  outer.success('Hello from the outer scope');\n  \n  setTimeout(() => {\n    const inner = outer.scope('inner', 'scope'); \n    inner.success('Hello from the inner scope');\n  }, 500);\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Existing\" src=\"media/scope-existing.png\" width=\"65%\">\n</div>\n\n### Interactive Loggers\n\nTo initialize an interactive logger, create a new signale instance with the [`interactive`](#interactive) attribute set to `true`. While into the interactive mode, previously logged messages originating from an interactive logger, will be overridden only by new ones originating from the same or a different interactive logger. Note that regular messages originating from regular loggers are not overridden by the interactive ones.\n\n```js\nconst {Signale} = require('signale');\n\nconst interactive = new Signale({interactive: true, scope: 'interactive'});\n\ninteractive.await('[%d/4] - Process A', 1);\n\nsetTimeout(() => {\n  interactive.success('[%d/4] - Process A', 2);\n  setTimeout(() => {\n    interactive.await('[%d/4] - Process B', 3);\n    setTimeout(() => {\n      interactive.error('[%d/4] - Process B', 4);\n      setTimeout(() => {}, 1000);\n    }, 1000);\n  }, 1000);\n}, 1000);\n```\n\n<div align=\"center\">\n  <img alt=\"Interactive Mode\" src=\"media/interactive-mode.gif\" width=\"65%\">\n</div>\n\n### Writable Streams\n\nBy default, all signale instances log their messages to the `process.stdout` stream. This can be modified, to match your own preference, through the [`stream`](#stream) property, where you can define a single or multiple valid Writable streams, which will be used by all logger types to log your data. Additionally, it is possible to define one or more Writable streams exclusively for a specific logger type, thus write data independently from the rest logger types.\n\n```js\nconst {Signale} = require('signale');\n\nconst options = {\n  stream: process.stderr, // All loggers will now write to `process.stderr`\n  types: {\n    error: {\n      // Only `error` will write to both `process.stdout` & `process.stderr`\n      stream: [process.stdout, process.stderr]\n    }\n  }\n};\n\nconst signale = new Signale(options);\nsignale.success('Message will appear on `process.stderr`');\nsignale.error('Message will appear on both `process.stdout` & `process.stderr`');\n```\n\n<div align=\"center\">\n  <img alt=\"Writable Streams\" src=\"media/writable-streams.png\" width=\"73%\">\n</div>\n\n### Secrets Filtering\n\nBy utilizing the `secrets` option, secrets and other sensitive information can be filtered out from the body as well as the metadata, i.e. scope names etc, of to-be-logged messages. The option is part of the configuration object passed to a `Signale` instance on its initialization, and is of type `Array<String|Number>`. The array can hold multiple secrets, all of which are removed, if present, from the to-be-logged messages and are replaced with the default `'[secure]'` string. Additionally, when the unary `signale.scope(name)` function is used, the returned `Signale` instance inherits all the secrets belonging to its parent. The secrets checking process is performed in a **case-sensitive** manner. Also, the unary [`signale.addSecrets()`](https://github.com/klaudiosinani/signale#signaleaddsecretssecrets) and the nullary [`signale.clearSecrets()`](https://github.com/klaudiosinani/signale#signaleclearsecrets) functions are available through the API for adding and clearing secrets respectively.\n\nIt is **critical** and **highly recommended** to **not type directly secrets in your code**, thus the following example serves **only** as a simple & easily reproducible usage demonstration.\n\n```js\nconst {Signale} = require('signale');\n\n// In reality secrets could be securely fetched/decrypted through a dedicated API \nconst [USERNAME, TOKEN] = ['klaudiosinani', 'token'];\n\nconst logger1 = new Signale({\n  secrets: [USERNAME, TOKEN]\n});\n\nlogger1.log('$ exporting USERNAME=%s', USERNAME);\nlogger1.log('$ exporting TOKEN=%s', TOKEN);\n\n// `logger2` inherits all secrets from its parent `logger1`\nconst logger2 = logger1.scope('parent');\n\nlogger2.log('$ exporting USERNAME=%s', USERNAME);\nlogger2.log('$ exporting TOKEN=%s', TOKEN);\n```\n\n<div align=\"center\">\n  <img alt=\"Secrets Filtering\" src=\"media/filter-secrets.png\" width=\"73%\">\n</div>\n\n### Timers\n\nTimer are managed by the `time()` and `timeEnd()` functions. A unique label can be used to identify a timer on initialization, though if none is provided the timer will be assigned one automatically. In addition, calling the `timeEnd()` function without a specified label will have as effect the termination of the most recently initialized timer, that was created without providing a label.\n\n```js\nconst signale = require('signale');\n\nsignale.time('test');\nsignale.time();\nsignale.time();\n\nsetTimeout(() => {\n  signale.timeEnd();\n  signale.timeEnd();\n  signale.timeEnd('test');\n}, 500);\n```\n\n<div align=\"center\">\n  <img alt=\"Timers\" src=\"media/timers.png\" width=\"60%\">\n</div>\n\n## Configuration\n\n### Global\n\nTo enable global configuration define the options under the `signale` namespace in your `package.json`.\n\nThe following illustrates all the available options with their respective default values.\n\n```json\n{\n  \"signale\": {\n    \"displayScope\": true,\n    \"displayBadge\": true,\n    \"displayDate\": false,\n    \"displayFilename\": false,\n    \"displayLabel\": true,\n    \"displayTimestamp\": false,\n    \"underlineLabel\": true,\n    \"underlineMessage\": false,\n    \"underlinePrefix\": false,\n    \"underlineSuffix\": false,\n    \"uppercaseLabel\": false\n  }\n}\n```\n\n<details>\n<summary>View all of the available options in detail.</summary>\n\n##### `displayScope`\n\n- Type: `Boolean`\n- Default: `true`\n\nDisplay the scope name of the logger. \n\n##### `displayBadge`\n\n- Type: `Boolean`\n- Default: `true`\n\nDisplay the badge of the logger.\n\n##### `displayDate`\n\n- Type: `Boolean`\n- Default: `false`\n\nDisplay the current local date in `YYYY-MM-DD` format. \n\n##### `displayFilename`\n\n- Type: `Boolean`\n- Default: `false`\n\nDisplay the name of the file that the logger is reporting from.\n\n##### `displayLabel`\n\n- Type: `Boolean`\n- Default: `true`\n\nDisplay the label of the logger.\n\n##### `displayTimestamp`\n\n- Type: `Boolean`\n- Default: `false`\n\nDisplay the current local time in `HH:MM:SS` format.\n\n##### `underlineLabel`\n\n- Type: `Boolean`\n- Default: `true`\n\nUnderline the logger label.\n\n##### `underlineMessage`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnderline the logger message.\n\n##### `underlinePrefix`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnderline the logger prefix.\n\n##### `underlineSuffix`\n\n- Type: `Boolean`\n- Default: `false`\n\nUnderline the logger suffix.\n\n##### `uppercaseLabel`\n\n- Type: `Boolean`\n- Default: `false`\n\nDisplay the label of the logger in uppercase.\n\n</details>\n\n### Local\n\nTo enable local configuration call the `config()` function on your signale instance. Local configurations will always override any pre-existing configuration inherited from `package.json`.\n\nIn the following example, loggers in the `foo.js` file will run under their own configuration, overriding the `package.json` one.\n\n```js\n// foo.js\nconst signale = require('signale');\n\n// Overrides any existing `package.json` config\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n}); \n\nsignale.success('Hello from the Global scope');\n```\n\n<div align=\"center\">\n  <img alt=\"Local Config\" src=\"media/local-config.png\" width=\"65%\">\n</div>\n\nAlso, scoped loggers can have their own independent configuration, overriding the one inherited by the parent instance or `package.json`. \n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n});\n\nsignale.success('Hello from the Global scope');\n\nfunction foo() {\n  // `fooLogger` inherits the config of `signale`\n  const fooLogger = signale.scope('foo scope');\n\n  // Overrides both `signale` and `package.json` configs\n  fooLogger.config({\n    displayFilename: true,\n    displayTimestamp: false,\n    displayDate: true\n  });\n\n  fooLogger.success('Hello from the Local scope');\n}\n\nfoo();\n```\n\n<div align=\"center\">\n  <img alt=\"Scope Config\" src=\"media/scope-config.png\" width=\"65%\">\n</div>\n\n## API\n\n#### signale.`<logger>(message[, message]|messageObj|errorObj)`\n\n##### **`logger`**\n\n- Type: `Function`\n\nCan be any default or custom logger.\n\n##### **`message`**\n\n- Type: `String`\n\nCan be one or more comma delimited strings.\n\n```js\nconst signale = require('signale');\n\nsignale.success('Successful operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful', 'operation');\n//=> ✔  success  Successful operation\n\nsignale.success('Successful %s', 'operation');\n//=> ✔  success  Successful operation\n```\n\n##### **`errorObj`**\n\n- Type: `Error Object`\n\nCan be any error object.\n\n```js\nconst signale = require('signale');\n\nsignale.error(new Error('Unsuccessful operation'));\n//=> ✖  error  Error: Unsuccessful operation\n//        at Module._compile (module.js:660:30)\n//        at Object.Module._extensions..js (module.js:671:10)\n//        ...\n```\n\n##### **`messageObj`**\n\n- Type: `Object`\n\nCan be an object holding the `prefix`, `message` and `suffix` attributes, with `prefix` and `suffix` always prepended and appended respectively to the logged `message`.\n\n```js\nconst signale = require('signale');\n\nsignale.complete({prefix: '[task]', message: 'Fix issue #59', suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n\nsignale.complete({prefix: '[task]', message: ['Fix issue #%d', 59], suffix: '(@klaudiosinani)'});\n//=> [task] ☒  complete  Fix issue #59 (@klaudiosinani)\n```\n\n#### signale.`scope(name[, name])`\n\nDefines the scope name of the logger.\n\n##### **`name`**\n\n- Type: `String`\n\nCan be one or more comma delimited strings.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \nconst fooBar = signale.scope('foo', 'bar');\n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfooBar.success('foo bar');\n//=> [foo] [bar] › ✔  success  foo bar\n```\n\n#### signale.`unscope()`\n\nClears the scope name of the logger.\n\n```js\nconst signale = require('signale');\n\nconst foo = signale.scope('foo'); \n\nfoo.success('foo');\n//=> [foo] › ✔  success  foo\n\nfoo.unscope();\n\nfoo.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`config(settingsObj)`\n\nSets the configuration of an instance overriding any existing global or local configuration.\n\n##### **`settingsObj`**\n\n- Type: `Object`\n\nCan hold any of the documented [options](#global).\n\n```js\n// foo.js\nconst signale = require('signale');\n\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: true\n});\n\nsignale.success('Successful operations');\n//=> [2018-5-15] [11:12:38] [foo.js] › ✔  success  Successful operations\n```\n\n#### signale.`time([, label])`\n\n- Return Type: `String`\n\nSets a timers and accepts an optional label. If none provided the timer will receive a unique label automatically.\n\nReturns a string corresponding to the timer label. \n\n##### **`label`**\n\n- Type: `String`\n\nLabel corresponding to the timer. Each timer must have its own unique label.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n```\n\n#### signale.`timeEnd([, label])`\n\n- Return Type: `Object`\n\nDeactivates the timer to which the given label corresponds. If no label is provided the most recent timer, that was created without providing a label, will be deactivated.\n\nReturns an object `{label, span}` holding the timer label and the total running time.\n\n##### **`label`**\n\n- Type: `String`\n\nLabel corresponding to the timer, each timer has its own unique label.\n\n```js\nconst signale = require('signale');\n\nsignale.time();\n//=> ▶  timer_0  Initialized timer...\n\nsignale.time();\n//=> ▶  timer_1  Initialized timer...\n\nsignale.time('label');\n//=> ▶  label    Initialized timer...\n\nsignale.timeEnd();\n//=> ◼  timer_1  Timer run for: 2ms\n\nsignale.timeEnd();\n//=> ◼  timer_0  Timer run for: 2ms\n\nsignale.timeEnd('label');\n//=> ◼  label    Timer run for: 2ms\n```\n\n#### signale.`disable()`\n\nDisables the logging functionality of all loggers belonging to a specific instance.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n```\n\n#### signale.`enable()`\n\nEnables the logging functionality of all loggers belonging to a specific instance.\n\n```js\nconst signale = require('signale');\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.enable();\n\nsignale.success('foo');\n//=> ✔  success  foo\n```\n\n#### signale.`isEnabled()`\n\nChecks whether the logging functionality of a specific instance is enabled.\n\n```js\nconst signale = require('signale');\n\nsignale.success('foo');\n//=> ✔  success  foo\n\nsignale.isEnabled();\n// => true\n\nsignale.disable();\n\nsignale.success('foo');\n//=>\n\nsignale.isEnabled();\n// => false\n```\n\n#### signale.`addSecrets(secrets)`\n\nAdds new secrets/sensitive-information to the targeted Signale instance.\n\n##### **`secrets`**\n\n- Type: `(String|Number)[]`\n\nArray holding the secrets/sensitive-information to be filtered out.\n\n```js\nconst signale = require('signale');\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n```\n\n#### signale.`clearSecrets()`\n\nRemoves all secrets/sensitive-information from the targeted Signale instance.\n\n```js\nconst signale = require('signale');\n\nsignale.addSecrets(['klaudiosinani']);\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=[secure]\n\nsignale.clearSecrets();\n\nsignale.log('$ exporting USERNAME=%s', 'klaudiosinani');\n//=> $ exporting USERNAME=klaudiosinani\n```\n\n## Development\n\nFor more info on how to contribute to the project, please read the [contributing guidelines](https://github.com/klaudiosinani/signale/blob/master/contributing.md).\n\n- Fork the repository and clone it to your machine\n- Navigate to your local fork: `cd signale`\n- Install the project dependencies: `npm install` or `yarn install`\n- Lint code for errors: `npm test` or `yarn test`\n\n## Related\n\n- [qoa](https://github.com/klaudiosinani/qoa) - Minimal interactive command-line prompts\n- [taskbook](https://github.com/klaudiosinani/taskbook) - Tasks, boards & notes for the command-line habitat\n- [hyperocean](https://github.com/klaudiosinani/hyperocean) - Deep oceanic blue Hyper terminal theme\n\n## Who's Using It?\n\n- [Boostnote](https://github.com/BoostIO/Boostnote)\n- [Docz](https://github.com/pedronauck/docz)\n- [Remix by Ethereum](https://github.com/ethereum/remix)\n- [Semantic Release](https://github.com/semantic-release/semantic-release)\n- [Shower](https://github.com/shower/shower)\n- [Taskbook](https://github.com/klaudiosinani/taskbook)\n- [Vant](https://github.com/youzan/vant)\n\nView in detail all the packages and repositories that are using Signale [here](https://github.com/klaudiosinani/signale/network/dependents).\n\n## Team\n\n- Klaudio Sinani [(@klaudiosinani)](https://github.com/klaudiosinani)\n- Mario Sinani [(@mariosinani)](https://github.com/mariosinani)\n\n## Sponsors\n\nA big thank you to all the people and companies supporting our Open Source work:\n\n- [Better Stack: Spot, Resolve, and Prevent Downtime.](https://betterstack.com/)\n\n\n## License\n\n[MIT](https://github.com/klaudiosinani/signale/blob/master/license.md)\n"
  },
  {
    "path": "src/signale.js",
    "content": "'use strict';\nconst util = require('util');\nconst path = require('path');\nconst readline = require('readline');\nconst chalk = require('chalk');\nconst figures = require('figures');\nconst pkgConf = require('pkg-conf');\nconst pkg = require('./../package.json');\nconst defaultTypes = require('./types');\n\nconst {green, grey, red, underline, yellow} = chalk;\n\nlet isPreviousLogInteractive = false;\nconst defaults = pkg.options.default;\nconst namespace = pkg.name;\n\nclass Signale {\n  constructor(options = {}) {\n    this._interactive = options.interactive || false;\n    this._config = Object.assign(this.packageConfiguration, options.config);\n    this._customTypes = Object.assign({}, options.types);\n    this._disabled = options.disabled || false;\n    this._scopeName = options.scope || '';\n    this._timers = options.timers || new Map();\n    this._types = this._mergeTypes(defaultTypes, this._customTypes);\n    this._stream = options.stream || process.stdout;\n    this._longestLabel = this._getLongestLabel();\n    this._secrets = options.secrets || [];\n    this._generalLogLevel = this._validateLogLevel(options.logLevel);\n\n    Object.keys(this._types).forEach(type => {\n      this[type] = this._logger.bind(this, type);\n    });\n  }\n\n  get _now() {\n    return Date.now();\n  }\n\n  get scopeName() {\n    return this._scopeName;\n  }\n\n  get currentOptions() {\n    return Object.assign({}, {\n      config: this._config,\n      disabled: this._disabled,\n      types: this._customTypes,\n      interactive: this._interactive,\n      timers: this._timers,\n      stream: this._stream,\n      secrets: this._secrets,\n      logLevel: this._generalLogLevel\n    });\n  }\n\n  get date() {\n    const _ = new Date();\n    return [_.getFullYear(), _.getMonth() + 1, _.getDate()].join('-');\n  }\n\n  get timestamp() {\n    const _ = new Date();\n    return [_.getHours(), _.getMinutes(), _.getSeconds()].join(':');\n  }\n\n  get filename() {\n    const _ = Error.prepareStackTrace;\n    Error.prepareStackTrace = (error, stack) => stack;\n    const {stack} = new Error();\n    Error.prepareStackTrace = _;\n\n    const callers = stack.map(x => x.getFileName());\n\n    const firstExternalFilePath = callers.find(x => {\n      return x !== callers[0];\n    });\n\n    return firstExternalFilePath ? path.basename(firstExternalFilePath) : 'anonymous';\n  }\n\n  get packageConfiguration() {\n    return pkgConf.sync(namespace, {defaults});\n  }\n\n  get _longestUnderlinedLabel() {\n    return underline(this._longestLabel);\n  }\n\n  get _logLevels() {\n    return {\n      info: 0,\n      timer: 1,\n      debug: 2,\n      warn: 3,\n      error: 4\n    };\n  }\n\n  set configuration(configObj) {\n    this._config = Object.assign(this.packageConfiguration, configObj);\n  }\n\n  _arrayify(x) {\n    return Array.isArray(x) ? x : [x];\n  }\n\n  _timeSpan(then) {\n    return (this._now - then);\n  }\n\n  _getLongestLabel() {\n    const {_types} = this;\n    const labels = Object.keys(_types).map(x => _types[x].label);\n    return labels.reduce((x, y) => x.length > y.length ? x : y);\n  }\n\n  _validateLogLevel(level) {\n    return Object.keys(this._logLevels).includes(level) ? level : 'info';\n  }\n\n  _mergeTypes(standard, custom) {\n    const types = Object.assign({}, standard);\n\n    Object.keys(custom).forEach(type => {\n      types[type] = Object.assign({}, types[type], custom[type]);\n    });\n\n    return types;\n  }\n\n  _filterSecrets(message) {\n    const {_secrets} = this;\n\n    if (_secrets.length === 0) {\n      return message;\n    }\n\n    let safeMessage = message;\n\n    _secrets.forEach(secret => {\n      safeMessage = safeMessage.replace(new RegExp(secret, 'g'), '[secure]');\n    });\n\n    return safeMessage;\n  }\n\n  _formatStream(stream) {\n    return this._arrayify(stream);\n  }\n\n  _formatDate() {\n    return `[${this.date}]`;\n  }\n\n  _formatFilename() {\n    return `[${this.filename}]`;\n  }\n\n  _formatScopeName() {\n    if (Array.isArray(this._scopeName)) {\n      const scopes = this._scopeName.filter(x => x.length !== 0);\n      return `${scopes.map(x => `[${x.trim()}]`).join(' ')}`;\n    }\n\n    return `[${this._scopeName}]`;\n  }\n\n  _formatTimestamp() {\n    return `[${this.timestamp}]`;\n  }\n\n  _formatMessage(str) {\n    return util.format(...this._arrayify(str));\n  }\n\n  _meta() {\n    const meta = [];\n\n    if (this._config.displayDate) {\n      meta.push(this._formatDate());\n    }\n\n    if (this._config.displayTimestamp) {\n      meta.push(this._formatTimestamp());\n    }\n\n    if (this._config.displayFilename) {\n      meta.push(this._formatFilename());\n    }\n\n    if (this._scopeName.length !== 0 && this._config.displayScope) {\n      meta.push(this._formatScopeName());\n    }\n\n    if (meta.length !== 0) {\n      meta.push(`${figures.pointerSmall}`);\n      return meta.map(item => grey(item));\n    }\n\n    return meta;\n  }\n\n  _hasAdditional({suffix, prefix}, args) {\n    return (suffix || prefix) ? '' : this._formatMessage(args);\n  }\n\n  _buildSignale(type, ...args) {\n    let [msg, additional] = [{}, {}];\n\n    if (args.length === 1 && typeof (args[0]) === 'object' && args[0] !== null) {\n      if (args[0] instanceof Error) {\n        [msg] = args;\n      } else {\n        const [{prefix, message, suffix}] = args;\n        additional = Object.assign({}, {suffix, prefix});\n        msg = message ? this._formatMessage(message) : this._hasAdditional(additional, args);\n      }\n    } else {\n      msg = this._formatMessage(args);\n    }\n\n    const signale = this._meta();\n\n    if (additional.prefix) {\n      if (this._config.underlinePrefix) {\n        signale.push(underline(additional.prefix));\n      } else {\n        signale.push(additional.prefix);\n      }\n    }\n\n    if (this._config.displayBadge && type.badge) {\n      signale.push(chalk[type.color](this._padEnd(type.badge, type.badge.length + 1)));\n    }\n\n    if (this._config.displayLabel && type.label) {\n      const label = this._config.uppercaseLabel ? type.label.toUpperCase() : type.label;\n      if (this._config.underlineLabel) {\n        signale.push(chalk[type.color](this._padEnd(underline(label), this._longestUnderlinedLabel.length + 1)));\n      } else {\n        signale.push(chalk[type.color](this._padEnd(label, this._longestLabel.length + 1)));\n      }\n    }\n\n    if (msg instanceof Error && msg.stack) {\n      const [name, ...rest] = msg.stack.split('\\n');\n      if (this._config.underlineMessage) {\n        signale.push(underline(name));\n      } else {\n        signale.push(name);\n      }\n\n      signale.push(grey(rest.map(l => l.replace(/^/, '\\n')).join('')));\n      return signale.join(' ');\n    }\n\n    if (this._config.underlineMessage) {\n      signale.push(underline(msg));\n    } else {\n      signale.push(msg);\n    }\n\n    if (additional.suffix) {\n      if (this._config.underlineSuffix) {\n        signale.push(underline(additional.suffix));\n      } else {\n        signale.push(additional.suffix);\n      }\n    }\n\n    return signale.join(' ');\n  }\n\n  _write(stream, message) {\n    if (this._interactive && stream.isTTY && isPreviousLogInteractive) {\n      readline.moveCursor(stream, 0, -1);\n      readline.clearLine(stream);\n      readline.cursorTo(stream, 0);\n    }\n\n    stream.write(message + '\\n');\n    isPreviousLogInteractive = this._interactive;\n  }\n\n  _log(message, streams = this._stream, logLevel) {\n    if (this.isEnabled() && this._logLevels[logLevel] >= this._logLevels[this._generalLogLevel]) {\n      this._formatStream(streams).forEach(stream => {\n        this._write(stream, message);\n      });\n    }\n  }\n\n  _logger(type, ...messageObj) {\n    const {stream, logLevel} = this._types[type];\n    const message = this._buildSignale(this._types[type], ...messageObj);\n    this._log(this._filterSecrets(message), stream, this._validateLogLevel(logLevel));\n  }\n\n  _padEnd(str, targetLength) {\n    str = String(str);\n    targetLength = parseInt(targetLength, 10) || 0;\n\n    if (str.length >= targetLength) {\n      return str;\n    }\n\n    if (String.prototype.padEnd) {\n      return str.padEnd(targetLength);\n    }\n\n    targetLength -= str.length;\n    return str + ' '.repeat(targetLength);\n  }\n\n  addSecrets(secrets) {\n    if (!Array.isArray(secrets)) {\n      throw new TypeError('Argument must be an array.');\n    }\n\n    this._secrets.push(...secrets);\n  }\n\n  clearSecrets() {\n    this._secrets = [];\n  }\n\n  config(configObj) {\n    this.configuration = configObj;\n  }\n\n  disable() {\n    this._disabled = true;\n  }\n\n  enable() {\n    this._disabled = false;\n  }\n\n  isEnabled() {\n    return !this._disabled;\n  }\n\n  scope(...name) {\n    if (name.length === 0) {\n      throw new Error('No scope name was defined.');\n    }\n\n    return new Signale(Object.assign(this.currentOptions, {scope: name}));\n  }\n\n  unscope() {\n    this._scopeName = '';\n  }\n\n  time(label) {\n    if (!label) {\n      label = `timer_${this._timers.size}`;\n    }\n\n    this._timers.set(label, this._now);\n\n    const message = this._meta();\n    message.push(green(this._padEnd(this._types.start.badge, 2)));\n\n    if (this._config.underlineLabel) {\n      message.push(green(this._padEnd(underline(label), this._longestUnderlinedLabel.length + 1)));\n    } else {\n      message.push(green(this._padEnd(label, this._longestLabel.length + 1)));\n    }\n\n    message.push('Initialized timer...');\n    this._log(message.join(' '), this._stream, 'timer');\n\n    return label;\n  }\n\n  timeEnd(label) {\n    if (!label && this._timers.size) {\n      const is = x => x.includes('timer_');\n      label = [...this._timers.keys()].reduceRight((x, y) => {\n        return is(x) ? x : (is(y) ? y : null);\n      });\n    }\n\n    if (this._timers.has(label)) {\n      const span = this._timeSpan(this._timers.get(label));\n      this._timers.delete(label);\n\n      const message = this._meta();\n      message.push(red(this._padEnd(this._types.pause.badge, 2)));\n\n      if (this._config.underlineLabel) {\n        message.push(red(this._padEnd(underline(label), this._longestUnderlinedLabel.length + 1)));\n      } else {\n        message.push(red(this._padEnd(label, this._longestLabel.length + 1)));\n      }\n\n      message.push('Timer run for:');\n      message.push(yellow(span < 1000 ? span + 'ms' : (span / 1000).toFixed(2) + 's'));\n      this._log(message.join(' '), this._stream, 'timer');\n\n      return {label, span};\n    }\n  }\n}\n\nmodule.exports = Signale;\n"
  },
  {
    "path": "src/types.js",
    "content": "'use strict';\nconst figures = require('figures');\n\nmodule.exports = {\n  error: {\n    badge: figures.cross,\n    color: 'red',\n    label: 'error',\n    logLevel: 'error'\n  },\n  fatal: {\n    badge: figures.cross,\n    color: 'red',\n    label: 'fatal',\n    logLevel: 'error'\n  },\n  fav: {\n    badge: figures('❤'),\n    color: 'magenta',\n    label: 'favorite',\n    logLevel: 'info'\n  },\n  info: {\n    badge: figures.info,\n    color: 'blue',\n    label: 'info',\n    logLevel: 'info'\n  },\n  star: {\n    badge: figures.star,\n    color: 'yellow',\n    label: 'star',\n    logLevel: 'info'\n  },\n  success: {\n    badge: figures.tick,\n    color: 'green',\n    label: 'success',\n    logLevel: 'info'\n  },\n  wait: {\n    badge: figures.ellipsis,\n    color: 'blue',\n    label: 'waiting',\n    logLevel: 'info'\n  },\n  warn: {\n    badge: figures.warning,\n    color: 'yellow',\n    label: 'warning',\n    logLevel: 'warn'\n  },\n  complete: {\n    badge: figures.checkboxOn,\n    color: 'cyan',\n    label: 'complete',\n    logLevel: 'info'\n  },\n  pending: {\n    badge: figures.checkboxOff,\n    color: 'magenta',\n    label: 'pending',\n    logLevel: 'info'\n  },\n  note: {\n    badge: figures.bullet,\n    color: 'blue',\n    label: 'note',\n    logLevel: 'info'\n  },\n  start: {\n    badge: figures.play,\n    color: 'green',\n    label: 'start',\n    logLevel: 'info'\n  },\n  pause: {\n    badge: figures.squareSmallFilled,\n    color: 'yellow',\n    label: 'pause',\n    logLevel: 'info'\n  },\n  debug: {\n    badge: figures('⬤'),\n    color: 'red',\n    label: 'debug',\n    logLevel: 'debug'\n  },\n  await: {\n    badge: figures.ellipsis,\n    color: 'blue',\n    label: 'awaiting',\n    logLevel: 'info'\n  },\n  watch: {\n    badge: figures.ellipsis,\n    color: 'yellow',\n    label: 'watching',\n    logLevel: 'info'\n  },\n  log: {\n    badge: '',\n    color: '',\n    label: '',\n    logLevel: 'info'\n  }\n};\n"
  },
  {
    "path": "test/config.ts",
    "content": "import * as signale from '..';\n\n// Overrides any existing `package.json` config\nsignale.config({\n  displayFilename: true,\n  displayTimestamp: true,\n  displayDate: false\n});\n\nsignale.success('Hello from the Global scope');\n\nfunction scopedConfigTest() {\n  // `fooLogger` inherits the config of `signale`\n  const fooLogger = signale.scope('foo scope');\n\n  // Overrides both `signale` and `package.json` configs\n  fooLogger.config({\n    displayFilename: true,\n    displayTimestamp: false,\n    displayDate: true\n  });\n\n  fooLogger.success('Hello from the Local scope');\n}\n\nscopedConfigTest();\n"
  },
  {
    "path": "test/custom.ts",
    "content": "import { Signale, SignaleConstructorOptions } from '../';\n\ntype CustomLogger = 'remind' | 'santa';\n\nconst optionsCustom: SignaleConstructorOptions<CustomLogger> = {\n  stream: process.stdout,\n  scope: 'custom',\n  types: {\n    remind: {\n      badge: '**',\n      color: 'yellow',\n      label: 'reminder'\n    },\n    santa: {\n      badge: '🎅',\n      color: 'red',\n      label: 'santa'\n    }\n  }\n};\n\nconst custom = new Signale(optionsCustom);\n\ncustom.remind('Improve documentation.');\ncustom.santa('Hoho! You have an unused variable on L45.');\ncustom.debug('This should still work');\n\n"
  },
  {
    "path": "test/default.ts",
    "content": "import * as logger1 from '..';\n\nconst { Signale } = logger1;\n\nlogger1.success('Operation successful');\nlogger1.debug('Hello', 'from', 'L59');\nlogger1.pending('Write release notes for %s', '1.2.0');\nlogger1.fatal(new Error('Unable to acquire lock'));\nlogger1.watch('Recursively watching build directory...');\nlogger1.complete({\n  prefix: '[task]',\n  message: 'Fix issue #59',\n  suffix: '(@klaussinani)'\n});\n\nconst logger2 = new Signale();\n\nlogger2.success('Operation successful');\nlogger2.debug('Hello', 'from', 'L59');\nlogger2.pending('Write release notes for %s', '1.2.0');\nlogger2.fatal(new Error('Unable to acquire lock'));\nlogger2.watch('Recursively watching build directory...');\nlogger2.complete({\n  prefix: '[task]',\n  message: 'Fix issue #59',\n  suffix: '(@klaussinani)'\n});\n"
  },
  {
    "path": "test/override.ts",
    "content": "import { Signale, SignaleConstructorOptions } from '../';\n\nconst optionsOverride: SignaleConstructorOptions = {\n  types: {\n    error: {\n      badge: '!!',\n      color: 'red',\n      label: 'fatal error'\n    },\n    success: {\n      badge: '++',\n      color: 'green',\n      label: 'huge success'\n    }\n  }\n};\n\nconst signale = new Signale(optionsOverride);\n\nsignale.error('Default Error Log');\nsignale.success('Default Success Log');\n\nconst customOverride = new Signale(optionsOverride);\n\ncustomOverride.error('Custom Error Log');\ncustomOverride.success('Custom Success Log');\n"
  },
  {
    "path": "test/scoped.ts",
    "content": "import { Signale, SignaleConstructorOptions } from '../';\n\nconst optionsScope: SignaleConstructorOptions = {\n  scope: 'global1 scope'\n};\n\nconst global1 = new Signale(optionsScope);\nglobal1.success('Successful Operation');\n\nconst global2 = global1.scope('global2 scope');\nglobal2.success('Hello from the global2 scope');\n\nfunction scopedTest() {\n  const outer = global2.scope('outer', 'scope');\n  outer.success('Hello from the outer scope');\n\n  setTimeout(() => {\n    const inner = outer.scope('inner', 'scope');\n    inner.success('Hello from the inner scope');\n  }, 500);\n}\n\nscopedTest();\n"
  },
  {
    "path": "test/secrets.ts",
    "content": "import { Signale, SignaleConstructorOptions } from '..';\n\n// In reality secrets could be securely fetched/decrypted through a dedicated API\nconst [USERNAME, TOKEN] = ['klaussinani', 'token'];\n\nconst opts: SignaleConstructorOptions = {\n  secrets: [USERNAME, TOKEN]\n}\n\nconst logger1 = new Signale(opts);\n\nlogger1.log('$ exporting USERNAME=%s', USERNAME);\nlogger1.log('$ exporting TOKEN=%s', TOKEN);\n\n// `logger2` inherits all secrets from its parent `logger1`\nconst logger2 = logger1.scope('parent');\n\nlogger2.log('$ exporting USERNAME=%s', USERNAME);\nlogger2.log('$ exporting TOKEN=%s', TOKEN);\n"
  },
  {
    "path": "test/streams.ts",
    "content": "import { Signale, SignaleConstructorOptions } from '..';\n\nconst opts: SignaleConstructorOptions = {\n  stream: process.stderr, // All loggers will now write to `process.stderr`\n  types: {\n    error: {\n      badge: '✖',\n      color: 'red',\n      label: 'error',\n      // Only `error` will write to both `process.stdout` & `process.stderr`\n      stream: [process.stdout, process.stderr]\n    }\n  }\n};\n\nconst signale = new Signale(opts);\n\nsignale.success('Message will appear on `process.stderr`');\nsignale.error('Message will appear on both `process.stdout` & `process.stderr`');\n"
  },
  {
    "path": "test/timers.ts",
    "content": "import * as signale from '../';\n\nsignale.time('test1');\nsignale.time('test2');\nsignale.time();\nsignale.time();\n\nsetTimeout(() => {\n  signale.timeEnd();\n  signale.timeEnd();\n  signale.timeEnd('test2');\n  signale.timeEnd('test1');\n}, 500);\n"
  },
  {
    "path": "test/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"strict\": true,\n    \"target\": \"ES2017\"\n  }\n}\n"
  },
  {
    "path": "types/signale.d.ts",
    "content": "/* Authors: Resi Respati <https://github.com/resir014>\n *          Kingdaro <https://github.com/kingdaro>\n *          Joydip Roy <https://github.com/rjoydip>\n *          Klaus Sinani <https://github.com/klaussinani>\n */\n\nimport { Writable as WritableStream } from 'stream';\n\ndeclare namespace _signale {\n  export type DefaultLogger =\n    | 'await'\n    | 'complete'\n    | 'debug'\n    | 'error'\n    | 'fatal'\n    | 'fav'\n    | 'info'\n    | 'log'\n    | 'note'\n    | 'pause'\n    | 'pending'\n    | 'star'\n    | 'start'\n    | 'success'\n    | 'wait'\n    | 'warn'\n    | 'watch';\n\n  export type ChalkColor =\n    | 'black'\n    | 'blue'\n    | 'blueBright'\n    | 'cyan'\n    | 'cyanBright'\n    | 'gray'\n    | 'green'\n    | 'greenBright'\n    | 'magenta'\n    | 'magentaBright'\n    | 'red'\n    | 'redBright'\n    | 'white'\n    | 'whiteBright'\n    | 'yellow'\n    | 'yellowBright';\n\n  export type Secret = (string | number)[];\n\n  export type LoggerFunction = (...message: any[]) => void;\n\n  export type LogLevel = 'info' | 'timer' | 'debug' | 'warn' | 'error';\n\n  export interface LoggerConfiguration {\n    badge: string;\n    color: ChalkColor;\n    label: string;\n    logLevel?: LogLevel;\n    stream?: WritableStream | WritableStream[];\n  }\n\n  export interface InstanceConfiguration {\n    displayBadge?: boolean;\n    displayDate?: boolean;\n    displayFilename?: boolean;\n    displayLabel?: boolean;\n    displayScope?: boolean;\n    displayTimestamp?: boolean;\n    underlineLabel?: boolean;\n    underlineMessage?: boolean;\n    underlinePrefix?: boolean;\n    underlineSuffix?: boolean;\n    uppercaseLabel?: boolean;\n  }\n\n  export interface ConstructorOptions<T extends string> {\n    config?: InstanceConfiguration;\n    disabled?: boolean;\n    interactive?: boolean;\n    logLevel?: LogLevel;\n    scope?: string;\n    secrets?: Secret;\n    stream?: WritableStream | WritableStream[];\n    types?: Partial<Record<T, LoggerConfiguration>>;\n  }\n\n  export interface Constructor {\n    new <T extends string = DefaultLogger>(\n      options?: ConstructorOptions<T>\n    ): Instance<T>;\n  }\n\n  interface Base<T extends string = DefaultLogger> {\n    addSecrets(secrets: Secret): void;\n    clearSecrets(): void;\n    config(configObj: InstanceConfiguration): Instance<T>;\n    disable(): void;\n    enable(): void;\n    isEnabled(): boolean;\n    scope(...name: string[]): Instance<T>;\n    time(label?: string): string;\n    timeEnd(label?: string): { label: string; span: number };\n    unscope(): void;\n  }\n\n  export type Instance<T extends string = DefaultLogger> = Base<T> &\n    Record<T, LoggerFunction> &\n    Record<DefaultLogger, LoggerFunction>;\n}\n\ndeclare namespace signale {\n  export type Secret = _signale.Secret;\n  export type LogLevel = _signale.LogLevel;\n  export type ChalkColor = _signale.ChalkColor;\n  export type DefaultLogger = _signale.DefaultLogger;\n  export type LoggerFunction = _signale.LoggerFunction;\n  export interface SignaleConfiguration\n    extends _signale.InstanceConfiguration {}\n  export interface LoggerConfiguration extends _signale.LoggerConfiguration {}\n  export interface SignaleConstructorOptions<T extends string = DefaultLogger>\n    extends _signale.ConstructorOptions<T> {}\n}\n\ndeclare const signale: _signale.Instance & {\n  Signale: _signale.Constructor;\n};\n\nexport = signale;\n"
  }
]