{"_id":"@eelkeblok/harbor","_rev":"1-4320de757ffbdf44a49ae07975164fde","name":"@eelkeblok/harbor","dist-tags":{"latest":"0.226.1"},"versions":{"0.226.0":{"name":"@eelkeblok/harbor","version":"0.226.0","type":"module","description":"Boilerplate for Drupal Themes","exports":"./Harbor/index.js","bin":{"harbor":"index.js"},"node":"^12.22.0 || ^14.17.0 || >=16.0.0","scripts":{"development":"node ./index.js --watch --styleguide","export":"node ./index.js --task=export","images":"node ./index.js --task=images","javascripts":"node ./index.js --task=javascripts","predevelopment":"npm run production","production":"node ./index.js --task=prepare,compile --minify","postproduction":"node ./index.js --task=export,setup","resolve":"node ./index.js --task=resolve","setup":"node ./index.js --task=setup","styleguide":"node ./index.js --styleguide","stylesheets":"node ./index.js --task=stylesheets","test:approve":"node ./index.js --task=test --test=approve","test:reference":"node ./index.js --task=test --test=reference","test":"node ./index.js --task=test"},"repository":{"type":"git","url":"git+https://github.com/eelkeblok/harbor.git"},"keywords":["Drupal","Theme"],"author":{"name":"Thomas van der Velde","email":"contact@eelkeblok.net"},"license":"MIT","bugs":{"url":"https://github.com/eelkeblok  /harbor/issues"},"homepage":"https://github.com/eelkeblok/harbor#readme","dependencies":{"@babel/cli":"^7.20.7","@babel/core":"^7.20.7","@babel/eslint-parser":"^7.19.1","@babel/preset-env":"^7.20.2","@storybook/addon-essentials":"^6.5.15","@storybook/builder-webpack5":"^6.5.15","@storybook/cli":"^6.5.15","@storybook/html":"^6.5.15","@storybook/manager-webpack5":"^6.5.15","autoprefixer":"^10.4.13","babel-loader":"^9.1.0","babel-plugin-module-resolver":"^4.1.0","camelcase":"^7.0.1","chalk":"^5.2.0","chokidar":"^3.5.3","concat":"^1.0.3","copyfiles":"^2.4.1","cssnano":"^5.1.14","dotenv":"16.0.3","eslint":"^8.31.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^8.5.0","eslint-import-resolver-babel-module":"^5.3.1","eslint-plugin-import":"^2.26.0","eslint-plugin-prettier":"^4.2.1","glob":"^8.0.3","html-escaper":"^3.0.3","imagemin":"^8.0.1","is-svg":"^4.3.2","log-symbols":"^5.1.0","mkdirp":"^1.0.4","node-polyfill-webpack-plugin":"^2.0.1","node-sass-glob-importer":"^5.3.2","outdent":"^0.8.0","postcss":"^8.4.20","postcss-combine-duplicated-selectors":"^10.0.3","postcss-scss":"^4.0.6","prettier":"^2.8.1","react":"^18.2.0","react-dom":"^18.2.0","rimraf":"^3.0.2","sass":"^1.57.1","snake-case":"^3.0.4","stringify-object":"^4.0.1","stylelint":"^14.16.1","stylelint-config-recommended-scss":"^8.0.0","stylelint-scss":"^4.3.0","svgo":"^3.0.2","svgstore":"^3.0.1","twing":"^5.1.2","twing-loader":"^4.0.0","type-name":"^2.0.2","uglify-js":"^3.17.4","webpack":"^5.75.0","ws":"^8.11.0","yaml-loader":"^0.8.0"},"gitHead":"5ce4781ed699d7d89769599f0e9ce1c952ee9c98","_id":"@eelkeblok/harbor@0.226.0","_nodeVersion":"20.4.0","_npmVersion":"9.7.2","dist":{"integrity":"sha512-tASRNz7CheJxjKxaPMNMQDegEKuDnbfjsYMnORs3qxEJzOr0wGsYjOCY1sr3+DntqM7NRKHtAlollfUys0CvLA==","shasum":"cef45d88ac4e25399b73a240ffafb100f5bcde64","tarball":"https://registry.npmjs.org/@eelkeblok/harbor/-/harbor-0.226.0.tgz","fileCount":89,"unpackedSize":219231,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHApw1jkKM6dPg8KzHtlBsLNy6gabfawVscfILQ5EE6IAiEAkzlVRqKqYCeHf/htOVZbGd/XSSBBy4UX4z7SCVzWt24="}]},"_npmUser":{"name":"eelkeblok","email":"npmjs.com@blokspeed.net"},"directories":{},"maintainers":[{"name":"eelkeblok","email":"npmjs.com@blokspeed.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/harbor_0.226.0_1690716514684_0.8411589813506617"},"_hasShrinkwrap":false},"0.226.1":{"name":"@eelkeblok/harbor","version":"0.226.1","type":"module","description":"Boilerplate for Drupal Themes","exports":"./Harbor/index.js","bin":{"harbor":"index.js"},"node":"^12.22.0 || ^14.17.0 || >=16.0.0","scripts":{"development":"node ./index.js --watch --styleguide","export":"node ./index.js --task=export","images":"node ./index.js --task=images","javascripts":"node ./index.js --task=javascripts","predevelopment":"npm run production","production":"node ./index.js --task=prepare,compile --minify","postproduction":"node ./index.js --task=export,setup","resolve":"node ./index.js --task=resolve","setup":"node ./index.js --task=setup","styleguide":"node ./index.js --styleguide","stylesheets":"node ./index.js --task=stylesheets","test:approve":"node ./index.js --task=test --test=approve","test:reference":"node ./index.js --task=test --test=reference","test":"node ./index.js --task=test"},"repository":{"type":"git","url":"git+https://github.com/eelkeblok/harbor.git"},"keywords":["Drupal","Theme"],"author":{"name":"Thomas van der Velde","email":"contact@eelkeblok.net"},"license":"MIT","bugs":{"url":"https://github.com/eelkeblok  /harbor/issues"},"homepage":"https://github.com/eelkeblok/harbor#readme","dependencies":{"@babel/cli":"^7.20.7","@babel/core":"^7.20.7","@babel/eslint-parser":"^7.19.1","@babel/preset-env":"^7.20.2","@storybook/addon-essentials":"^6.5.15","@storybook/builder-webpack5":"^6.5.15","@storybook/cli":"^6.5.15","@storybook/html":"^6.5.15","@storybook/manager-webpack5":"^6.5.15","autoprefixer":"^10.4.13","babel-loader":"^9.1.0","babel-plugin-module-resolver":"^4.1.0","camelcase":"^7.0.1","chalk":"^5.2.0","chokidar":"^3.5.3","concat":"^1.0.3","copyfiles":"^2.4.1","cssnano":"^5.1.14","dotenv":"16.0.3","eslint":"^8.31.0","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^8.5.0","eslint-import-resolver-babel-module":"^5.3.1","eslint-plugin-import":"^2.26.0","eslint-plugin-prettier":"^4.2.1","glob":"^8.0.3","html-escaper":"^3.0.3","imagemin":"^8.0.1","is-svg":"^4.3.2","log-symbols":"^5.1.0","mkdirp":"^1.0.4","node-polyfill-webpack-plugin":"^2.0.1","node-sass-glob-importer":"^5.3.2","outdent":"^0.8.0","postcss":"^8.4.20","postcss-combine-duplicated-selectors":"^10.0.3","postcss-scss":"^4.0.6","prettier":"^2.8.1","react":"^18.2.0","react-dom":"^18.2.0","rimraf":"^3.0.2","sass":"^1.57.1","snake-case":"^3.0.4","stringify-object":"^4.0.1","stylelint":"^14.16.1","stylelint-config-recommended-scss":"^8.0.0","stylelint-scss":"^4.3.0","svgo":"^3.0.2","svgstore":"^3.0.1","twing":"^5.1.2","twing-loader":"^4.0.0","type-name":"^2.0.2","uglify-js":"^3.17.4","webpack":"^5.75.0","ws":"^8.11.0","yaml-loader":"^0.8.0"},"gitHead":"7ab254b5d35ec9a2538da948dfde351fb4c40694","_id":"@eelkeblok/harbor@0.226.1","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-m0ethXDRgt3pb+wYGUuKJ46LAMnoXyH2dsvH623apnDy5H3qgZgP23b29K8AQvaTNEfh12GCr82LzUoKWrHyTA==","shasum":"30e0251ddeddac73f3fdabbfb4917f7cb8bafd71","tarball":"https://registry.npmjs.org/@eelkeblok/harbor/-/harbor-0.226.1.tgz","fileCount":89,"unpackedSize":219386,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA4ORcgpppSo8fkUkzVGkwv3xwWNC9OGfkR7kU8Fh1qXAiEAkwBzXgshrrAftu3G/ZnklmTDI5EAfkicQQYHyX+daH8="}]},"_npmUser":{"name":"eelkeblok","email":"npmjs.com@blokspeed.net"},"directories":{},"maintainers":[{"name":"eelkeblok","email":"npmjs.com@blokspeed.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/harbor_0.226.1_1690832590190_0.6640112829304265"},"_hasShrinkwrap":false}},"time":{"created":"2023-07-30T11:28:34.604Z","0.226.0":"2023-07-30T11:28:34.899Z","modified":"2023-07-31T19:43:10.470Z","0.226.1":"2023-07-31T19:43:10.368Z"},"maintainers":[{"name":"eelkeblok","email":"npmjs.com@blokspeed.net"}],"description":"Boilerplate for Drupal Themes","homepage":"https://github.com/eelkeblok/harbor#readme","keywords":["Drupal","Theme"],"repository":{"type":"git","url":"git+https://github.com/eelkeblok/harbor.git"},"author":{"name":"Thomas van der Velde","email":"contact@eelkeblok.net"},"bugs":{"url":"https://github.com/eelkeblok  /harbor/issues"},"license":"MIT","readme":"# Harbor\n\n*Note: This is not the canonical version of this package. Please refer to \n[@toolbarthomas/harbor](https://www.npmjs.com/package/@toolbarthomas/harbor).*\n\nHarbor is an asset builder that fits within the theme architecture of [Drupal](https://drupal.org/) 8+ setups.\nIt can create [Drupal](https://drupal.org/) compatible themes without the need to install the actual CMS.\nWith the help of [Storybook](https://storybookjs.org/) it can generate the Twig templates that are used by Drupal themes.\n\nThe assets are processed on a very basic level, stylesheets can be compiled with the included compiler and Babel will transform the defined javascript files to enable JS compatibility for older browsers.\n\nIt is optional to use the bundled workers but they ensure that they work correctly within Drupal and your styleguide. It is possible to include other frameworks within the environment by simply adding it within a compatible theme library configuration.\n\n[Get more information](./TIPS.md) for implementing Harbor in your current Drupal environment.\n\n## Setup\n\nYou can install Harbor via NPM ([Nodejs](https://nodejs.org) is required in order to do this.):\n\n```sh\n$ npm install @eelkeblok/harbor\n```\n\nThen you can start Harbor by simply running:\n\n```sh\n$ node node_modules/@eelkeblok/harbor/index.js\n```\n\nHarbor will run the default tasks when there are no CLI arguments defined for the initial command.\nThe following CLI arguments can be used in order to customize the build process.\n\n| Argument     | Description                                                                           |\n| ------------ | ------------------------------------------------------------------------------------- |\n| --task       | Starts one or more worker tasks to compile the theme assets.                          |\n| --verbose    | Writes extended console messages within the command line.                             |\n| --styleguide | Starts the styleguide builder.                                                        |\n| --watch      | Observes for file changes for the initiated tasks.                                    |\n| --minify     | Minifies the processed assets.                                                        |\n| --test       | Defines the testing phase for Backstopjs, should be `test`, `reference` or `approve`. |\n\nYou can also use the `harbor` command instead if you installed it globally:\nThis will only run the default workers but you can use additional parameters like the local commands.\nKeep in mind that you need to be in the correct working directory in order to run\nit correctly.\n\n```sh\n$ npm install -g @eelkeblok/harbor\n```\n\nInstalling Harbor globally will lock you in a specific version so keep in mind\nit can break your workflow if you installed the newest version without fixing the breaking-changes.\n\n```sh\n$ harbor\n# or\n$ harbor --styleguide --watch\n```\n\n## Workers\n\nA worker provides the core tasks for Harbor and can be adjusted within the configuration.\nWorkers can be initiated during a Harbor process by calling the defined hook within the command or as CLI argument.\n\n```sh\n# Starts the workers that have the stylesheets hook from the configuration.\n$ node node_modules/@eelkeblok/harbor/index.js --task=stylesheets\n$ node node_modules/@eelkeblok/harbor/index.js stylesheets\n```\n\nThis example will start the workers that are defined with the `stylesheets` hook, by default it will process the configured sass entry files (or it will try to use the default configured entries).\n\nThe actual hooks are defined within the default configuration of each worker, these hooks can be adjusted within your custom configuration. Workers that share the same hook will be called in parallel order by default.\nThe order of this queue can be adjusted by adding the optional flag `::` with the index value to mark the order, this will also run the queue in a sequence.\nThis configuration example will start the Cleaner worker before the FileSync worker during the usage of the `prepare` task within the CLI.\n\n```js\n...\nCleaner: {\n  hook: ['clean', 'prepare::0'],\n  ...\n},\nFileSync: {\n  hook: ['sync', 'prepare::1']\n  ...\n}\n...\n```\n\nWorkers that share the same hook without the double colons will run in a parallel order:\n\n```sh\n# Should initiate the compile workers in a parallel order:\n$ node node_modules/@eelkeblok/harbor/index.js --task=compile\n```\n\nThe following workers are configured within the default configuration:\n\n| Worker           | Description                                                                     | Hook(s)                                                 |\n| ---------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| AssetExporter    | Wraps the defined entries as a template literal module.                         | `AssetExporter` `export`                                |\n| Cleaner          | Cleans the defined THEME_DIST environment directory.                            | `Cleaner` `clean` `prepare` `default`                   |\n| FileSync         | Synchronizes the defined entry files to the THEME_DIST environment directory.   | `FilSync` `sync` `prepare` `default`                    |\n| JsCompiler       | Transforms the defined entry javascript files with Babel.                       | `JSCompiler` `js` `javascripts` `compile` `default`     |\n| Resolver         | Resolves NPM installed vendor pacakges to the THEME_DIST environment directory. | `Resolver` `resolve` `prepare` `default`                |\n| SassCompiler     | Compiles the defined entry Sass files with Node Sass.                           | `SassCompiler` `sass` `stylesheets` `compile` `default` |\n| StyleguideHelper | Creates initial storybook entries from the defined Twig templates.              | `StyleguideHelper` `setup`                              |\n| StyleguideTester | Initiates Snapshot tests for the styleguide with BackstopJS.                    | `StyleguideTester` `test`                               |\n| SVSpriteCompiler | Creates one or more inline SVG sprites based from the configured entries.       | `SVGSpriteCompiler` `svg` `images` `compile` `default`  |\n\n## Plugins\n\nPlugins are used to run post-process tasks like starting the storybook development server, optimizing the assets or include a file watcher.\nThese can be defined by adding the given CLI argument hooks within your command:\n\n```sh\n$ node node_modules/@eelkeblok/harbor/index.js --task=javascripts --minify\n```\n\nMore plugins can be included within a single command, the following plugins are available within the default configuration, the result of certain plugins can vary between environments:\n\n| Plugin             | Environment        | Description                                                                                 | Hook(s)               |\n| ------------------ | ------------------ | ------------------------------------------------------------------------------------------- | --------------------- |\n| JSOptimizer        | production `only`  | Minifies the defined js entries within the THEME_DIST directory                             | minify                |\n| StyleOptimizer     | production `only`  | Minifies the defined css entries within the THEME_DIST directory                            | minify                |\n| StyleguideCompiler | production         | Creates a static storybook styleguide.                                                      | storybook, styleguide |\n| StyleguideCompiler | development        | Starts the storybook development server.                                                    | storybook, styleguide |\n| Watcher            | development `only` | Watches the configured instance entries and runs the assigned workers during a file change. | watch                 |\n\nThis will only generate the actual assets that should be compatible for the Drupal environment.\nKeep in mind that this command will only run the configured Harbor workers, the actual development tools can be included with extra CLI arguments:\n\n```sh\n$ node node_modules/@eelkeblok/harbor/index.js --task=javascripts --minify --watch\n```\n\n## Environment\n\nAn optional Harbor environment can be defined by creating a [dotenv](https://www.npmjs.com/package/dotenv) file within the root of your theme directory.\nThe following configuration can be adjusted, the default values will be used for any missing environment variable.\n\n| Environment variable   | Default value    | Description                                                                                                                                                  |\n| ---------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| THEME_SRC              | ./src            | Defines the working source directory for all Worker entries.                                                                                                 |\n| THEME_DIST             | ./dist           | Defines the build directory for all Worker entries & the styleguide development server.                                                                      |\n| THEME_PORT             | 8080             | Defines the server port for the styleguide development server.                                                                                               |\n| THEME_DEBUG            | false            | Includes sourcemaps if the defined entries support it.                                                                                                       |\n| THEME_ENVIRONMENT      | production       | Enables environment specific Plugins to be used.                                                                                                             |\n| THEME_STATIC_DIRECTORY | storybook-static | Defines the destination path for the static styleguide build. This is used to create multiple static builds within the codebase.                             |\n| THEME_WEBSOCKET_PORT   | 35729            | Enables attached library stylesheets to be automatically refreshed within the styleguide, the websocket won't be created if there is no port number defined. |\n| THEME_TEST_PHASE       | test             | Defines the testing method for BackstopJS: `test`, `reference` or `approve`.                                                                                 |\n| THEME_AS_CLI           | false            | Launches Storybook in CLI mode that is used by the StyleguideTester.                                                                                         |\n\n## Default Configuration\n\nThe Harbor workers can be configured to point out the location of your assets. A default configuration has been defined within Harbor,\na custom configuration can be used by creating `harbor.config.js` within the working directory.\n\nFor example:\n\n```js\n  // harbor.config.js\n\n  ...\n  workers: {\n    SassCompiler: {\n      options: ...,\n      hook: 'stylesheets',\n      plugins: ...,\n      entry: {\n        main: [...]\n      },\n    },\n  }\n  ...\n```\n\n## Common Configuration\n\nThe following configuration options are available for the default Workers & Plugins.\nMost options are used before the defined Worker/Plugin is actually running; like resolving the actual entry files or ignoring some source paths for the Worker/Plugin entry:\n\n| Option  | type            | Description                                                                                                                                            |\n| ------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| entry   | String/String[] | The actual sources that will be processed for the defined Worker or Plugin.                                                                            |\n| hook    | String          | Defines the commands that should start the given Worker or Plugin                                                                                      |\n| ignore  | String/String[] | Excludes the defined path(s) from the entry sources for the defined Worker or Plugin.                                                                  |\n| options | Object          | Defines the optional configuration for the defined Worker/Plugin, the actual options are not common since they are defined for the used NPM libraries. | § |\n\n## Default Worker Configuration\n\n### Cleaner configuration\n\nThe Cleaner is a default Harbor worker that will delete all files within the defined environment destination directory: `THEME_DIST`\nNo specific configuration is available for this Worker.\n\n### FileSync configuration\n\nThe FileSync will synchronize the defined static entries to the configured environment destination directory.\n\n| Option   | type     | Description                                                                                   |\n| -------- | -------- | --------------------------------------------------------------------------------------------- |\n| patterns | String[] | Copies the given patterns and it's folder structure to the environment destination directory. |\n\n### JsCompiler configuration\n\nThe JsCompiler transforms & lints the defined entries with Babel & Eslint.\nThe result will be written relative to the configured environment destination directory.\n\n| Option            | type   | Description                                                             |\n| ----------------- | ------ | ----------------------------------------------------------------------- |\n| plugins           | Object | Optional plugins that will be assigned to the Babel & Eslint instances. |\n| plugins.eslint    | Object | The optional Eslint plugin(configuration).                              |\n| plugins.transform | Object | The optional Babel transform(configuration).                            |\n\n### SassCompiler configuration\n\nThe SassCompiler renders & prepares the defined entries with Node Sass & Postcss.\nThe result will be written relative to the configured environment destination directory.\n\n| Option                    | type    | Description                                                                 |\n| ------------------------- | ------- | --------------------------------------------------------------------------- |\n| options                   | Object  | Optional configuration for the Node Sass compiler.                          |\n| options.useLegacyCompiler | Boolean | Flag that enables the Node Sass compiler instead of the Dart Sass compiler. |\n| plugins                   | Object  | Optional plugins that will be assigned to the Postcss plugin.               |\n| plugins.postcss           | Object  | The optional Postcss plugin(configuration).                                 |\n\n### StyleguideHelper configuration\n\nThe StyleguideHelper creates initial Styleguide entry templates from the existing Twig templates any json or yaml file that is relative to the Twig template will be included within the styleguide entyr.\n\n| Option                          | type        | Description                                                                                                                          |\n| ------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |\n| options                         | Object      | Optional configuration for the worker.                                                                                               |\n| options.configurationExtensions | String[]    | Includes the first configuration entry from the defined extensions, the configuration is found relative within the template context. |\n| options.defaultModuleName       | String      | Defines the name for the default entry story.                                                                                        |\n| options.destinationDirectory    | String/null | Writes the new entries to the defined directory or write it relative to the template by disabling this option.                       |\n| options.disableAlias            | Boolean     | Don't use the included @theme alias and use a relative path instead.                                                                 |\n| options.extname                 | String      | Use the defined extension when the styleguide entry is written to the FileSystem.                                                    |\n| options.filterKeywords          | String[]    | Removes the defined keywords from the generated Module export, File paths won't be adjusted from this settings.                      |\n| options.ignoreInitial           | Boolean     | Overwrites the existing entry files when enabled.                                                                                    |\n| options.prettier                | Boolean     | Should implement your project prettier configuration to ensure the styleguide entries are written in the correct syntax.             |\n| options.sep                     | String      | Defines the structure separator for the entry title.                                                                                 |\n| options.structuredTitle         | Boolean     | Includes the base directory structure for the styleguide entries when enabled.                                                       |\n| options.variants                | Object      | Includes optional module variants for the entry template.                                                                            |\n| options.variants[].context      | String      | Should match with the file that is used for the variant configuration.                                                               |\n| options.variants[].query        | String      | Executes a regular expression match within the defined context path, scripting files are ignored.                                    |\n| options.variants[].transform    | Function    | Optional handler that will the matched query values.                                                                                 |\n\n#### Define StyleguideHelper variants\n\nYou can define additional module variants for each entry template by defining additional\nproperties that will be used within the template scope:\n\n```js\nStyleguideHelper: {\n  variants: {\n    modifier_class: {\n      query: /[^&(){}`a-zA-Z][.][a-zA-Z-]+--[a-zA-Z-]+/g,\n      context: 'scss',\n      transform: (v) => v.split('.').join(''),\n    },\n  },\n}\n```\n\nThe `query` option should match a regular expression that will match everything\nwithin the given source file. This source file is based defined from the initial source file where the `from` option is used as file extension replacement:\n\n```\nsrc/example.twig => src/example.scss\n```\n\nA `transform` handler can be included in order to strip any unwanted character from the matched results within the regular expression.\n\nYou can also directly import the variant configuration if the defined context matches a `.js`, `.json`, `.mjs` or `.yaml` file. This will assign the extra properties to the defined variant:\n\n```js\n// Will create a variant as module import:\n// import ButtonExampleConfiguration from button.example.json\n// within the template context: button.twig.\nStyleguideHelper: {\n  variants: {\n    modifier_class: {\n      context: '.example.json',\n    },\n  },\n}\n```\n\nIt is also possible to search for configuration files outside the directory by including the `includeDirectories` option within the variant configuration.\n\nKeep in mind that the directories are resolved from the defined `THEME_SRC` environment path. It will use the configuration if the file `config/{module}.example.json` exists:\n\n```js\n// Will create a variant as module import:\n// import ButtonExampleConfiguration from button.example.json\n// outside the template context: button.twig.\nStyleguideHelper: {\n  variants: {\n    modifier_class: {\n      context: '.example.json',\n      includeDirectories: ['config'],\n    },\n  },\n}\n```\n\n### StyleguideTester configuration\n\nThe StyleguideTester enables snapshot testing of the generated styleguide. All valid stories will be extracted by Storybook and are tested with [BackstopJS](https://github.com/garris/BackstopJS).\n\n| Option                    | type   | Description                                                                                                          |\n| ------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------- |\n| options                   | Object | Optional configuration for the worker & BackstopJS.                                                                  |\n| options.backstopJS        | Object | Defines the base configuration for BackstopJS. [More info](https://github.com/garris/BackstopJS#advanced-scenarios)  |\n| options.outputPath        | String | The destination for the Styleguide manifest that is used for the Snapshot tester.                                    |\n| options.scenarioDirectory | String | Defines the destination directory for additional scenarios defined as YAML or JSON file.                             |\n| options.staticDirectory   | String | Defines the destination directory for the static styleguide build, to prevent removal of already generated packages. |\n\n### SvgSpriteCompiler configuration\n\nThe SvgSpriteCompiler will compile the defined entries into inline SVG sprites.\nThe result will be written relative to the configured environment destination directory.\n\n| Option | type   | Description                                             |\n| ------ | ------ | ------------------------------------------------------- |\n| prefix | String | The ID prefix for each icon within the compiled sprite. |\n\n### Resolver configuration\n\nThe Resolver will resolve the defined packages from the node_modules to the environment destination.\n\n| Option      | type   | Description                                                                |\n| ----------- | ------ | -------------------------------------------------------------------------- |\n| options.cwd | String | The destination directory where the resolved entries will be Written into. |\n\n## Default Plugin Configuration\n\n### AssetExporter configuration\n\nThe AssetExporter wraps the defined entry templates as a valid module export template literal.\nIt is possible to include an optional literal function within the actual asset by defining a new `includeLiteral` Object within the options.\n\n| Option                          | type   | Description                                                                                        |\n| ------------------------------- | ------ | -------------------------------------------------------------------------------------------------- |\n| options                         | Object | Optional configuration for the AssetExporter.                                                      |\n| options.includeLiteral          | Object | Assigns Babel module-resolver aliases to the Storybook instance.                                   |\n| options.includeLiteral[].entry  | String | Should match with the defined entry name, a custom literal will be included when there is a match. |\n| options.includeLiteral[].export | String | The actual literal that can be prefixed with.                                                      |\n| options.includeLiteral[].import | String | The actual import source for the optional module literal.                                          |\n\n### StyleguideCompiler configuration\n\nThe Styleguide Compiler will generate a new Storybook instance for the defined `THEME_ENVIRONMENT` value.\n\nA Storybook development version can be launched by defining `THEME_ENVIRONMENT='development'` within your environment configuration.\n\nThis will launch a new Storybook development server with the Storybook CLI.\nMore information about the usage of this server can be found on [Storybook](https://storybook.js.org/docs)\n\nYou can also create a static version of your Storybook instance by setting `THEME_ENVIRONMENT` to `production`.\nThis static styleguide will be written to the defined `THEME_DEST` destination and will resolve the processed assets within the static package.\nKeep in mind that some assets cannot be displayed when viewing the static HTML document directly for security reasons.\n\nThis can be resolved by viewing the actual result from a (local) webserver.\n\n| Option                    | type           | Description                                                                                                    |\n| ------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------- |\n| options                   | Object         | Optional configuration for the Storybook compiler.                                                             |\n| options.addons            | Array          | Should contain the [Storybook addon](https://storybook.js.org/docs/react/addons/install-addons) configuration. |\n| options.alias             | Object         | Assigns Babel module-resolver aliases to the Storybook instance.                                               |\n| options.builderDirectory  | String         | Defines the Twing instance directory `.twing` that can be used to include custom Twing functionality.          |\n| options.configDirectory   | String         | Defines the Storybook instance directory for your theme: `./.storybook`.                                       |\n| options.globalMode        | Boolean/String | `experimental` This will use a global render context for Twig.                                                 |\n| options.optimization      | Object         | Defines the [Webpack optimization](https://webpack.js.org/configuration/optimization/) configuration.          |\n| options.staticDirectory   | String         | Defines the destination path for the `production` build of the Storybook styleguide `storybook-static`.        |\n| options.useLegacyCompiler | Boolean        | Enables the usage of older Twing libraries within the styleguide to disable the requirement of async stories.  |\n\n### Watcher configuration\n\nThe Watcher can be started by defining the `watch` parameter to the CLI and will run the defined hooks from the TaskManager.\nThe Watcher will shutdown automatically if no event occured during the defined duration.\n\n| Option              | type                   | Description                                                                             |\n| ------------------- | ---------------------- | --------------------------------------------------------------------------------------- |\n| instances           | Object[String, Object] | Spawns a Wacther instance for each defined entry.                                       |\n| instances[].event   | String                 | Defines the Event handler and will publish the defined hook with the TaskManager.       |\n| instances[].path    | String/String[]        | Watches the given paths for the spawned Watcher.                                        |\n| instances[].workers | String[]               | Will publish the defined Harbor workers in order.                                       |\n| options             | Object                 | Optional configuration for the Watcher class.                                           |\n| options.delay       | number                 | Creates a timeout before running the connected Workers after a Watch event has occured. |\n| options.duration    | number                 | Defines the lifetime in miliseconds of the spawned Watcher instances.                   |\n\n## Example NPM script setup\n\nYou can assign the following NPM script entries when using the default hook configuration:\n\n```js\n  {\n    \"production\": \"node node_modules/@eelkeblok/harbor/index.js --task=prepare,compile --minify\",\n    \"predevelopment\": \"npm run production\",\n    \"development\": \"node node_modules/@eelkeblok/harbor/index.js --watch --styleguide\",\n    \"images\": \"node node_modules/@eelkeblok/harbor/index.js --task=images\",\n    \"javascripts\": \"node node_modules/@eelkeblok/harbor/index.js --task=javascripts\",\n    \"resolve\": \"node node_modules/@eelkeblok/harbor/index.js --task=resolve\",\n    \"styleguide\": \"node node_modules/@eelkeblok/harbor/index.js --styleguide\",\n    \"stylesheets\": \"node node_modules/@eelkeblok/harbor/index.js --task=stylesheets\",\n    \"test\": \"node node_modules/@eelkeblok/harbor/index.js --task=test\",\n  }\n```\n\n### Asset management\n\nAssets can be included by using the [attach_library](https://www.drupal.org/docs/theming-drupal/adding-stylesheets-css-and-javascript-js-to-a-drupal-theme) Twig function within your templates.\n\nStylesheets that are injected from the `attach_library` function will also refresh during a file change.\n\nYou need a valid Drupal theme library configuration file within your theme with the defined resources you want to use within the theme:\n\n```yml\n# example.libraries.yml\nbase:\n  version: 1.x\n  css:\n    base:\n      dist/main/stylesheets/index.css: {}\n  js:\n    dist/main/javascripts/base.js: {}\n```\n\nThe defined assets will be included within the templates that uses the `attach_library` Twig function:\n\n```twig\n\n{{ attach_library('example/base') }}\n\n```\n\nIt also possible to use the defined Storybook preview head & body snippets within your project. Harbor will copy the configuration files from the defined `configDirectory` option within the `StyleguideCompiler` plugin ('./storybook').\n\nYou can also import the actual assets within each storybook story to enable Hot Module Reload. Keep in mind that you still need to define the required libraries within Drupal if you don't include assets with the `attach_library` function.\n\n```js\n// example.stories.js\n\nimport styles from './styles.css';\n\n...\n```\n\n### Suggested javascript structure.\n\nUsing the functionality of the Drupal.behaviors Object, you can run the defined javascript during the (initial) (re)load within Drupal and Storybook.\nStorybook calls the attach handler within the Drupal behaviors, this Object is used within Drupal sites and is also available for the styleguide.\n\nThe actual javascript can be created like the following and should be compliant with the Drupal javascript structure:\n\n```js\n  (function example(Drupal) {\n    Drupal.behaviors.example = {\n      attach: (context, settings) => {\n        ...\n      }\n    }\n  })(Drupal, drupalSettings);\n```\n\n### Implementing templates since >=1.0.0\n\nAs of version 1.0.0 you need to define your Twing templates within the Storybook `loaders` configuration. This is required in order to display the actual templates; since they are rendered in asynchronous order:\n\n```js\n// example.stories.js\n\nimport Template from 'template.twig';\n\nexport default {\n  title: 'Example template',\n  loaders: [\n    async ({ args }) => {\n      Template: await Template(args); // Keyname can be anything.\n    },\n  ],\n};\n\n// loaded.Templates is defined within the default default export.\nexport const Default = (args, { loaded }) = > loaded.Template;\n\n// Define the actual arguments\nDefault.args = {\n  title: 'Foo',\n};\n```\n\n```twig\n{{ title }}\n```\n\n### Usage of SVG Inline Sprites\n\nHarbor compiles the defined SVG images with the SVGSpriteCompiler and these can be used within the Twig templates. The sprites are available as a Storybook Global that can be accessed within the styleguide.\n\nYou can easily include these paths with the `add_svg` Twig function. This will output the path of an inline SVG sprite that has been created by the SVGSpriteCompiler. This function accepts 3 arguments to output the path of your selection:\n\n```twig\n{{ add_svg('svg--chevron--down') }}\n```\n\nThis will include the path of the SVG sprite based from the first inline svg that has been stored within the `THEME_SPRITES` storybook global.\nThis would output `dist/main/images/svgsprite.svg#svg--chevron--down` if the entry key would be defined as `svgsprite`...\n\nYou can use any entry key of the SVGSpriteCompiler configuration to use that specific sprite path instead:\n\n```js\n  // harbor.config.js\n\n  workers: {\n    ...\n      SvgSpriteCompiler: {\n        ...\n        entry: {\n          common: 'main/images/common/**.svg',\n          icons: 'main/images/icons/**.svg',\n        },\n        ...\n    ...\n  }\n```\n\n```twig\n{{ add_svg('svg--chevron--down', 'icons') }}\n```\n\nThis will output `dist/main/images/icons.svg#svg--chevron--down`.\n\nIt is also possible to output the base SVG element when the second or third argument has been defined as `true`:\n\n```twig\n{{ add_svg('svg--logo', true) }}\n```\n\nWould output:\n\n```html\n<svg aria-hidden=\"true\" aria-focusable=\"false\">\n  <use xlink:href=\"dist/main/images/common.svg#svg--logo\"></use>\n</svg>\n```\n\nAnd:\n\n```twig\n  {{ add_svg('svg--chevron--down', 'icons', true) }}\n```\n\nWill render:\n\n```xml\n<svg aria-hidden=\"true\" aria-focusable=\"false\">\n  <use xlink:href=\"dist/main/images/icons.svg#svg--chevron--down\"></use>\n</svg>\n```\n\n### Running Snapshot tests\n\nIt is possible to run Snapshot tests with BackstopJS for all created Storybook stories.\nStorybook first generates a stories manifest in order to define the components to test.\nA temporary Storybook instance will be created afterwards, which BackstopJS will use for the snapshot tests.\n\nYou need to enable reference snapshots first otherwise you will encounter an error, you need to pass the optional `test` parameter within the command:\n\n```sh\n$ harbor --task=test --test=reference\n```\n\nThis will create reference snapshots within the defined `options.backstopJS.bitmaps_reference` configuration option.\nThese snapshots will tested with the defined testing snapshots afterwards:\n\n```sh\n# You don't need to define the `test` parameter since this is the default testing method.\n$ harbor --task=test --test=test\n```\n\nAn exception will be thrown if there are any mismatches with the references. You can approve these changes automatically by running:\n\n```sh\n$ harbor --task=test --test=approve\n```\n","readmeFilename":"README.md"}