diff --git a/.autorc b/.autorc new file mode 100644 index 000000000..4a0ce55f1 --- /dev/null +++ b/.autorc @@ -0,0 +1,11 @@ +{ + "plugins": [ + [ + "released", + { + "label": "released :rocket:", + "message": "%TYPE was released with %VERSION" + } + ] + ] +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 8951c3929..12280f30a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,6 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..a5ec49122 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,9 @@ +**/node_modules/** +node_modules +**/vendor/** +vendor +**/test/** +**/dist/** + +// being refactored / removed +packages/uikit-workshop/src/scripts/components/styleguide.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..826a1702e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,86 @@ +module.exports = { + root: true, + env: { + node: true, + builtin: true, + es6: true, + browser: true, + }, + parser: 'babel-eslint', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + allowImportExportEverywhere: true, + ecmaFeatures: { + jsx: true, + experimentalDecorators: true, + }, + }, + globals: {}, + plugins: ['prettier'], + extends: ['eslint-config-prettier'].map(require.resolve), + rules: { + 'prettier/prettier': 'error', + 'block-scoped-var': 0, + camelcase: 0, + 'consistent-return': 2, + curly: [2, 'all'], + 'dot-notation': [1, { allowKeywords: true }], + eqeqeq: [2, 'allow-null'], + 'global-strict': [0, 'never'], + 'guard-for-in': 2, + 'key-spacing': 0, + 'new-cap': 0, + 'no-alert': 2, + 'no-bitwise': 2, + 'no-caller': 2, + 'no-cond-assign': [2, 'except-parens'], + 'no-debugger': 2, + 'no-dupe-args': 2, + 'no-dupe-keys': 2, + 'no-empty': 2, + 'no-eval': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-parens': 0, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 1, + 'no-iterator': 2, + 'no-loop-func': 2, + 'no-mixed-requires': 0, + 'no-multi-str': 2, + 'no-native-reassign': 2, + 'no-new': 2, + 'no-param-reassign': 1, + 'no-proto': 2, + 'no-redeclare': 0, + 'no-script-url': 2, + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow': 2, + 'no-undef': 2, + 'no-underscore-dangle': 0, + 'no-unreachable': 1, + 'no-unused-vars': 1, + 'no-use-before-define': 1, + 'no-useless-call': 2, + 'no-useless-concat': 2, + 'no-var': 2, + 'no-with': 2, + quotes: [0, 'single'], + radix: 2, + strict: 0, + 'valid-typeof': 2, + 'vars-on-top': 0, + 'prefer-const': [ + 'error', + { + destructuring: 'any', + ignoreReadBeforeAssign: false, + }, + ], + }, +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index d5dd0f115..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "env": { - "node": true, - "builtin": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module" - }, - "globals": {}, - "extends": ["prettier"], - "plugins": ["prettier"], - "rules": { - "prettier/prettier": "error", - "block-scoped-var": 0, - "camelcase": 0, - "consistent-return": 2, - "curly": [2, "all"], - "dot-notation": [1, { "allowKeywords": true }], - "eqeqeq": [2, "allow-null"], - "global-strict": [0, "never"], - "guard-for-in": 2, - "key-spacing": 0, - "new-cap": 0, - "no-alert": 2, - "no-bitwise": 2, - "no-caller": 2, - "no-cond-assign": [2, "except-parens"], - "no-debugger": 2, - "no-dupe-args": 2, - "no-dupe-keys": 2, - "no-empty": 2, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-parens": 0, - "no-func-assign": 2, - "no-implied-eval": 2, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 1, - "no-iterator": 2, - "no-loop-func": 2, - "no-mixed-requires": 0, - "no-multi-str": 2, - "no-native-reassign": 2, - "no-new": 2, - "no-param-reassign": 1, - "no-proto": 2, - "no-redeclare": 0, - "no-script-url": 2, - "no-self-assign": 2, - "no-self-compare": 2, - "no-sequences": 2, - "no-shadow": 2, - "no-undef": 2, - "no-underscore-dangle": 0, - "no-unreachable": 1, - "no-unused-vars": 1, - "no-use-before-define": 1, - "no-useless-call": 2, - "no-useless-concat": 2, - "no-var": 2, - "no-with": 2, - "quotes": [0, "single"], - "radix": 2, - "strict": 0, - "valid-typeof": 2, - "vars-on-top": 0, - "prefer-const": [ - "error", - { - "destructuring": "any", - "ignoreReadBeforeAssign": false - } - ] - } -} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..b88ac72a2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,208 @@ +# Automatically normalize line endings for all text-based files +# https://git-scm.com/docs/gitattributes#_end_of_line_conversion +# +## GITATTRIBUTES FOR WEB PROJECTS +# +# These settings are for any web project. +# +# Details per file setting: +# text These files should be normalized (i.e. convert CRLF to LF). +# binary These files are binary and should be left untouched. +# +# Note that binary is a macro for -text -diff. +###################################################################### + +## AUTO-DETECT +## Handle line endings automatically for files detected as +## text and leave all files detected as binary untouched. +## This will handle all files NOT defined below. +* text=auto + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# For the following file types, normalize line endings to LF on +# checkin and prevent conversion to CRLF when they are checked out +# (this is required in order to prevent newline related issues like, +# for example, after the build script is run) + +.* text eol=lf +*.css text eol=lf +*.html text eol=lf +*.js text eol=lf +*.json text eol=lf +*.md text eol=lf +*.sh text eol=lf +*.txt text eol=lf +*.xml text eol=lf + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +## SOURCE CODE +*.bat text eol=crlf +*.coffee text +*.htm text +*.inc text +*.ini text +*.jsx text +*.less text +*.od text +*.onlydata text +*.php text +*.pl text +*.py text +*.rb text +*.sass text +*.scm text +*.scss text +*.sql text +*.styl text +*.tag text +*.ts text +*.tsx text +*.xhtml text + +## DOCKER +*.dockerignore text +Dockerfile text + +## DOCUMENTATION +*.markdown text +*.mdwn text +*.mdown text +*.mkd text +*.mkdn text +*.mdtxt text +*.mdtext text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +copyright text +*COPYRIGHT* text +INSTALL text +license text +LICENSE text +NEWS text +readme text +*README* text +TODO text + +## TEMPLATES +*.dot text +*.ejs text +*.haml text +*.handlebars text +*.hbs text +*.hbt text +*.jade text +*.latte text +*.mustache text +*.njk text +*.phtml text +*.tmpl text +*.tpl text +*.twig text + +## LINTERS +.babelrc text +.csslintrc text +.eslintrc text +.htmlhintrc text +.jscsrc text +.jshintrc text +.jshintignore text +.prettierrc text +.stylelintrc text + +## CONFIGS +*.bowerrc text +*.cnf text +*.conf text +*.config text +.browserslistrc text +.editorconfig text +.gitattributes text +.gitconfig text +.gitignore text +.htaccess text +*.npmignore text +*.yaml text +*.yml text +browserslist text +Makefile text +makefile text + +## HEROKU +Procfile text +.slugignore text + +## GRAPHICS +*.ai binary +*.bmp binary +*.eps binary +*.gif binary +*.ico binary +*.jng binary +*.jp2 binary +*.jpg binary +*.jpeg binary +*.jpx binary +*.jxr binary +*.pdf binary +*.png binary +*.psb binary +*.psd binary +*.svg text +*.svgz binary +*.tif binary +*.tiff binary +*.wbmp binary +*.webp binary + +## AUDIO +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +## VIDEO +*.3gpp binary +*.3gp binary +*.as binary +*.asf binary +*.asx binary +*.fla binary +*.flv binary +*.m4v binary +*.mng binary +*.mov binary +*.mp4 binary +*.mpeg binary +*.mpg binary +*.ogv binary +*.swc binary +*.swf binary +*.webm binary + +## ARCHIVES +*.7z binary +*.gz binary +*.jar binary +*.rar binary +*.tar binary +*.zip binary + +## FONTS +*.ttf binary +*.eot binary +*.otf binary +*.woff binary +*.woff2 binary + +## EXECUTABLES +*.exe binary +*.pyc binary diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 477f273af..fef054cce 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,7 +2,7 @@ If you'd like to contribute to Pattern Lab Node, please do so! There is always a lot of ground to cover and something for your wheelhouse. -No pull request is too small. Check out any [help wanted 🆘](https://github.com/pattern-lab/patternlab-node/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted+%3Asos%3A%22) or [good first issues 🎓](https://github.com/pattern-lab/patternlab-node/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue+%3Amortar_board%3A%22)as a good way to get your feet wet, or add some more unit tests. +No pull request is too small. Check out any [help wanted 🆘](https://github.com/pattern-lab/patternlab-node/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted+%3Asos%3A%22) or [good first issues 🎓](https://github.com/pattern-lab/patternlab-node/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue+%3Amortar_board%3A%22) as a good way to get your feet wet, or add some more unit tests. ## Prerequisites @@ -18,7 +18,7 @@ nvm use <> The best way to make changes to the Pattern Lab Node core and test them is through an edition. * Fork this repository on Github. -* `npm install && npm run bootstrap` +* `yarn install && yarn run bootstrap` * Create a new branch in your fork and push your changes in that fork. * `cd packages/edition-node` * Test your changes with the edition's api @@ -28,15 +28,16 @@ The best way to make changes to the Pattern Lab Node core and test them is throu To ensure that developers can bootstrap the repo from a fresh clone, do this in your working copy: ```sh -git reset --hard && git clean -dfx && npm install && npm run bootstrap +git reset --hard && git clean -dfx && yarn install && yarn run bootstrap ``` This ensures that any changes you've made will still result in a clean and functional developer experience. **Note**: be sure you've committed any outstanding work before doing this -- it will blow away whatever's still outstanding, including anything staged but not commited. ## Guidelines -* _ALWAYS_ submit pull requests against the [dev branch](https://github.com/pattern-lab/patternlab-node/tree/dev). If this does not occur, I will first, try to redirect you gently, second, attempt to redirect the target branch myself, thirdly, port over your contribution manually if time allows, and/or lastly, close your pull request. If you have a major feature to stabilize over time, talk to @bmuenzenmeyer via an issue about making a dedicated `feature-branch` +* _ALWAYS_ submit pull requests against the [dev branch](https://github.com/pattern-lab/patternlab-node/tree/dev). If this does not occur, we will first, try to redirect you gently, second, attempt to redirect the target branch myself, thirdly, port over your contribution manually if time allows, and/or lastly, close your pull request. If you have a major feature to stabilize over time, ping @pattern-lab/trusted-committers via an issue about making a dedicated `feature-branch` * Keep your pull requests concise and limited to **ONE** substantive change at a time. This makes reviewing and testing so much easier. +* If it takes you considerable time to finish your work, submit a [draft pull request](https://github.blog/2019-02-14-introducing-draft-pull-requests/). This is Github's way to indicate work in progress but allows for feedback. * Commits should reference the issue you are adressing. For any Pull Request that you send, use the template provided. * Commits are best formatted using the [conventional commits pattern](https://conventionalcommits.org/). * If you can, add some unit tests using the existing patterns in the `.packages/core/test` directory @@ -47,13 +48,13 @@ This ensures that any changes you've made will still result in a clean and funct ## Coding style -Formatting is automated via [Prettier](https://prettier.io/), setup to run on precommit. We suggest [editor integration](https://prettier.io/docs/en/editors.html) for this and for eslint. Prettier is further configured within `.prettierrc`. Eslint validates syntax and usage that Prettier doesn't handle. Configuration for both is found within the `.eslintrc.json` file. +Formatting is automated via [Prettier](https://prettier.io/), setup to run on precommit. We suggest [editor integration](https://prettier.io/docs/en/editors.html) for this and for eslint. Prettier is further configured within `.prettierrc`. Eslint validates syntax and usage that Prettier doesn't handle. Configuration for both is found within the `.eslintrc.js` file. -The `.editorconfig` controls spaces / tabs within supported editors. Check out their [site](http://editorconfig.org/). +The `.editorconfig` controls spaces / tabs within supported editors. Check out their [site](https://editorconfig.org/). ## Tests -Add unit and integration tests if you can. It's always nice if our code coverage improves bit by bit (literally!). We are using [Node Tap](http://www.node-tap.org/) as test framework and [Rewire](https://github.com/jhnns/rewire) for mocking things like file system access. +Add unit and integration tests if you can. It's always nice if our code coverage improves bit by bit (literally!). We are using [Node Tap](https://node-tap.org/) as test framework and [Rewire](https://github.com/jhnns/rewire) for mocking things like file system access. ## Branching Scheme diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9e5ad2464..be5b0bd4c 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,8 @@ - + + + I am using Pattern Lab Node `vX.X.X` on `Windows | Mac | Linux`, with Node `vX.X.X`, using a `Gulp | Grunt | Vanilla | Custom` Edition. diff --git a/.github/gitgraph/README.md b/.github/gitgraph/README.md index 02cc14ca4..fda47c7b9 100644 --- a/.github/gitgraph/README.md +++ b/.github/gitgraph/README.md @@ -1,8 +1,8 @@ Generating a new graph ====================== -This folder uses http://gitgraphjs.com/ for generating the git graph model. +This folder uses https://www.nicoespeon.com/gitgraph.js for generating the git graph model. -1. Change `patternlab-flow.js` to your needs according to the documentation on http://gitgraphjs.com/ +1. Change `patternlab-flow.js` to your needs according to the documentation on https://www.nicoespeon.com/gitgraph.js 2. Open branching-scheme.html in browse, right click the graph and "Save as...". 3. Overwrite `/.github/branching-scheme.png` diff --git a/.github/gitgraph/branching-scheme.html b/.github/gitgraph/branching-scheme.html index 32d2ffb80..2af1dbf13 100644 --- a/.github/gitgraph/branching-scheme.html +++ b/.github/gitgraph/branching-scheme.html @@ -1,17 +1,26 @@ - - - - - - - - - - - + + + Branching scheme + + + + + + + + + diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..637f28bce --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,67 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: 'CodeQL' + +on: + push: + branches: [dev, master] + pull_request: + # The branches below must be a subset of the branches above + branches: [dev] + schedule: + - cron: '0 18 1 * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: ['javascript'] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 000000000..12752d1c8 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,28 @@ +name: Continuous Integration +on: [push, pull_request] + +jobs: + build: + name: Build & Test + runs-on: ubuntu-latest + steps: + - name: Check out the source code + uses: actions/checkout@v3 + + - name: Set up NodeJS + uses: actions/setup-node@v3 + with: + node-version: '16' + + - name: Setup the project + run: | + yarn run setup + npx lerna add @pattern-lab/engine-mustache --scope=@pattern-lab/core + npx lerna add @pattern-lab/engine-handlebars --scope=@pattern-lab/core + npx lerna add @pattern-lab/engine-underscore --scope=@pattern-lab/core + npx lerna add @pattern-lab/engine-liquid --scope=@pattern-lab/core + npx lerna add @pattern-lab/engine-twig --scope=@pattern-lab/core + npx lerna add @pattern-lab/engine-react --scope=@pattern-lab/core + + - name: Run Unit Tests + run: yarn run test diff --git a/.gitignore b/.gitignore index 74ad6c9b4..fd845fc5a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,14 @@ pattern_exports/ .DS_Store Thumbs.db .nyc_output/ -.vscode/ .idea/ +.env packages/core/test/public packages/*/public !packages/core/test/patterns/public/.gitkeep !packages/core/test/patterns/testDependencyGraph.json lerna-debug.log packages/edition-node-gulp/dependencyGraph.json +packages/uikit-workshop/dist + +yarn-error.log diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..f91359dc2 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install pretty-quick --staged diff --git a/.nvmrc b/.nvmrc index a13e7b9c8..59ea99ee6 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10.0.0 +16.20 diff --git a/.prettierignore b/.prettierignore index f25d454d3..bdfdbff8b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,7 +9,9 @@ packages/core/scripts/api.handlebars packages/core/scripts/events.handlebars packages/core/test/files/annotations.js packages/**/annotations.js -**/uikit-workshop/src/js/**/* *.json *.md -*.scss +**/reset.scss +**/_meta/_head.* +**/_meta/_foot.* +**/development-edition*/source/_patterns/** diff --git a/.prettierrc b/.prettierrc index c1a6f6671..3baced411 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,4 @@ { "singleQuote": true, - "trailingComma": "es5" + "endOfLine": "auto" } diff --git a/.travis.yml b/.travis.yml index e019fca93..3fb4c3593 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,24 @@ language: node_js +addons: + chrome: stable + before_install: - - phantomjs --version + # version lifted from `.nvmrc` + - nvm install + - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.19.0 + - export PATH="$HOME/.yarn/bin:$PATH" before_script: - - npm install -g lerna@3.2.1 - - npm run setup - - lerna add @pattern-lab/engine-mustache --scope=@pattern-lab/core - - lerna add @pattern-lab/engine-handlebars --scope=@pattern-lab/core - - lerna add @pattern-lab/engine-underscore --scope=@pattern-lab/core - - lerna add @pattern-lab/engine-liquid --scope=@pattern-lab/core - - lerna add @pattern-lab/engine-twig --scope=@pattern-lab/core - - lerna add @pattern-lab/engine-react --scope=@pattern-lab/core + - yarn run setup + - npx lerna add @pattern-lab/engine-mustache --scope=@pattern-lab/core + - npx lerna add @pattern-lab/engine-handlebars --scope=@pattern-lab/core + - npx lerna add @pattern-lab/engine-underscore --scope=@pattern-lab/core + - npx lerna add @pattern-lab/engine-liquid --scope=@pattern-lab/core + - npx lerna add @pattern-lab/engine-twig --scope=@pattern-lab/core + - npx lerna add @pattern-lab/engine-react --scope=@pattern-lab/core + +script: travis_wait yarn run test branches: only: diff --git a/.vscode/extensions.adoc b/.vscode/extensions.adoc new file mode 100644 index 000000000..a49aa22e9 --- /dev/null +++ b/.vscode/extensions.adoc @@ -0,0 +1,10 @@ += Extensions configuration + +See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. +Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + +List of extensions which should be recommended for users of this workspace: +`"recommendations"`` + +List of extensions recommended by VS Code that should not be recommended for users of this workspace: +`"unwantedRecommendations"`` diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..6d97db0dc --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["editorconfig.editorconfig", "henrynguyen5-vsc.vsc-nvm"] +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..52f197a05 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,812 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + + +### Features + +* **engine-twig-php:** update @basalt/twig-renderer to v3.0.1 using Twig v3.7.1 ([#1499](https://github.com/pattern-lab/patternlab-node/issues/1499)) ([2e5c9e1](https://github.com/pattern-lab/patternlab-node/commit/2e5c9e1c6a3318ba1cd3765d448c181e4a3a9a27)), closes [#1496](https://github.com/pattern-lab/patternlab-node/issues/1496) [#1496](https://github.com/pattern-lab/patternlab-node/issues/1496) + + + + + +## [6.0.3](https://github.com/pattern-lab/patternlab-node/compare/v6.0.2...v6.0.3) (2023-03-12) + + +### Bug Fixes + +* subitems menu height restricted only for horizontal mode ([#1492](https://github.com/pattern-lab/patternlab-node/issues/1492)) ([e65f294](https://github.com/pattern-lab/patternlab-node/commit/e65f294d9cbf032fd7fd03d9f957500949db5440)) + + + + + +## [6.0.2](https://github.com/pattern-lab/patternlab-node/compare/v6.0.1...v6.0.2) (2023-02-26) + + +### Bug Fixes + +* **starterkit-twig-demo:** pages not rendering pattern-specific data from json ([#1490](https://github.com/pattern-lab/patternlab-node/issues/1490)) ([1c878df](https://github.com/pattern-lab/patternlab-node/commit/1c878dfa35d549f23e199b3e235ff79cb471ac86)), closes [#1486](https://github.com/pattern-lab/patternlab-node/issues/1486) + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + + +### Bug Fixes + +* **twig engine:** startup and running problems ([#1478](https://github.com/pattern-lab/patternlab-node/issues/1478)) ([e5a1904](https://github.com/pattern-lab/patternlab-node/commit/e5a19049f083315939406677b1c0480f4b420569)) + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + + +### Bug Fixes + +* **engine-twig-php:** twig include function syntax not matched by findPartials ([#1472](https://github.com/pattern-lab/patternlab-node/issues/1472)) ([3677539](https://github.com/pattern-lab/patternlab-node/commit/3677539409ac41dfee71d90cc429be5c92890838)), closes [#1471](https://github.com/pattern-lab/patternlab-node/issues/1471) +* **engine-twig:** twig include function syntax not matched by findPartials ([#1473](https://github.com/pattern-lab/patternlab-node/issues/1473)) ([cfa792b](https://github.com/pattern-lab/patternlab-node/commit/cfa792b2753d9f9f1840e08d55983c6c051b01fd)), closes [#1471](https://github.com/pattern-lab/patternlab-node/issues/1471) +* hogan to handlebars migration leftovers ([#1461](https://github.com/pattern-lab/patternlab-node/issues/1461)) ([566485a](https://github.com/pattern-lab/patternlab-node/commit/566485a5c20d739bfe9c77c11b8ddfa09e292481)) +* HTML structure ([#1450](https://github.com/pattern-lab/patternlab-node/issues/1450)) ([8567e2b](https://github.com/pattern-lab/patternlab-node/commit/8567e2b218a4ef9df0e359ca77229dda54712200)) +* js error ([#1475](https://github.com/pattern-lab/patternlab-node/issues/1475)) ([209b9a1](https://github.com/pattern-lab/patternlab-node/commit/209b9a15871354ac4ae982d93d6be03272799005)), closes [/github.com/pattern-lab/patternlab-node/pull/1102/files#diff-9111c2e0138c935342632437be7178f25322b8f5c86431f2b85f4fe760d32980L96-R111](https://github.com//github.com/pattern-lab/patternlab-node/pull/1102/files/issues/diff-9111c2e0138c935342632437be7178f25322b8f5c86431f2b85f4fe760d32980L96-R111) +* updated base template to handlebars ([#1463](https://github.com/pattern-lab/patternlab-node/issues/1463)) ([c69c658](https://github.com/pattern-lab/patternlab-node/commit/c69c658d06dab9a1bf04f77e7902ff3f07c94c3e)) + + +### Features + +* activate prettier for scss ([#1468](https://github.com/pattern-lab/patternlab-node/issues/1468)) ([fac6ad4](https://github.com/pattern-lab/patternlab-node/commit/fac6ad4be48c95eccfe890a280cad441ee84f677)) +* **docs:** added plugin ([#1469](https://github.com/pattern-lab/patternlab-node/issues/1469)) ([535c5f0](https://github.com/pattern-lab/patternlab-node/commit/535c5f0805936a25eeddde0e360cb6000c000b1b)) + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + + +### Features + +* **engine-twig:** add custom twing extensions ([#1435](https://github.com/pattern-lab/patternlab-node/issues/1435)) ([c32a45c](https://github.com/pattern-lab/patternlab-node/commit/c32a45c02e3b71bb841e7ea15cae000a68857df3)), closes [#1230](https://github.com/pattern-lab/patternlab-node/issues/1230) [#1230](https://github.com/pattern-lab/patternlab-node/issues/1230) +* integrate @hadl/patternlab-plugin-pattern-wrap into core ([#1433](https://github.com/pattern-lab/patternlab-node/issues/1433)) ([414e038](https://github.com/pattern-lab/patternlab-node/commit/414e0383732b4bc4682981000908d1e0d1292703)), closes [#1432](https://github.com/pattern-lab/patternlab-node/issues/1432) [#1432](https://github.com/pattern-lab/patternlab-node/issues/1432) + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + + +### Bug Fixes + +* code scanning alert ([#1442](https://github.com/pattern-lab/patternlab-node/issues/1442)) ([749a3e7](https://github.com/pattern-lab/patternlab-node/commit/749a3e722249846c522e3f7de6e73b5afa8531b1)) +* div isn't allowed in button elements ([#1438](https://github.com/pattern-lab/patternlab-node/issues/1438)) ([e5c6950](https://github.com/pattern-lab/patternlab-node/commit/e5c6950e6218df99f9d9d35388c36a0130236f28)) +* twig logo is rendered as "NaN" ([#1434](https://github.com/pattern-lab/patternlab-node/issues/1434)) ([ab6b133](https://github.com/pattern-lab/patternlab-node/commit/ab6b133019d9dfa3816e8fc9a9caa7b547e19097)), closes [#1407](https://github.com/pattern-lab/patternlab-node/issues/1407) + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + + +### Bug Fixes + +* transformed asset types is ignored ([#1426](https://github.com/pattern-lab/patternlab-node/issues/1426)) ([8cbe189](https://github.com/pattern-lab/patternlab-node/commit/8cbe189d45afaa753ce6de41bdd9de1596e074f3)), closes [#1339](https://github.com/pattern-lab/patternlab-node/issues/1339) + + +### Features + +* remove sandbox attribute from iframe ([#1422](https://github.com/pattern-lab/patternlab-node/issues/1422)) ([4335660](https://github.com/pattern-lab/patternlab-node/commit/4335660bac6f87618baaef9d773e00d7e80c6eec)) + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package patternlab-node-main + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + + +### Bug Fixes + +* **annotations:** displaying annotation tooltips correctly ([#1406](https://github.com/pattern-lab/patternlab-node/issues/1406)) ([3f33ce5](https://github.com/pattern-lab/patternlab-node/commit/3f33ce5c51f2f7a6afd86d3500b7659afd0198e6)), closes [#2](https://github.com/pattern-lab/patternlab-node/issues/2) [#1](https://github.com/pattern-lab/patternlab-node/issues/1) +* **annotations:** hiding those correctly ([#1415](https://github.com/pattern-lab/patternlab-node/issues/1415)) ([ef0a60f](https://github.com/pattern-lab/patternlab-node/commit/ef0a60fcc8656acc6d83bb0723c02a658f7ff1f3)) + + + + + +## [5.15.7](https://github.com/pattern-lab/patternlab-node/compare/v5.15.6...v5.15.7) (2021-12-07) + +**Note:** Version bump only for package patternlab-node-main + + + + + +## [5.15.6](https://github.com/pattern-lab/patternlab-node/compare/v5.15.5...v5.15.6) (2021-12-07) + +**Note:** Version bump only for package patternlab-node-main + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + + +### Bug Fixes + +* corrected some github urls ([#1388](https://github.com/pattern-lab/patternlab-node/issues/1388)) ([7f37e9d](https://github.com/pattern-lab/patternlab-node/commit/7f37e9d56b553dc4be53590766c0fc6251458829)) + + +### Features + +* define initial viewport ([#1386](https://github.com/pattern-lab/patternlab-node/issues/1386)) ([6fa630e](https://github.com/pattern-lab/patternlab-node/commit/6fa630e2353ed68295550e59c31148269f3b7cd0)) + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + + +### Bug Fixes + +* corrected some github urls ([#1388](https://github.com/pattern-lab/patternlab-node/issues/1388)) ([7f37e9d](https://github.com/pattern-lab/patternlab-node/commit/7f37e9d56b553dc4be53590766c0fc6251458829)) + + +### Features + +* define initial viewport ([#1386](https://github.com/pattern-lab/patternlab-node/issues/1386)) ([6fa630e](https://github.com/pattern-lab/patternlab-node/commit/6fa630e2353ed68295550e59c31148269f3b7cd0)) + + + + + +## [5.15.3](https://github.com/pattern-lab/patternlab-node/compare/v5.15.2...v5.15.3) (2021-11-21) + + +### Bug Fixes + +* **docs:** tiles z-index to not overlay the menu anymore ([#1370](https://github.com/pattern-lab/patternlab-node/issues/1370)) ([384dc89](https://github.com/pattern-lab/patternlab-node/commit/384dc8900ee5768f5a260fd00fe03d11ae047484)) +* **handlebars-demo:** move and modify the icon files ([#1377](https://github.com/pattern-lab/patternlab-node/issues/1377)) ([7c66f8a](https://github.com/pattern-lab/patternlab-node/commit/7c66f8ad4cd15e0a814f9808d0fbca727903aeb5)) + + +### Features + +* **vs-code:** added recommendations ([#1375](https://github.com/pattern-lab/patternlab-node/issues/1375)) ([cfa74c0](https://github.com/pattern-lab/patternlab-node/commit/cfa74c0d09c3aae78ef10654f48749a568f3e30d)) +* ensure consistent line endings across files ([#1372](https://github.com/pattern-lab/patternlab-node/issues/1372)) ([57efccb](https://github.com/pattern-lab/patternlab-node/commit/57efccb895f142d8a18e774d7b7c01b2f1266737)) + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/compare/v5.15.1...v5.15.2) (2021-11-03) + + +### Bug Fixes + +* **core:** Subgroup cannot be hidden ([#1368](https://github.com/pattern-lab/patternlab-node/issues/1368)) ([3ce13ab](https://github.com/pattern-lab/patternlab-node/commit/3ce13abffaab2810194003aeca88be671fedd38f)) + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/compare/v5.15.0...v5.15.1) (2021-10-16) + + +### Bug Fixes + +* **docs:** use "UIKits" instead of "StyleguideKits" ([#1345](https://github.com/pattern-lab/patternlab-node/issues/1345)) ([a2885ea](https://github.com/pattern-lab/patternlab-node/commit/a2885ea738c2d807dd99c6749ac6e6437d8d3e7e)) +* **initialize:** updating no-emit-webpack-plugin dependency [#1348](https://github.com/pattern-lab/patternlab-node/issues/1348) ([#1349](https://github.com/pattern-lab/patternlab-node/issues/1349)) ([a884897](https://github.com/pattern-lab/patternlab-node/commit/a884897cf9f98b61c9bdd20acf7e079de0782f10)) +* **node16:** prevent warning on installation process ([#1352](https://github.com/pattern-lab/patternlab-node/issues/1352)) ([d58e4c6](https://github.com/pattern-lab/patternlab-node/commit/d58e4c6f2979f5e0bba9a14e17e0dbc4afc64f75)) + + +### Features + +* added https description to the docs ([#1355](https://github.com/pattern-lab/patternlab-node/issues/1355)) ([4118f74](https://github.com/pattern-lab/patternlab-node/commit/4118f740810842b16cf86b9ee28bda2a623aa9c7)) + + +### Reverts + +* Revert "refactor: optimized engines directory retrieval (#1359)" (#1363) ([a275d36](https://github.com/pattern-lab/patternlab-node/commit/a275d36c50c3846fc51c78baf6e11dba5309f5dc)), closes [#1359](https://github.com/pattern-lab/patternlab-node/issues/1359) [#1363](https://github.com/pattern-lab/patternlab-node/issues/1363) + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/compare/v5.14.3...v5.15.0) (2021-07-01) + + +### Bug Fixes + +* **live-server:** testing ([#1331](https://github.com/pattern-lab/patternlab-node/issues/1331)) ([2b2e1b1](https://github.com/pattern-lab/patternlab-node/commit/2b2e1b1c2426ab578dc014ea99df520d17a7db92)) + + +### Features + +* **docs:** adding a sitemap.xml ([#1329](https://github.com/pattern-lab/patternlab-node/issues/1329)) ([0a7fd95](https://github.com/pattern-lab/patternlab-node/commit/0a7fd95d5f1c3ce690bbe89cc30580ff58d1ab9c)) +* **documentation:** added (sub)groups documentation again [#1262](https://github.com/pattern-lab/patternlab-node/issues/1262) ([#1334](https://github.com/pattern-lab/patternlab-node/issues/1334)) ([9fac269](https://github.com/pattern-lab/patternlab-node/commit/9fac2699d2f6c64c4544e8e4d8e18c1a1ce7e49f)) + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/compare/v5.14.2...v5.14.3) (2021-05-17) + + +### Bug Fixes + +* **pseudopatterns:** use the template instead of the pseudo data file for template rendering [#1308](https://github.com/pattern-lab/patternlab-node/issues/1308) ([#1312](https://github.com/pattern-lab/patternlab-node/issues/1312)) ([7ecca69](https://github.com/pattern-lab/patternlab-node/commit/7ecca69bcfed4060d17390b76562e5f468b4a897)) + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/compare/v5.14.1...v5.14.2) (2021-03-28) + + +### Bug Fixes + +* **core:** ReadDocumentation throw error on older node versions ([#1295](https://github.com/pattern-lab/patternlab-node/issues/1295)) ([399d0e1](https://github.com/pattern-lab/patternlab-node/commit/399d0e118ab77a414a926b078da9abbcb5347969)) +* **twig:** starter-kit-twig urls are incorrect on npm ([#1297](https://github.com/pattern-lab/patternlab-node/issues/1297)) ([4256d6b](https://github.com/pattern-lab/patternlab-node/commit/4256d6b13f9c2cfadf7620b0cb744cf71c3257f5)) + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/compare/v5.14.0...v5.14.1) (2021-02-19) + + +### Bug Fixes + +* **demopage:** switched to HTTPS URLs for image placeholders ([#1289](https://github.com/pattern-lab/patternlab-node/issues/1289)) ([e09bf6a](https://github.com/pattern-lab/patternlab-node/commit/e09bf6aae9bad99365b5a01381e0df6de9ddeafe)) + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package patternlab-node + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package patternlab-node-main + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package patternlab-node-main + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package patternlab-node-main + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package patternlab-node-main + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package patternlab-node + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.1) (2020-06-28) + + +### Bug Fixes + +* update Viewport Size toggle to better handle async-loaded ishControl data + prevent rendering errors ([b937706](https://github.com/pattern-lab/patternlab-node/commit/b93770669c6f723128ba68e522c9398cc1d2d70c)) +* update Webpack config to point to the patched version of preact-dom ([d3660b7](https://github.com/pattern-lab/patternlab-node/commit/d3660b78bc0a74c52ed85b69b023c612b789c318)) +* update yarn.lock ([dca1948](https://github.com/pattern-lab/patternlab-node/commit/dca19489b85f715de3ade2294fa49df89b8bb59f)) +* visually hide NavToggle icon text; fix for visual regression after merging down https://github.com/pattern-lab/patternlab-node/pull/1227 ([3a2ad9f](https://github.com/pattern-lab/patternlab-node/commit/3a2ad9f12d83b6d21dcca62e89d944a6a46342f6)) +* **docs:** corrected a URL ([26ede14](https://github.com/pattern-lab/patternlab-node/commit/26ede14a6eafe8649cbc6b0076d84f1d323c3e20)) +* **docs:** fixed css code for custom patternstates color ([8995241](https://github.com/pattern-lab/patternlab-node/commit/89952416162c01d1e3e05221ce58a7755544131c)), closes [#1216](https://github.com/pattern-lab/patternlab-node/issues/1216) +* **docs:** headlines styling breaks in edge cases [#1158](https://github.com/pattern-lab/patternlab-node/issues/1158) ([d8244a2](https://github.com/pattern-lab/patternlab-node/commit/d8244a2d307b0a81d0846491f8c5a12e0ae167a5)) +* **patternflyouts:** preventing horizontal scrollbar in pattern flyouts in Edge 18 [#1124](https://github.com/pattern-lab/patternlab-node/issues/1124) ([63300bc](https://github.com/pattern-lab/patternlab-node/commit/63300bc00ee797e38bfdb73fdc7694c188a423dc)) +* **patternstate:** added css color for pattern state "inprogress" [#1216](https://github.com/pattern-lab/patternlab-node/issues/1216) ([856bcda](https://github.com/pattern-lab/patternlab-node/commit/856bcda150239928bb5e8719246b97e9fa366468)) +* **resetcss:** selector in uikit-workshop [#1109](https://github.com/pattern-lab/patternlab-node/issues/1109) ([6893b7c](https://github.com/pattern-lab/patternlab-node/commit/6893b7cb5478309d4fdab0121edba3921718bd69)) +* enable partial build via option ([8aaa533](https://github.com/pattern-lab/patternlab-node/commit/8aaa53398563ade14123c481bf509f9ee0c768f5)) +* enable partial build via option ([4b9dbf9](https://github.com/pattern-lab/patternlab-node/commit/4b9dbf9095bfb8bfd2360b310dd7395dbfe3cf98)) + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.0) (2020-06-28) + + +### Bug Fixes + +* update Viewport Size toggle to better handle async-loaded ishControl data + prevent rendering errors ([b937706](https://github.com/pattern-lab/patternlab-node/commit/b93770669c6f723128ba68e522c9398cc1d2d70c)) +* update Webpack config to point to the patched version of preact-dom ([d3660b7](https://github.com/pattern-lab/patternlab-node/commit/d3660b78bc0a74c52ed85b69b023c612b789c318)) +* visually hide NavToggle icon text; fix for visual regression after merging down https://github.com/pattern-lab/patternlab-node/pull/1227 ([3a2ad9f](https://github.com/pattern-lab/patternlab-node/commit/3a2ad9f12d83b6d21dcca62e89d944a6a46342f6)) +* **docs:** corrected a URL ([26ede14](https://github.com/pattern-lab/patternlab-node/commit/26ede14a6eafe8649cbc6b0076d84f1d323c3e20)) +* **docs:** fixed css code for custom patternstates color ([8995241](https://github.com/pattern-lab/patternlab-node/commit/89952416162c01d1e3e05221ce58a7755544131c)), closes [#1216](https://github.com/pattern-lab/patternlab-node/issues/1216) +* **docs:** headlines styling breaks in edge cases [#1158](https://github.com/pattern-lab/patternlab-node/issues/1158) ([d8244a2](https://github.com/pattern-lab/patternlab-node/commit/d8244a2d307b0a81d0846491f8c5a12e0ae167a5)) +* **patternflyouts:** preventing horizontal scrollbar in pattern flyouts in Edge 18 [#1124](https://github.com/pattern-lab/patternlab-node/issues/1124) ([63300bc](https://github.com/pattern-lab/patternlab-node/commit/63300bc00ee797e38bfdb73fdc7694c188a423dc)) +* **patternstate:** added css color for pattern state "inprogress" [#1216](https://github.com/pattern-lab/patternlab-node/issues/1216) ([856bcda](https://github.com/pattern-lab/patternlab-node/commit/856bcda150239928bb5e8719246b97e9fa366468)) +* **resetcss:** selector in uikit-workshop [#1109](https://github.com/pattern-lab/patternlab-node/issues/1109) ([6893b7c](https://github.com/pattern-lab/patternlab-node/commit/6893b7cb5478309d4fdab0121edba3921718bd69)) +* enable partial build via option ([8aaa533](https://github.com/pattern-lab/patternlab-node/commit/8aaa53398563ade14123c481bf509f9ee0c768f5)) +* enable partial build via option ([4b9dbf9](https://github.com/pattern-lab/patternlab-node/commit/4b9dbf9095bfb8bfd2360b310dd7395dbfe3cf98)) + + + + + +## [5.10.2](https://github.com/pattern-lab/patternlab-node/compare/v5.10.1...v5.10.2) (2020-05-24) + + +### Bug Fixes + +* update link to new PL docs homepage ([831b467](https://github.com/pattern-lab/patternlab-node/commit/831b467c57b9259c32ce3d3ddf366fe1867a48a9)) + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package pl-node + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** google lighthouse error - bg and text contrast ratio [#1197](https://github.com/pattern-lab/patternlab-node/issues/1197) ([f43978a](https://github.com/pattern-lab/patternlab-node/commit/f43978a3a121b661cfbf763ba72bcda2c36a5d3a)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([8dc020a](https://github.com/pattern-lab/patternlab-node/commit/8dc020a217b51cfafdd62ceca95fc42811a6c285)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([f557fdd](https://github.com/pattern-lab/patternlab-node/commit/f557fddeda640d88c7267d9d5fba8e8cc5e07929)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([0023a91](https://github.com/pattern-lab/patternlab-node/commit/0023a910126a635006c1ad468a412af0e93338fb)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([c9635ec](https://github.com/pattern-lab/patternlab-node/commit/c9635ec2d9eb700b23188d5c72b83b3d16e6deda)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([f56ad39](https://github.com/pattern-lab/patternlab-node/commit/f56ad3951ea0319a43f0b1aeabba0d3ad96c5553)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([cae9420](https://github.com/pattern-lab/patternlab-node/commit/cae94208c52e4068430e048e729f4ff97847715a)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([84138c3](https://github.com/pattern-lab/patternlab-node/commit/84138c36cdfe5b9a38b34e32b177a0416b077716)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([374c103](https://github.com/pattern-lab/patternlab-node/commit/374c103a59504ba239b16680f86a89b4d95e304f)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([cb0fcdb](https://github.com/pattern-lab/patternlab-node/commit/cb0fcdb5ad8504f9d78d4d5e040afa408aa2c356)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([48de8c2](https://github.com/pattern-lab/patternlab-node/commit/48de8c2e134a61c0b4440375254bc9590a3e2563)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([363f22c](https://github.com/pattern-lab/patternlab-node/commit/363f22c643239ef4ca48d6f5942111604fda5ead)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([487cc78](https://github.com/pattern-lab/patternlab-node/commit/487cc783388043ec16ab1e54a3bfd8490038d058)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([571017f](https://github.com/pattern-lab/patternlab-node/commit/571017ffafa2cf6e8fa01b7ea7effc88922b05d1)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([420e829](https://github.com/pattern-lab/patternlab-node/commit/420e8293c033557ede073bc13e68955a450a3c8e)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([b4eb12e](https://github.com/pattern-lab/patternlab-node/commit/b4eb12e68ceb402964a7e303610e5b0c008876ba)) +* Contribution guidelines should refer to yarn ([c30cc81](https://github.com/pattern-lab/patternlab-node/commit/c30cc81a3e155072774438304b73d58b6635876d)) +* **uikitworkshop:** preventing cropping pattern parts [#1174](https://github.com/pattern-lab/patternlab-node/issues/1174) ([6a67d03](https://github.com/pattern-lab/patternlab-node/commit/6a67d039048129e9837c3b6eb3e195ed2e86a815)) + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/compare/v5.9.2...v5.9.3) (2020-05-01) + + +### Bug Fixes + +* **plugintabs:** enabling multiple file formats [#1163](https://github.com/pattern-lab/patternlab-node/issues/1163) ([bb5e817](https://github.com/pattern-lab/patternlab-node/commit/bb5e8179e6b8553a6e1af0bede26db412b6c0b68)) +* adjust UIKit Nav updates to account for the noViewAll config variation ([73eac97](https://github.com/pattern-lab/patternlab-node/commit/73eac976461f4e587b0c30668942c4895aea319f)) +* make sure the top-level Dropdown menus always open/close ([7a8b418](https://github.com/pattern-lab/patternlab-node/commit/7a8b418bfcbd200ef8b2802b1a07964a9995bf9f)) +* only allow one top level nav item to be open at a time while rendering as a dropdown menu ([409bef3](https://github.com/pattern-lab/patternlab-node/commit/409bef37165260d9b728013ac33e7aa67541c832)) +* re-try Netlify preview to debug local vs prod rendering differences ([6da41a1](https://github.com/pattern-lab/patternlab-node/commit/6da41a14feea034f891c745dfeb062fa3b196235)) +* Update dependency on twing JS engine ([cfe88c6](https://github.com/pattern-lab/patternlab-node/commit/cfe88c6cdbf2219b9955eaa0ffcfc0e4a7683511)) +* **cli:** fix test script glob ([ff18eb5](https://github.com/pattern-lab/patternlab-node/commit/ff18eb51ce24fc5423b009168e85ede366069139)) + + + + + +## [5.9.2](https://github.com/pattern-lab/patternlab-node/compare/v5.9.1...v5.9.2) (2020-04-24) + +**Note:** Version bump only for package pl-node + + + + + +## [5.9.1](https://github.com/pattern-lab/patternlab-node/compare/v5.9.0...v5.9.1) (2020-04-24) + + +### Bug Fixes + +* **cli:** ensure specified directory exists prior to scaffold ([cc3b696](https://github.com/pattern-lab/patternlab-node/commit/cc3b69624d486c94ee3b1f4b1bbb0334a514fa59)) + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/compare/v5.8.0...v5.9.0) (2020-04-24) + + +### Bug Fixes + +* **cli:** set current working directory before scaffolded npm init ([6d2186d](https://github.com/pattern-lab/patternlab-node/commit/6d2186d8e8a74634198a4474ca8ae83221dd70a9)) +* **core:** do not warn about uikit-polyfills ([6bb68e7](https://github.com/pattern-lab/patternlab-node/commit/6bb68e763769969546542bf7aaf6d1f4235c6622)) +* actually exit build when Twig render fails ([5d28a24](https://github.com/pattern-lab/patternlab-node/commit/5d28a24a53011396289c1e29e0a715cd82470185)) +* Update packages/engine-twig-php/lib/engine_twig_php.js ([c67d50e](https://github.com/pattern-lab/patternlab-node/commit/c67d50ebb5d69816b7514e85f129f8ecde984ad3)) + + +### Features + +* **docs:** yarnify ([5a47dc7](https://github.com/pattern-lab/patternlab-node/commit/5a47dc7b90dc5c43c12a51143b41943dcbd8564c)) +* **README:** add netlify badges ([941df8a](https://github.com/pattern-lab/patternlab-node/commit/941df8a59b6b75bc1255646005f329e40be68106)) + + + + + +# [5.8.0](https://github.com/pattern-lab/patternlab-node/compare/v5.7.2...v5.8.0) (2020-04-03) + + +### Bug Fixes + +* the namespace notation should not be mixed with PatternLab shorthand pattern naming & name is not defined in the textarea macro ([8250fe8](https://github.com/pattern-lab/patternlab-node/commit/8250fe88231d03735424d597eae40496da2cb48c)) +* Updated the README to reflect which issues are resolved. ([d90c3c4](https://github.com/pattern-lab/patternlab-node/commit/d90c3c4605f9a5bcd1153996e3f4d1a17d58bd92)) + + +### Features + +* switch engine-twig to use twing rather than node-twig ([daca95c](https://github.com/pattern-lab/patternlab-node/commit/daca95c4ffa48916fb6c67c5184bde9b624acd76)) + + + + + +## [5.7.2](https://github.com/pattern-lab/patternlab-node/compare/v5.7.1...v5.7.2) (2020-03-24) + + +### Bug Fixes + +* update iframe resizer UI to be hidden when iframe is full width ([9797c1a](https://github.com/pattern-lab/patternlab-node/commit/9797c1a047d746d21b88a1f57b57f618a03a54df)) + + + + + +## [5.7.1](https://github.com/pattern-lab/patternlab-node/compare/v5.7.0...v5.7.1) (2020-02-24) + + +### Bug Fixes + +* update twig-renderer ([46f53b7](https://github.com/pattern-lab/patternlab-node/commit/46f53b79f8bb0bb64a9c55fd32f29459cea6e28c)) + + + + + +# [5.7.0](https://github.com/pattern-lab/patternlab-node/compare/v5.6.0...v5.7.0) (2020-02-17) + + +### Features + +* **cli:** make options more user friendly ([ad845b3](https://github.com/pattern-lab/patternlab-node/commit/ad845b394ef81f90895ebb5bc6f12cc608e5e3d4)) + + + + + +# [5.6.0](https://github.com/pattern-lab/patternlab-node/compare/v5.5.0...v5.6.0) (2020-01-18) + + +### Bug Fixes + +* a11y fix on text contrast ([6d75b22](https://github.com/pattern-lab/patternlab-node/commit/6d75b226ce27228025b2915e5d402f7080faee31)) +* a11y issue on a missing description of that complementary icon ([4f13807](https://github.com/pattern-lab/patternlab-node/commit/4f13807cb93df33435088de3a51170b9c4515889)) + + +### Features + +* pass additional configuration into twig-php engine ([dff5a78](https://github.com/pattern-lab/patternlab-node/commit/dff5a7830918fa46e2692d9f9daed4121f803461)) + + + + + + +# [5.5.0](https://github.com/pattern-lab/patternlab-node/compare/v5.4.2...v5.5.0) (2019-12-19) + + +### Features + +* upgrade Twig to use new filter, map, reduce ([4218a5a](https://github.com/pattern-lab/patternlab-node/commit/4218a5a04b06027548afd9f417486297dd25fef8)) + + + + + +## [5.4.2](https://github.com/pattern-lab/patternlab-node/compare/v5.4.1...v5.4.2) (2019-11-27) + +**Note:** Version bump only for package pl-node-pr + + + + + +## [5.4.1](https://github.com/pattern-lab/patternlab-node/compare/v5.4.0...v5.4.1) (2019-11-26) + + +### Bug Fixes + +* temp workaround to address instance where the latest version of Edge supports ES modules but NOT Custom Elements ([ada3d82](https://github.com/pattern-lab/patternlab-node/commit/ada3d829019345fd33ed949f306972efdcb4fa57)) + + + + + +# [5.4.0](https://github.com/pattern-lab/patternlab-node/compare/v5.3.3...v5.4.0) (2019-11-26) + + +### Bug Fixes + +* re-add popstate listener ([6dbbd6a](https://github.com/pattern-lab/patternlab-node/commit/6dbbd6aae3709cc17544c12dd10588120eb9e71a)) +* **script:** remove quotes around starterkit ([e4897fb](https://github.com/pattern-lab/patternlab-node/commit/e4897fb6e4d4cd0985ab72397abd03ff04be514b)) +* add a new method to check if PL is currently compiling + add new method to get the config PL is using ([26e886c](https://github.com/pattern-lab/patternlab-node/commit/26e886c93db5d135c91de648724f7278c4d5b3e9)) +* check if dependency graph file exists before trying to remove ([f9af6a9](https://github.com/pattern-lab/patternlab-node/commit/f9af6a95025a22041e7ff8a4bfb19e4727385e98)) +* comment out example config to disable viewAll links ([ddb3fad](https://github.com/pattern-lab/patternlab-node/commit/ddb3fad5770d1d66432c4b583ae9af09a3a47d48)) + + +### Features + +* add the ability to disable Pattern Lab viewall links in the navigation ([156e609](https://github.com/pattern-lab/patternlab-node/commit/156e609a92e7f7e7ebd8f4f5cd77b5d695db8bad)) +* major improvements to local UIKit workflow ([4dc9173](https://github.com/pattern-lab/patternlab-node/commit/4dc9173a5a44b422e9677824de3728048b7c4f05)) +* test adding cross-env to Twig Edition test ([3f8bb01](https://github.com/pattern-lab/patternlab-node/commit/3f8bb01bc4e96a0aba61c213ea1619c02593defc)) + + + + + +## [5.3.3](https://github.com/pattern-lab/patternlab-node/compare/v5.3.2...v5.3.3) (2019-11-22) + + +### Bug Fixes + +* simplify overflow fix ([378cf42](https://github.com/pattern-lab/patternlab-node/commit/378cf4282a3e5b4f597287eb538270e3358c8c69)) +* testing potential FF fix for https://github.com/pattern-lab/patternlab-node/issues/1100 ([613bba1](https://github.com/pattern-lab/patternlab-node/commit/613bba104f2082be507938db78f1db7a07f6b8be)) + + + + + + +## [5.3.2](https://github.com/pattern-lab/patternlab-node/compare/v5.3.1...v5.3.2) (2019-11-14) + +**Note:** Version bump only for package pl-node + + + + + +## [5.3.1](https://github.com/pattern-lab/patternlab-node/compare/v5.3.0...v5.3.1) (2019-11-13) + + +### Bug Fixes + +* CSS fix to properly highlight the correct active page / link in the Nav; improve dropdown open / close animation ([ec4ab84](https://github.com/pattern-lab/patternlab-node/commit/ec4ab84ddc8007796c9012a3f493822d76f039a7)) +* small UI fixes for the sticky Tabs header on smaller screens + drawer content collapsing on smaller screens + better handling of Nav link cleanup when changing pages ([347e2fe](https://github.com/pattern-lab/patternlab-node/commit/347e2fe29a78a1d168005a07c656b4f9f1124c7f)) +* tweak header and drawer padding when viewing on a device with curved edges ([98e9baf](https://github.com/pattern-lab/patternlab-node/commit/98e9baf649eceb9124218a924b6b08097b910e86)) +* uikit fixes and minor CSS updates intended for the v5.3.0 release ([26c4ced](https://github.com/pattern-lab/patternlab-node/commit/26c4ceddaae09fa4fa4873f092c924274498c5da)) + + + + + +# [5.3.0](https://github.com/pattern-lab/patternlab-node/compare/v5.2.0...v5.3.0) (2019-11-13) + + +### Bug Fixes + +* add PluginTab workaround for Safari ([2fa9367](https://github.com/pattern-lab/patternlab-node/commit/2fa936769be65484af52f242dca2536a3382462c)) +* **core:** re-add cleanPublic fix ([c100bbc](https://github.com/pattern-lab/patternlab-node/commit/c100bbca3f339e9132acb9c482e98c1c8a66b8b5)) +* **plugin-tab:** defensively call addPanels ([b82bd12](https://github.com/pattern-lab/patternlab-node/commit/b82bd129fdbe48de95b62d75fb7fe95cea896b7e)) +* port over missing UIKit Sass that wasn't added in the original PR ([f7659e6](https://github.com/pattern-lab/patternlab-node/commit/f7659e64d0eee13be20921dd5afc48ac20ae93e6)) + + +### Features + +* port latest UIKit updates + fixes upstream ([d07952c](https://github.com/pattern-lab/patternlab-node/commit/d07952cb07e3792b995dda2e589262ecf4153fdc)) + + + + + +# [5.2.0](https://github.com/pattern-lab/patternlab-node/compare/v5.1.0...v5.2.0) (2019-11-12) + + +### Bug Fixes + +* **deploy:** add setup command ([7c1d8d1](https://github.com/pattern-lab/patternlab-node/commit/7c1d8d14842a467bb301e2ede2ec83074ff35ae2)) +* add missing $ ([c95a06e](https://github.com/pattern-lab/patternlab-node/commit/c95a06ece78631b068f8721666caf33452e57a7a)) +* address bug causing viewport width to progressively decrease in size when resizing your screen / refreshing on certain devices ([41b11af](https://github.com/pattern-lab/patternlab-node/commit/41b11af8aaaf066fcf99abd2513eae8706122d32)) +* configure the Logo's `altText` config option when used as an HTML attribute ([ade34a2](https://github.com/pattern-lab/patternlab-node/commit/ade34a29435f5112f0449ad020bee7e9dc2c81e1)) +* fix classname typo ([da3c5f1](https://github.com/pattern-lab/patternlab-node/commit/da3c5f144d22b1ac3ad99680a264433d4438ebb2)) +* temp workaround to fix content exceeding the height of drawer container ([435243c](https://github.com/pattern-lab/patternlab-node/commit/435243cbfbd000a7d96a0e9fa7beff1a988ede64)) +* update drawer UI to not collapse content on smaller screen sizes ([7147085](https://github.com/pattern-lab/patternlab-node/commit/71470856b8b389421348366afd247a599d1e9c86)) +* update package.json description in `@pattern-lab/uikit-polyfills` ([22fc44a](https://github.com/pattern-lab/patternlab-node/commit/22fc44a4b3683753a469a98abfcdad8f1234f28a)) +* **engine_twig_php:** Allow additional flexibility with twig namespaces. ([07bfaa3](https://github.com/pattern-lab/patternlab-node/commit/07bfaa35a00ff62fd2016cc9f34e09cf5af36559)) + + +### Features + +* add lit-element, basic Typescript support to Webpack ([611f705](https://github.com/pattern-lab/patternlab-node/commit/611f705be85eea8a31091169750d64e988798cee)) +* add local copy of new Slotify library till published to NPM ([63b9d83](https://github.com/pattern-lab/patternlab-node/commit/63b9d833908151ce5cb5aa5184c72254125c7ed1)) +* add new component to make Button-like styles more reusable ([5e7b014](https://github.com/pattern-lab/patternlab-node/commit/5e7b0140622eb89154c38925769a6def6d669fb3)) +* add new component ([e8ce2a9](https://github.com/pattern-lab/patternlab-node/commit/e8ce2a927365b8d5316a7d8229c979ff31b04907)) +* add support for auto-closing Nav when clicking inside of the rendered iframe ([9d602fe](https://github.com/pattern-lab/patternlab-node/commit/9d602fe335a5d3b5bca5cac258c2465934d9a46a)) +* add support for optional chaining syntax via Babel plugin ([c8886b6](https://github.com/pattern-lab/patternlab-node/commit/c8886b6d9d91fea246fa3ab7947f289509dc26d5)) +* major refactoring + UI updates to address cross browser support; UI cleanup and conversion of the majority of the remaining components over to lit-element ([2ff8e1c](https://github.com/pattern-lab/patternlab-node/commit/2ff8e1c98cdd02e8077064c48eca5f7754a3db02)) +* refactor + convert pl-toggle-info to lit-element ([85cd9c5](https://github.com/pattern-lab/patternlab-node/commit/85cd9c50ca814066bf999badf2071d84964f00cc)) +* refactor + convert pl-toggle-layout to lit-element ([46009d9](https://github.com/pattern-lab/patternlab-node/commit/46009d91b1cb9ed613baa5a7626cba4f42883465)) +* refactor + convert pl-toggle-theme to lit-element ([95a3b21](https://github.com/pattern-lab/patternlab-node/commit/95a3b21a89dacd2d5b4df8c134ce438d4efdbd04)) +* refactor Drawer to render via lit-element + massively improve rendering performance ([28d47eb](https://github.com/pattern-lab/patternlab-node/commit/28d47eb3cbbce038204203e786e5188b4cefe64f)) +* remove mixin that was causing outlines to be removed from default UI styles ([622ed76](https://github.com/pattern-lab/patternlab-node/commit/622ed76d435b3b2e31e412266c3090506f98051b)) +* temp add unsafe-svg directive till upstream PR merged ([34de61c](https://github.com/pattern-lab/patternlab-node/commit/34de61ccd9c7bb3b48ca5ef386a87efc8e84babc)) +* update the Nav design to not bold the active item in order to not shift the layout ([0eda431](https://github.com/pattern-lab/patternlab-node/commit/0eda4312ba9f4c61afa6322c3ff45f9cda0efc9e)) +* update Webpack config to use the latest Style Loader + new SVG icon system ([2ed70e7](https://github.com/pattern-lab/patternlab-node/commit/2ed70e79d8656c7314d8b3109aa1c34160ad24f9)) + + + + + + +# [5.1.0](https://github.com/pattern-lab/patternlab-node/compare/v5.0.2...v5.1.0) (2019-10-29) + + +### Features + +* **config:** add new default pattern export options ([a7487a0](https://github.com/pattern-lab/patternlab-node/commit/a7487a0681cb11e6f3c5c8eaefd62e5648ad5ea3)) + + + + + +## [5.0.2](https://github.com/pattern-lab/patternlab-node/compare/v5.0.1...v5.0.2) (2019-10-28) + + +### Bug Fixes + +* **uikit-workshop:** add template files to published bundle ([9005fce](https://github.com/pattern-lab/patternlab-node/commit/9005fcee9e129fb41d509f706195e1437bddc710)) +* **uikit-workshop:** add webpack config to published bundle ([060a573](https://github.com/pattern-lab/patternlab-node/commit/060a573cbddce9ee3d270d39337d0c8cac8372fa)) + + + + + +## [5.0.1](https://github.com/pattern-lab/patternlab-node/compare/v5.0.0...v5.0.1) (2019-10-28) + + +### Bug Fixes + +* add missing “dist” folder to array of files / folders published to NPM ([8829429](https://github.com/pattern-lab/patternlab-node/commit/88294296c438352570befd2eb6b9e1ca2ae3b750)) + + + + + +# [5.0.0](https://github.com/pattern-lab/patternlab-node/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + + +### Bug Fixes + +* **1049:** Treat folders like patterns only if they're subfolders of pattern groupings ([4eb79ab](https://github.com/pattern-lab/patternlab-node/commit/4eb79ab48b335a35b2e5ed3b7053974b8e8bb6b6)) +* **cli:** add custom install logic to edition-node ([f04fd26](https://github.com/pattern-lab/patternlab-node/commit/f04fd266429cd806987dab747e6d69bff9b926a4)) +* **cli:** allow any package to be installed as a starterkit ([d2aa1be](https://github.com/pattern-lab/patternlab-node/commit/d2aa1be810a0a7473dcc52391a2263dacfdda0b8)), closes [#1067](https://github.com/pattern-lab/patternlab-node/issues/1067) +* **cli:** merge config arrays via overwrite instead of concatenate ([42e5f7b](https://github.com/pattern-lab/patternlab-node/commit/42e5f7b42a26b4fc1f262c68ee4b474b546f2eac)) +* **cli:** proper path resolution to helpers ([a18fe5e](https://github.com/pattern-lab/patternlab-node/commit/a18fe5ef4d1c074a5eba8bfa255ebbee2261bf74)) +* **cli:** re-order and clarify engines ([e39e301](https://github.com/pattern-lab/patternlab-node/commit/e39e301a33306c6615fabf64262f1893ca682b97)) +* **core:** allow plugin resolution to follow normal algorithm ([3f6b83b](https://github.com/pattern-lab/patternlab-node/commit/3f6b83be080c88aec1d8b73bececb76f0f57a79d)) +* **core:** find plugins from config only and with simpler args ([fe7351c](https://github.com/pattern-lab/patternlab-node/commit/fe7351cba346425512cbb2ef3a1b7728ab06ae60)) +* **deploy:** add setup command ([74dd314](https://github.com/pattern-lab/patternlab-node/commit/74dd3142bf48873a9f1ec4e8dccb8aa2fef9001d)) +* **engine_twig_php:** Pseudo patterns Twig PHP ([226aa8b](https://github.com/pattern-lab/patternlab-node/commit/226aa8bbaaf5e418530ccf54a28f6c5657ee6dea)), closes [#1045](https://github.com/pattern-lab/patternlab-node/issues/1045) +* **engine_twig_php:** Twig incremental rebuilds ([1ade945](https://github.com/pattern-lab/patternlab-node/commit/1ade9451840b2645706a0b01129e2b697dc22d4b)), closes [#1015](https://github.com/pattern-lab/patternlab-node/issues/1015) +* **engine_twig_php:** Twig incremental rebuilds ([5d33f24](https://github.com/pattern-lab/patternlab-node/commit/5d33f24f156ebe50900701513a855de7de608dcf)), closes [#1015](https://github.com/pattern-lab/patternlab-node/issues/1015) +* **lerna:** typo in config ([525a47b](https://github.com/pattern-lab/patternlab-node/commit/525a47b51fba91c1bf5b7439735f48eb7dfa073e)) +* **lint:** Use const instead of var ([ad1e782](https://github.com/pattern-lab/patternlab-node/commit/ad1e782ef71295eb610f56d019eaa35499fb3f85)) +* **plugin:** correct spelling error and function locations ([d4abd88](https://github.com/pattern-lab/patternlab-node/commit/d4abd88cb017550002407241b5045a2ad1adb1dc)) +* **plugin-tab:** bump lodash from 4.17.5 to 4.17.15 in /packages/plugin-tab ([#1081](https://github.com/pattern-lab/patternlab-node/issues/1081)) ([3f89dda](https://github.com/pattern-lab/patternlab-node/commit/3f89dda1685874e251f9777f969c0943e0080881)) +* **plugin-tab:** handle params correctly ([d248993](https://github.com/pattern-lab/patternlab-node/commit/d2489939bb0db1a1d67b0e7f47dfb1838b88b0a0)) +* **starterkit:** add css output and build command ([ccb2d35](https://github.com/pattern-lab/patternlab-node/commit/ccb2d3569b741220324a3fa738ab3d4d2eb97ffe)) +* add better pre-rendering support ([8ecd615](https://github.com/pattern-lab/patternlab-node/commit/8ecd6159a89232f42e0a9dc3c688b6e21de8fc30)) +* add eslint fixes ([00d7bbe](https://github.com/pattern-lab/patternlab-node/commit/00d7bbe319ea77a6ee8cc9cd0348856feaaf13ad)) +* add missing @babel/runtime package to address silent error getting thrown on Travis ([1918d04](https://github.com/pattern-lab/patternlab-node/commit/1918d042d7e90cc8aaa2fdfcd8649961c0a5dd50)) +* add missing preact-render-to-string library ([881296a](https://github.com/pattern-lab/patternlab-node/commit/881296a2c256424beac28bd560c5b1a5e1fed005)) +* add repo info to root package.json so Auto knows what repo to configure for ([85142e8](https://github.com/pattern-lab/patternlab-node/commit/85142e8e94549edd7980459e5975d0639c34864d)) +* address unrelated eslint errors from PL core ([6ada00d](https://github.com/pattern-lab/patternlab-node/commit/6ada00d396eb436837f7453664bfa50522a2ec10)) +* correct typo in build logging ([96d989f](https://github.com/pattern-lab/patternlab-node/commit/96d989f8869630ba9f59705bfca66755f20e35ab)) +* fall back to seeing the current pattern's query string to `all` or the defaultPattern value if undefined when the iframe page initially loads ([a368459](https://github.com/pattern-lab/patternlab-node/commit/a3684590fca02cf96b99421b87a0ad0a711893ad)) +* fix incorrect Webpack version in package.json ([9788e89](https://github.com/pattern-lab/patternlab-node/commit/9788e8977921e31fe43f2a1ec19d4684dd4709c5)) +* fix issue with viewport height exceeding the space available ([95cd1cf](https://github.com/pattern-lab/patternlab-node/commit/95cd1cfa57f086ecb84ac2e996ecda81f0c6a1a6)) +* fix Prism.js typo so languages not found / supported don't throw a JS error ([a8c19f9](https://github.com/pattern-lab/patternlab-node/commit/a8c19f9f9b11d4abbdcd9e573fb0cb418d665660)) +* fix Twig Edition examples by adding missing Twig namespaces to config ([b4c20ef](https://github.com/pattern-lab/patternlab-node/commit/b4c20ef88ee0d3010760584c6f05ff7f92b711a6)) +* minor CSS fixes + fresh prod build ([8ac2c1f](https://github.com/pattern-lab/patternlab-node/commit/8ac2c1fa1c7558ed2ac50755f599a438d682ee2a)) +* re-enable displaying the top level `All` link if PL isn't configured to hide this specific link in the ishControlsHide config option. Addresses [#1048](https://github.com/pattern-lab/patternlab-node/issues/1048) ([6bb4e1a](https://github.com/pattern-lab/patternlab-node/commit/6bb4e1ac6f38b47f93030c8c5bca62d5db2132e4)) +* re-enable using the defaultPattern config for the initial iframe page load if defined ([d645ea1](https://github.com/pattern-lab/patternlab-node/commit/d645ea15150061d7ad13741d2dc37b12b9786411)) +* regenerate fresh UIKit build after fixing main JS issues ([9ea34d2](https://github.com/pattern-lab/patternlab-node/commit/9ea34d2efe43cafacb3729ac113121ba51126344)) +* Rename Handlebars and Nunjucks extension setting to "extend" ([74e5af2](https://github.com/pattern-lab/patternlab-node/commit/74e5af28c4e714fdfc1db535b94c52f3dc14a3a4)) +* squashing minor UI bugs ([a8a606c](https://github.com/pattern-lab/patternlab-node/commit/a8a606cfb224f7041f53ff5026a84e13fa17914c)) +* temporarily disable Random and Disco viewport controls until the full JS logic for these is re-enabled ([14b9a19](https://github.com/pattern-lab/patternlab-node/commit/14b9a19e4dee9462f3784eae28066893cc893624)) +* temporarily downgrade Preact version so tooltip used for displaying viewport sizes renders correctly ([52dcf85](https://github.com/pattern-lab/patternlab-node/commit/52dcf85e756ee171ca993288d98f5b5ef9a0a24b)) +* update autoprefixer browserslist config to address warning messages ([5e52f2b](https://github.com/pattern-lab/patternlab-node/commit/5e52f2b0ed02e2002ca867368636c3c0dc79ff0a)) +* update initial PL iframe path default ([a26fbb9](https://github.com/pattern-lab/patternlab-node/commit/a26fbb956e13901d1751c435b76de65637191ca4)) +* update Javascript to address merge conflict issue with previous PR merge / recent release ([cf2ecc1](https://github.com/pattern-lab/patternlab-node/commit/cf2ecc154383c3e8abd56dc88484370bc58ac30b)) +* update styles for pattern state dots ([7728acc](https://github.com/pattern-lab/patternlab-node/commit/7728accc9a6e5cd83be451f7d74e522dfe721cad)) +* update the default pattern that displays in the Handlebars demo ([ff1d85f](https://github.com/pattern-lab/patternlab-node/commit/ff1d85f2852fc4f210841e8e0aaf14b55165ce58)) +* **starterkit:** remove config file ([f90e38a](https://github.com/pattern-lab/patternlab-node/commit/f90e38aa873dcff0dd08fe4dabc3b71bf95080b6)) +* **starterkit:** use handlebars meta files ([d8f5e12](https://github.com/pattern-lab/patternlab-node/commit/d8f5e12471bd783bd3755626701ecc17669fc761)) +* updates to address eslint / prettier issues ([d945acc](https://github.com/pattern-lab/patternlab-node/commit/d945acc13b8e4e36f3815b017fbc12266c323d1f)) +* updates to fix eslint / prettier issues; update packages/core to reuse root .eslintrc.js file ([5b7a057](https://github.com/pattern-lab/patternlab-node/commit/5b7a057d46ccd16b5832af1441030c7b76f237a8)) +* use 100% of the screen available when JS is disabled / the first time the iframe loads up ([c0c5bff](https://github.com/pattern-lab/patternlab-node/commit/c0c5bff7a63b157d5b81dc2bcecee9e732ecfd4e)) +* **uikit:** clear out "404" responses when loading tabs ([73874b1](https://github.com/pattern-lab/patternlab-node/commit/73874b1b0b66ca6425c2b74331d417efdb529e2e)) +* **uikit-workshop:** fix merge problem ([d245b3b](https://github.com/pattern-lab/patternlab-node/commit/d245b3bca044c29f281052bf2feb95eeffafcf6b)) + + +### Features + +* **core:** invoke registered plugin hooks ([a54d775](https://github.com/pattern-lab/patternlab-node/commit/a54d7753b6939fe6a58da543f4fb34f64dd8901a)) +* **edition-node:** switch to engine-handlebars ([b481e22](https://github.com/pattern-lab/patternlab-node/commit/b481e22dc1f41ddd4da709621640a15190fba257)) +* **engine-handlebars:** Default location for helpers, like engine-nunjucks ([11c4180](https://github.com/pattern-lab/patternlab-node/commit/11c41805e0c3dbebb7109719c4f3c780d32feab5)) +* **engine-handlebars:** Demonstration of custom Handlebars helper ([f330b5b](https://github.com/pattern-lab/patternlab-node/commit/f330b5bca72f2f34bfafe5c2c64e6b0b8823eb1c)) +* **engine-handlebars:** Document the Helpers feature ([a01e040](https://github.com/pattern-lab/patternlab-node/commit/a01e040429a7f77dfeb28d67c690e835b97881de)) +* **engine-handlebars:** Load Handlebars helpers specified in the config ([a12df36](https://github.com/pattern-lab/patternlab-node/commit/a12df36d2a644dfac8ded1dfd94b987e99c29d79)) +* **engine-nunjucks:** Configurable extension locations; Use usePatternlabConfig() ([e54e3b3](https://github.com/pattern-lab/patternlab-node/commit/e54e3b3d48f934d3a4d44b9f4ff262f742a4aaf9)) +* **engine-react:** set package to private ([3aea881](https://github.com/pattern-lab/patternlab-node/commit/3aea8815f19df5b527cdda0b75cf99a9a8c3bc1e)) +* **plugin-tab:** pivot to using hook functions ([d4b2598](https://github.com/pattern-lab/patternlab-node/commit/d4b25984fc2a2646cc1876a5c635f57593c35f09)) +* **plugin-tab, core:** initial plugin hook exploration ([2f3d39a](https://github.com/pattern-lab/patternlab-node/commit/2f3d39ac6b125ad4c6b872e27ee224ce2ea33a12)) +* **starterkits:** add starterkit-handlebars-demo ([384d2cf](https://github.com/pattern-lab/patternlab-node/commit/384d2cfa3440c1e6f456d39f56ca6381f82f7689)) +* **uikit-workshop:** add plugin-loader ([fc966d6](https://github.com/pattern-lab/patternlab-node/commit/fc966d6b151e24055bc2f4146d6a90b5fb392765)) +* introduce netlify preview ([6c5d332](https://github.com/pattern-lab/patternlab-node/commit/6c5d332479fb6836bd8bd5530a074d13440f8ae4)) +* remove pre-built uikit dist folder and switch to auto-building when bootstrapping OR when publishing to NPM ([b5dd553](https://github.com/pattern-lab/patternlab-node/commit/b5dd5538ee00ddf1da321851865fa1c223cedb43)) +* switch to Yarn + Yarn workspaces ([f4c4ec3](https://github.com/pattern-lab/patternlab-node/commit/f4c4ec33cd30d372c87ffa904fbe7d5b819ee14e)) +* update Node to v12 ([fcbb970](https://github.com/pattern-lab/patternlab-node/commit/fcbb970648cdd775c9a88078f14c1f24c5b62d73)) + + +### Reverts + +* don't flatten folders containing only one item inside ([77f1f46](https://github.com/pattern-lab/patternlab-node/commit/77f1f46595328bd96fba46347b532295c65802d1)) + + +### BREAKING CHANGES + +* **core:** plugins now use async functions instead of events +* **plugin-tab:** event based listeners replaced with functions +* **cli:** previously, we concatenated arrays, which is unlikely to be intended +* **edition-node:** use handlebars over mustache diff --git a/CODEOWNERS b/CODEOWNERS index 75ecbe287..532d55de7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -7,9 +7,6 @@ # review when someone opens a pull request. @pattern-lab/trusted-committers -# CLI owner -/packages/cli @raphaelokon - # uikit-workshop owner /packages/uikit-workshop @sghoweri diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9f536bcc4..39d8d867a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,13 +34,13 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at brian.muenzenmeyer@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. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team by opening an issue. 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. Project 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. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/4/ diff --git a/CUTTING_A_RELEASE.md b/CUTTING_A_RELEASE.md new file mode 100644 index 000000000..b90c8c9df --- /dev/null +++ b/CUTTING_A_RELEASE.md @@ -0,0 +1,73 @@ +# How To Cut a Pattern Lab Release + +We use a handful of tools to help automate and simplify the process of cutting a new Pattern Lab release. The most important ones being [Lerna](https://github.com/lerna/lerna) and [Auto](https://intuit.github.io/auto/). + +## Release Prep + +1. Make sure any/all the code ready to get released is merged down to the `dev` branch and all CI checks, etc are passing as expected + +2. Git checkout the `dev` branch locally and make sure: +- You've run `yarn` to install the latest dependencies +- You don't have any local changes pending + +``` +git checkout dev +git pull +yarn +git status # confirm no pending changes +``` + +3. Before running the publish command, I also like to run the `build` command to be extra sure everything compiles fine locally (ex. Node.js version matches with the version of Sass that's installed, gotchas like that) + +``` +yarn build +``` + +4. You'll also want to make sure you have a `.env` file in your PL Node repo root (and create one if you don't) + +You can grab the NPM + Github tokens needed here by heading to https://github.com/settings/tokens/new (grant repo access) and https://www.npmjs.com/settings/NPM_USER/tokens + +``` +## .env +export GH_TOKEN=PASTE_GITHUB_TOKEN_HERE +export NPM_TOKEN=PASTE_NPM_TOKEN_HERE +``` + +I personally like to use zsh's `env` plugin (already installed with Oh My ZSH) which has instructions for enabling here https://github.com/johnhamelink/env-zsh + +> Pro tip: you can quickly check to see if your env variable tokens are available for these CLI commands by running `npx auto release --dry-run` which will throw an error if the tokens above can't be found! + +5. Finally you'll also want to confirm that you're logged into your NPM account with access to publish to the Pattern Lab NPM org by running `npm login` and following the prompts. + +## Cutting The Release + +6. Run the `publish` command + +Ok - with all that prep out of the way, the actual release process is pretty quick and should be super straightforward. + +Simply run the `yarn run publish` command and include the type of SEMVER release you want to cut. + +So for example: + +``` +yarn run publish minor + +## alternatively you can include the exact version you want to publish +yarn run publish v5.14.0 +``` + +Lerna should prompt you with a confirmation that the version about to get released matches up with what you expect ^ + +7. Manually (re)run the `auto release` command? + +Ok, if everything built and published successfully, this final step may or may not be required... + +Normally the `auto release` command should run automatically after Lerna finishes publishing to NPM. This command will create the Github release associated with the latest Git tag, add any relevant release notes, and comment on related PRs, however the last couple of releases required this last step to get re-run manually. + +Note that you'll need to replace the `from` and `use-version` version numbers to match the last previous Git tag and this next release getting cut. + +``` +npx auto release --from v5.11.1 --use-version v5.12.0 +``` + +8. Confirm the [Github release](https://github.com/pattern-lab/patternlab-node/releases) was added and manually tweak any release notes as needed. diff --git a/LICENSE b/LICENSE index c9b8c1daa..3bb526cd2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2018 Brian Muenzenmeyer, http://brianmuenzenmeyer.com & Brad Frost, http://bradfrostweb.com +Copyright (c) 2018 Brian Muenzenmeyer, https://brianmuenzenmeyer.com & Brad Frost, https://bradfrost.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index da9e4eec4..3d82c45c7 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,30 @@ +> [!IMPORTANT] +> Pattern Lab is no longer actively maintained. All repositories, along with the rest of the @pattern-lab ecosystem on GitHub and npm, have been deprecated and archived. The code, releases, and history remain available so the work stays discoverable and forks can continue independently under the MIT license. No new releases, security patches, or issue triage will be performed. +> [Read the full message](https://github.com/pattern-lab), and thank you. +

- Pattern Lab Logo + Pattern Lab Logo

# Pattern Lab -This monorepo contains the core of Pattern Lab / Node and all related engines, UI kits, plugins and utilities. Pattern Lab helps you and your team build thoughtful, pattern-driven user interfaces using atomic design principles. +This monorepo contains the core of Pattern Lab / Node and all related engines, UI kits, plugins, and utilities. Pattern Lab helps you and your team build thoughtful, pattern-driven user interfaces using atomic design principles. -If you'd like to see what a front-end project built with Pattern Lab looks like, check out this [online demo of Pattern Lab output](http://demo.patternlab.io/). +If you'd like to see what a front-end project built with Pattern Lab looks like, check out this [online demo of Pattern Lab output](https://demo.patternlab.io/). -[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) +[![Continuous Integration](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml) +[![CodeQL](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml) ![current release](https://img.shields.io/npm/v/@pattern-lab/core.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Coverage Status](https://coveralls.io/repos/github/pattern-lab/patternlab-node/badge.svg?branch=master)](https://coveralls.io/github/pattern-lab/patternlab-node?branch=master) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) -[![node (scoped)](https://img.shields.io/node/v/@pattern-lab/patternlab-node.svg)]() +[![node (scoped)](https://img.shields.io/node/v/@pattern-lab/core.svg)]() [![Join the chat at Gitter](https://badges.gitter.im/pattern-lab/node.svg)](https://gitter.im/pattern-lab/node) +[![Join the chat at Discord](https://img.shields.io/badge/Chat-Discord-informational.svg)](https://discord.gg/UcZrYYE7ht) + +Docs @ [![Netlify Status](https://api.netlify.com/api/v1/badges/d454dbde-02c5-4bd4-8393-4ab75e862b03/deploy-status)](https://app.netlify.com/sites/patternlab-docs-preview/deploys) + +Pattern Lab Preview @ [![Netlify Status](https://api.netlify.com/api/v1/badges/a6db1666-cb4f-4d26-82d4-9d88d875f286/deploy-status)](https://app.netlify.com/sites/patternlab-handlebars-preview/deploys) ## Using Pattern Lab @@ -22,29 +32,29 @@ Refer to the [core usage guidelines](https://github.com/pattern-lab/patternlab-n ### Installation -As of Pattern Lab Node 3.0.0, installation of [Editions](http://patternlab.io/docs/advanced-ecosystem-overview.html) is accomplished via the command line interface. +As of Pattern Lab Node 3.0.0, installation of [Editions](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/) is accomplished via the command line interface. The below assumes a new directory and project is required. This is likely what you want to do if starting from scratch. You could also run this within an existing project. The CLI will ask you for the installation location. -1. Open a terminal window and following along below: +1. Open a terminal window and follow along below: ```bash mkdir new-project cd new-project npm create pattern-lab ``` > If you get an error stating that `npx` is not installed, ensure you are on `npm 5.2.0` or later by running `npm -v` or install it globally with `npm install -g npx`. [Learn more about npx.](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) -1. Follow the on-screen prompts to choose your Edition and a Starterkit should you want one. - - If you chose `edition-node`, new commands in the "scripts" will be added in your `package.json`. +1. Follow the on-screen prompts to choose your Edition and a Starter Kit should you want one. + - If you chose `edition-node`, new commands in the "scripts" will be added to your `package.json`. - If you chose `edition-node-gulp`, a `gulpfile.js` will be added to your project. - > Notice that `@pattern-lab/cli` was installed as a depdendency. Learn how to further [use the cli in your own project](https://github.com/pattern-lab/patternlab-node/blob/dev/packages/cli/readme.md#configuring-your-project-to-use-the-cli). + > Notice that `@pattern-lab/cli` was installed as a dependency. Learn how to further [use the cli in your own project](https://github.com/pattern-lab/patternlab-node/blob/dev/packages/cli/readme.md#configuring-your-project-to-use-the-cli). ## Ecosystem -![Pattern Lab Ecosystem](http://patternlab.io/assets/pattern-lab-2-image_18-large-opt.png) +![Pattern Lab Ecosystem](https://patternlab.io/images/pattern-lab-2-image_18-large-opt.png) -Core, and Editions, are part of the [Pattern Lab Ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). With this architecture, we encourage people to write and maintain their own Editions, Starterkits, and even PatternEngines. +Core, and Editions, are part of the [Pattern Lab Ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). With this architecture, we encourage people to write and maintain their own Editions, Starter kits, and even PatternEngines. ## Changelog @@ -55,13 +65,27 @@ Core, and Editions, are part of the [Pattern Lab Ecosystem](http://patternlab.io ## Support for Pattern Lab -Pattern Lab / Node wouldn't be what it is today without the support of the community. It will always be free and open source. Continued development is made possible in part from the support of [these wonderful project supporters](https://github.com/pattern-lab/patternlab-node/wiki/Thanks). If you want to learn more about supporting the project, visit the [Pattern Lab / Node Patreon page](https://www.patreon.com/patternlab). +Pattern Lab / Node wouldn't be what it is today without the support of the community. It will always be free and open source. Continued development is made possible in part from the support of [contributors](https://github.com/pattern-lab/patternlab-node/graphs/contributors). + +Thanks to [Netlify](https://www.netlify.com/) for building tooling and hosting. + +## Node Support Policy + +We only support actively [maintained](https://github.com/nodejs/Release#release-schedule) versions of Node. + +We specifically limit our support to maintenance versions of Node, not because this package won't work on other versions, but because we have a limited amount of time, and supporting the oldest maintenance offers the greatest return on that investment while still providing the lowest standard level for installations on any possible actively maintained environment out there. + +This package may work correctly on newer versions of Node. It may even be possible to use this package on older versions of Node. However, that's more unlikely as we'll make every effort to take advantage of features available in the oldest maintenance Node version we support. + +As each Node maintenance version reaches its end-of-life, we will replace that version from the `node` `engines` property of our package's `package.json` file with the newer oldest one. As this replacement would be considered a breaking change, we will publish a new major version of this package. We will not accept any requests to support an end-of-life version of Node. Any merge requests or issues supporting an end-of-life version of Node will be closed. + +And we might even update the minor and patch version of that supported maintenance Node version regularly, without making this a breaking change than as it should be in everybody's interest even also to follow this concept of using patched software as their development system basis, especially on those older Node versions. + +We will accept code that allows this package to run on newer, non-maintenance versions of Node. Furthermore, we will attempt to ensure our changes work on the latest version of Node. To help in that commitment, we even test that out by ourselves and get feedback from the community regularly regarding all LTS versions of Node and the most recent Node release called current. -**:100: Thanks for support from the following:** +JavaScript package managers like e.g. [NVM](https://github.com/nvm-sh/nvm) should allow you to install this package with any version of Node, with, at most, a warning if your version of Node does not fall within the range specified by our `node` `engines` property. If you encounter issues installing this package, please report the issue to your package manager. -* **[Brad Frost](http://bradfrost.com/)** -* [Marcos Peebles](https://twitter.com/marcospeebles) -* [Susan Simkins](https://twitter.com/susanmsimkins) +This policy has been adapted from . ## Contributing diff --git a/UPGRADE_GUIDE.md b/UPGRADE_GUIDE.md new file mode 100644 index 000000000..b2318ecf2 --- /dev/null +++ b/UPGRADE_GUIDE.md @@ -0,0 +1,12 @@ +# Upgrading Pattern Lab Node + +To upgrade the Node version of Pattern Lab do the following: + +## Version 6 instructions + +- Ensure that you're using at least Node.js version 14, to which we've upgraded to with [!1430](https://github.com/pattern-lab/patternlab-node/pull/1430) +- If you haven't migrated from `mustache` to `handlebars` engine and templates so far, now would be a good time as `mustache` has been replaced by `handlebars` as the default template language with version 5 of pattern lab, and `mustache` might get removed sooner rather than later. To make a long story short, `handlebars` is mostly compatible, but more mature than `mustache`, so a migration shouldn't be too hard, and even beneficial. Additionally using `mustache` templates most likely won't work anymore starting with this new major version 6 due to these potentially breaking changes for `mustache` usage: + - Removed `styleModifiers` with [!1452](https://github.com/pattern-lab/patternlab-node/pull/1452), that haven't been mentioned in the documentation any more anyhow. + - replaced `hogan.js` by `handlebars` rendering [!1456](https://github.com/pattern-lab/patternlab-node/pull/1456), that would expect the usage of block helpers instead of typical mustache iterations over objects. +- Please explicitly configure your used engine within `patternlab-config.json` as described within the documentations section https://patternlab.io/docs/editing-the-configuration-options/#heading-engines. The previous way of scanning `node_modules` folder for pattern engines is deprecated and will be removed with version 7. + diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..6960ccf61 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,27 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + ], + plugins: [ + /** + * 1. Helps with our Web Component Preact renderer + */ + '@babel/plugin-syntax-jsx' /* [1] */, + [ + '@babel/plugin-transform-react-jsx' /* [1] */, + { + pragma: 'h', + pragmaFrag: '"span"', + throwIfNamespace: false, + useBuiltIns: false, + }, + ], + ], +}; diff --git a/lerna.json b/lerna.json index 776f2c56b..7a57a21cc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,27 +1,38 @@ { - "lerna": "3.11.0", + "lerna": "4.0.0", + "version": "6.1.0", "packages": [ "packages/*" ], - "version": "independent", "command": { "init": { "exact": true }, - "bootstrap": { - "hoist": [ - "tap", - "eslin*", - "husky", - "prettier", - "pretty-quick" - ] - }, "publish": { - "allowBranch": "master" + "allowBranch": [ + "master", + "dev" + ], + "conventionalCommits": true, + "gitReset": true, + "includeMergedTags": true, + "noCommitHooks": true, + "verifyAccess": true + }, + "changed": { + "includeMergedTags": true } }, + "ignoreChanges": [ + "**/__fixtures__/**", + "**/__tests__/**", + "**/*.md", + "**/__snapshots__/**" + ], + "npmClient": "yarn", "npmClientArgs": [ + "--ignore-optional", "--registry=https://registry.npmjs.org/" - ] + ], + "useWorkspaces": true } diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000..94337a4da --- /dev/null +++ b/netlify.toml @@ -0,0 +1,2 @@ +[context.deploy-preview] + command = "yarn setup && yarn preview:hbs && yarn preview:docs" diff --git a/package.json b/package.json index 650a8a3a8..3a33784a5 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,46 @@ { - "devDependencies": { - "lerna": "3.11.0" + "workspaces": { + "packages": [ + "packages/*" + ], + "nohoist": [ + "@pattern-lab/engine-*", + "**/@pattern-lab/engine-*", + "**/@pattern-lab/uikit-workshop" + ] + }, + "dependencies": { + "@auto-it/released": "^10.27.0", + "@babel/plugin-proposal-decorators": "^7.13.5", + "@babel/plugin-syntax-jsx": "^7.12.13", + "auto": "^10.27.0", + "babel-eslint": "^10.0.2", + "eslint": "^6.1.0", + "eslint-config-prettier": "^6.0.0", + "eslint-plugin-prettier": "^3.1.0", + "lerna": "4.0.0", + "prettier": "^2.8.1", + "pretty-quick": "^3.1.3" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/pattern-lab/patternlab-node.git" }, "private": true, "scripts": { - "bootstrap": "lerna bootstrap", - "setup": "npm run bootstrap && npm run build:uikit", - "build:uikit": "lerna exec --scope @pattern-lab/uikit-workshop -- npm run build", + "postinstall": "lerna run postbootstrap", + "setup": "yarn", + "build:uikit": "cd packages/uikit-workshop && npm run build", "precommit": "pretty-quick --staged", - "prettier": "prettier --config .prettierrc --write ./**/*.js --ignore-path .prettierignore", + "lint:fix": "npm run lint -- --fix", + "lint": "eslint --max-warnings 0 './packages/{core,cli,uikit-workshop}/**/*.js ' --ignore-path .eslintignore", "test": "lerna run test", - "clean": "git clean -dfx" + "clean": "git clean -dfx", + "publish": "npx lerna publish -m \"[skip travis] chore(release): publish %s\"", + "postpublish": "auto release", + "preview:docs": "cd packages/docs && yarn production", + "preview:hbs": "cd packages/development-edition-engine-handlebars && yarn pl:starterkit && yarn pl:build", + "prepare": "husky install" }, "nyc": { "exclude": [ @@ -19,5 +49,8 @@ "packages/core/test", "packages/live-server" ] + }, + "devDependencies": { + "husky": "^8.0.2" } } diff --git a/packages/cli/.gitignore b/packages/cli/.gitignore index 55a89459b..511707a54 100644 --- a/packages/cli/.gitignore +++ b/packages/cli/.gitignore @@ -17,13 +17,13 @@ coverage # nyc test coverage .nyc_output -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript -# Compiled binary addons (http://nodejs.org/api/addons.html) +# Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories diff --git a/packages/cli/.nvmrc b/packages/cli/.nvmrc index a13e7b9c8..59ea99ee6 100644 --- a/packages/cli/.nvmrc +++ b/packages/cli/.nvmrc @@ -1 +1 @@ -10.0.0 +16.20 diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 02d65dc16..cadcbeb26 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -3,6 +3,373 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.15.1...v5.15.2) (2021-11-03) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.15.0...v5.15.1) (2021-10-16) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.14.3...v5.15.0) (2021-07-01) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.10.2...v5.11.1) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.10.2...v5.11.0) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.9.3...v5.10.0) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.9.2...v5.9.3) (2020-05-01) + + +### Bug Fixes + +* **cli:** fix test script glob ([ff18eb5](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/ff18eb51ce24fc5423b009168e85ede366069139)) + + + + + + +## [5.9.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.9.0...v5.9.1) (2020-04-24) + + +### Bug Fixes + +* **cli:** ensure specified directory exists prior to scaffold ([cc3b696](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/cc3b69624d486c94ee3b1f4b1bbb0334a514fa59)) + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.8.0...v5.9.0) (2020-04-24) + + +### Bug Fixes + +* **cli:** set current working directory before scaffolded npm init ([6d2186d](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/6d2186d8e8a74634198a4474ca8ae83221dd70a9)) + + + + + +# [5.7.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.6.0...v5.7.0) (2020-02-17) + + +### Features + +* **cli:** make options more user friendly ([ad845b3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/ad845b394ef81f90895ebb5bc6f12cc608e5e3d4)) + + + + + + +# [5.4.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.3.3...v5.4.0) (2019-11-26) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.3.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.2.0...v5.3.0) (2019-11-13) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.1.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v5.0.2...v5.1.0) (2019-10-29) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + +# [5.0.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + + +### Bug Fixes + +* updates to fix eslint / prettier issues; update packages/core to reuse root .eslintrc.js file ([5b7a057](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/5b7a057d46ccd16b5832af1441030c7b76f237a8)) +* **cli:** add custom install logic to edition-node ([f04fd26](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/f04fd266429cd806987dab747e6d69bff9b926a4)) +* **cli:** allow any package to be installed as a starterkit ([d2aa1be](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/d2aa1be810a0a7473dcc52391a2263dacfdda0b8)), closes [#1067](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/issues/1067) +* **cli:** merge config arrays via overwrite instead of concatenate ([42e5f7b](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/42e5f7b42a26b4fc1f262c68ee4b474b546f2eac)) +* **cli:** proper path resolution to helpers ([a18fe5e](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/a18fe5ef4d1c074a5eba8bfa255ebbee2261bf74)) +* **cli:** re-order and clarify engines ([e39e301](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/e39e301a33306c6615fabf64262f1893ca682b97)) +* **plugin:** correct spelling error and function locations ([d4abd88](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/d4abd88cb017550002407241b5045a2ad1adb1dc)) + + +### Features + +* **starterkits:** add starterkit-handlebars-demo ([384d2cf](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/384d2cfa3440c1e6f456d39f56ca6381f82f7689)) + + +### BREAKING CHANGES + +* **cli:** previously, we concatenated arrays, which is unlikely to be intended + + + + + + +## [1.0.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/@pattern-lab/cli@1.0.2...@pattern-lab/cli@1.0.3) (2019-10-14) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + + +# [1.0.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/@pattern-lab/cli@0.1.0...@pattern-lab/cli@1.0.0) (2019-08-23) + + +### Bug Fixes + +* **cli:** merge config arrays via overwrite instead of concatenate ([42e5f7b](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/42e5f7b)) +* **cli:** proper path resolution to helpers ([a18fe5e](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/a18fe5e)) + + +### BREAKING CHANGES + +* **cli:** previously, we concatenated arrays, which is unlikely to be intended + + + + + +# [0.1.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/@pattern-lab/cli@0.0.3...@pattern-lab/cli@0.1.0) (2019-08-23) + + +### Bug Fixes + +* updates to fix eslint / prettier issues; update packages/core to reuse root .eslintrc.js file ([5b7a057](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/5b7a057)) +* **cli:** add custom install logic to edition-node ([f04fd26](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/f04fd26)) +* **cli:** re-order and clarify engines ([e39e301](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/e39e301)) + + +### Features + +* **starterkits:** add starterkit-handlebars-demo ([384d2cf](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/commit/384d2cf)) + + + + + + +## [0.0.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/@pattern-lab/cli@0.0.3-alpha.0...@pattern-lab/cli@0.0.3) (2019-05-16) + +**Note:** Version bump only for package @pattern-lab/cli + + + + + ## [0.0.1-beta.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli/compare/@pattern-lab/cli@0.0.1-beta.0...@pattern-lab/cli@0.0.1-beta.2) (2019-02-09) diff --git a/packages/cli/bin/archive.js b/packages/cli/bin/archive.js index 9d7a6989c..e27696977 100644 --- a/packages/cli/bin/archive.js +++ b/packages/cli/bin/archive.js @@ -31,7 +31,7 @@ function exportPatterns(config) { ); }); - archive.on('error', function(err) { + archive.on('error', function (err) { throw new TypeError( `export: An error occured during zipping the patterns: ${err}` ); diff --git a/packages/cli/bin/ask.js b/packages/cli/bin/ask.js index 55a337230..652fbda3b 100644 --- a/packages/cli/bin/ask.js +++ b/packages/cli/bin/ask.js @@ -12,8 +12,8 @@ const ask = inquirer.prompt; * @param {object} options - Options passed in from CLI * @param {boolean} options.force - Flag whether to force install in existing project directory. May overwrite stuff. */ -const init = options => - wrapsAsync(function*() { +const init = (options) => + wrapsAsync(function* () { /** * @property {string} project_root="./" - Path to the project root directory * @property {string|Symbol} edition - The name of the edition npm package or a Symbol for no install diff --git a/packages/cli/bin/build.js b/packages/cli/bin/build.js index 51108a33d..383be9b59 100644 --- a/packages/cli/bin/build.js +++ b/packages/cli/bin/build.js @@ -19,6 +19,10 @@ function build(config, options) { // Initiate Pattern Lab core with the config const patternLab = pl(config); + if (options && options.watch) { + config.watch = options.watch; + } + /** * Check whether a flag was passed for build * 1. Build only patterns @@ -31,7 +35,7 @@ function build(config, options) { } else { // 2 debug(`build: Building your project now into ${config.paths.public.root}`); - return patternLab.build(config.cleanPublic); + return patternLab.build(config); } } diff --git a/packages/cli/bin/cli-actions/build.js b/packages/cli/bin/cli-actions/build.js index c6a34434a..b9a752665 100644 --- a/packages/cli/bin/cli-actions/build.js +++ b/packages/cli/bin/cli-actions/build.js @@ -3,10 +3,10 @@ const buildPatterns = require('../build'); const resolveConfig = require('../resolve-config'); const { error, info, wrapAsync } = require('../utils'); -const build = options => - wrapAsync(function*() { +const build = (options) => + wrapAsync(function* () { try { - const config = yield resolveConfig(options.parent.config); + const config = yield resolveConfig(options.config); yield buildPatterns(config, options); info(`build: Yay, your Pattern Lab project was successfully built ☺`); } catch (err) { diff --git a/packages/cli/bin/cli-actions/disable.js b/packages/cli/bin/cli-actions/disable.js index ebf90ef60..35a460dc7 100644 --- a/packages/cli/bin/cli-actions/disable.js +++ b/packages/cli/bin/cli-actions/disable.js @@ -10,9 +10,12 @@ const writeJsonAsync = require('../utils').writeJsonAsync; * @desc Handles deactivation of starterkits/plugins * @param {object} options */ -const enable = options => - wrapAsync(function*() { - const { parent: { config: configPath }, plugins } = options; +const enable = (options) => + wrapAsync(function* () { + const { + parent: { config: configPath }, + plugins, + } = options; const config = yield resolveConfig(configPath); const spinner = ora(`⊙ patternlab → Disable …`).start(); @@ -21,7 +24,7 @@ const enable = options => spinner.succeed( `⊙ patternlab → Disable following plugins: ${plugins.join(', ')}` ); - plugins.map(plugin => { + plugins.map((plugin) => { if (_.has(config, `plugins[${plugin}]`)) { _.set(config, `plugins[${plugin}]['enabled']`, false); spinner.succeed( @@ -32,7 +35,7 @@ const enable = options => } }); } - yield writeJsonAsync(options.parent.config, config); + yield writeJsonAsync(options.config, config); spinner.succeed(`⊙ patternlab → Updated config`); }); diff --git a/packages/cli/bin/cli-actions/enable.js b/packages/cli/bin/cli-actions/enable.js index d7095f25f..f5a3c67fb 100644 --- a/packages/cli/bin/cli-actions/enable.js +++ b/packages/cli/bin/cli-actions/enable.js @@ -10,9 +10,12 @@ const writeJsonAsync = require('../utils').writeJsonAsync; * @desc Handles activation of starterkits/plugins * @param {object} options */ -const enable = options => - wrapAsync(function*() { - const { parent: { config: configPath }, plugins } = options; +const enable = (options) => + wrapAsync(function* () { + const { + parent: { config: configPath }, + plugins, + } = options; const config = yield resolveConfig(configPath); const spinner = ora(`⊙ patternlab → Enable …`).start(); @@ -21,7 +24,7 @@ const enable = options => spinner.succeed( `⊙ patternlab → Enable following plugins: ${plugins.join(', ')}` ); - plugins.map(plugin => { + plugins.map((plugin) => { if (_.has(config, `plugins[${plugin}]`)) { _.set(config, `plugins[${plugin}]['enabled']`, true); spinner.succeed(`⊙ patternlab → Enabled following plugin: ${plugin}`); @@ -30,7 +33,7 @@ const enable = options => } }); } - yield writeJsonAsync(options.parent.config, config); + yield writeJsonAsync(options.config, config); spinner.succeed(`⊙ patternlab → Updated config`); }); diff --git a/packages/cli/bin/cli-actions/export.js b/packages/cli/bin/cli-actions/export.js index 5f4f4ebc7..bfe674770 100644 --- a/packages/cli/bin/cli-actions/export.js +++ b/packages/cli/bin/cli-actions/export.js @@ -3,9 +3,9 @@ const archive = require('../archive'); const resolveConfig = require('../resolve-config'); const wrapAsync = require('../utils').wrapAsync; -const _export = options => - wrapAsync(function*() { - const config = yield resolveConfig(options.parent.config); +const _export = (options) => + wrapAsync(function* () { + const config = yield resolveConfig(options.config); archive(config); }); diff --git a/packages/cli/bin/cli-actions/help.js b/packages/cli/bin/cli-actions/help.js index 6448e7749..e3ff72c85 100644 --- a/packages/cli/bin/cli-actions/help.js +++ b/packages/cli/bin/cli-actions/help.js @@ -3,8 +3,8 @@ module.exports = () => { /* eslint-disable */ console.log(` Examples: - $ patternlab init # Initialize a Pattern Lab project.'); - $ patternlab # Builds Pattern Lab from the current dir'); - $ patternlab --config # Pattern Lab from a config in a specified directory');`); + $ patternlab init # Initialize a Pattern Lab project + $ patternlab # Builds Pattern Lab from the current dir + $ patternlab --config # Pattern Lab from a config in a specified directory`); /* eslint-enable */ }; diff --git a/packages/cli/bin/cli-actions/init.js b/packages/cli/bin/cli-actions/init.js index b8c743188..ff4decc91 100644 --- a/packages/cli/bin/cli-actions/init.js +++ b/packages/cli/bin/cli-actions/init.js @@ -13,8 +13,11 @@ const writeJsonAsync = require('../utils').writeJsonAsync; const defaultPatternlabConfig = patternlab.getDefaultConfig(); -const init = options => - wrapAsync(function*() { +// https://github.com/TehShrike/deepmerge#overwrite-array +const overwriteMerge = (destinationArray, sourceArray) => sourceArray; + +const init = (options) => + wrapAsync(function* () { const sourceDir = 'source'; const publicDir = 'public'; const exportDir = 'pattern_exports'; @@ -43,6 +46,7 @@ const init = options => ); // 1 yield scaffold(projectDir, sourceDir, publicDir, exportDir); // 2 + process.env.projectDir = path.join(process.cwd(), projectDir); if (edition) { spinner.text = `⊙ patternlab → Installing edition: ${edition}`; @@ -52,7 +56,9 @@ const init = options => projectDir ); // 3.1 if (newConf) { - patternlabConfig = merge(patternlabConfig, newConf); // 3.2 + patternlabConfig = merge(patternlabConfig, newConf, { + arrayMerge: overwriteMerge, + }); // 3.2 } spinner.succeed(`⊙ patternlab → Installed edition: ${edition}`); } @@ -65,7 +71,9 @@ const init = options => ); spinner.succeed(`⊙ patternlab → Installed starterkit: ${starterkit}`); if (starterkitConfig) { - patternlabConfig = merge(patternlabConfig, starterkitConfig); + patternlabConfig = merge(patternlabConfig, starterkitConfig, { + arrayMerge: overwriteMerge, + }); } } // 4 yield writeJsonAsync( diff --git a/packages/cli/bin/cli-actions/install.js b/packages/cli/bin/cli-actions/install.js index 28aa8a445..a00fca97f 100644 --- a/packages/cli/bin/cli-actions/install.js +++ b/packages/cli/bin/cli-actions/install.js @@ -11,9 +11,9 @@ const writeJsonAsync = require('../utils').writeJsonAsync; * @desc Handles async install and activation of starterkits/plugins * @param {object} options */ -const install = options => - wrapAsync(function*() { - const config = yield resolveConfig(options.parent.config); +const install = (options) => + wrapAsync(function* () { + const config = yield resolveConfig(options.config); const spinner = ora( `⊙ patternlab → Installing additional resources …` @@ -21,8 +21,8 @@ const install = options => if (options.starterkits && Array.isArray(options.starterkits)) { const starterkits = yield Promise.all( - options.starterkits.map(starterkit => - wrapAsync(function*() { + options.starterkits.map((starterkit) => + wrapAsync(function* () { spinner.text = `⊙ patternlab → Installing starterkit: ${starterkit}`; return yield installStarterkit( { @@ -42,8 +42,8 @@ const install = options => } if (options.plugins && Array.isArray(options.plugins)) { const plugins = yield Promise.all( - options.plugins.map(plugin => - wrapAsync(function*() { + options.plugins.map((plugin) => + wrapAsync(function* () { return yield installPlugin( { name: plugin, @@ -58,7 +58,7 @@ const install = options => `⊙ patternlab → Installed following plugins: ${plugins.join(', ')}` ); } - yield writeJsonAsync(options.parent.config, config); + yield writeJsonAsync(options.config, config); spinner.succeed(`⊙ patternlab → Updated config`); }); diff --git a/packages/cli/bin/cli-actions/serve.js b/packages/cli/bin/cli-actions/serve.js index 6e2cc8fd2..40576a761 100644 --- a/packages/cli/bin/cli-actions/serve.js +++ b/packages/cli/bin/cli-actions/serve.js @@ -3,9 +3,9 @@ const resolveConfig = require('../resolve-config'); const servePatterns = require('../serve'); const wrapAsync = require('../utils').wrapAsync; -const serve = options => - wrapAsync(function*() { - const config = yield resolveConfig(options.parent.config); +const serve = (options) => + wrapAsync(function* () { + const config = yield resolveConfig(options.config); servePatterns(config, options); }); diff --git a/packages/cli/bin/inquiries/edition.js b/packages/cli/bin/inquiries/edition.js index 08cc2b068..fca4958f2 100644 --- a/packages/cli/bin/inquiries/edition.js +++ b/packages/cli/bin/inquiries/edition.js @@ -12,23 +12,15 @@ const editionSetup = [ { type: 'list', name: 'edition', - message: 'Which edition do you want to use (defaults to edition-node)?', + message: 'What templating language do you want to use with Pattern Lab?', choices: [ { - name: 'edition-twig (php engine)', - value: '@pattern-lab/edition-twig', - }, - { - name: 'edition-node', + name: 'Handlebars', value: '@pattern-lab/edition-node', }, { - name: 'edition-node-grunt', - value: '@pattern-lab/edition-node-grunt', - }, - { - name: 'edition-node-gulp', - value: '@pattern-lab/edition-node-gulp', + name: 'Twig (PHP)', + value: '@pattern-lab/edition-twig', }, new inquirer.Separator(), { @@ -36,9 +28,9 @@ const editionSetup = [ value: false, }, ], - default: function() { + default: function () { return { - name: 'edition-node', + name: 'Handlebars', value: '@pattern-lab/edition-node', }; }, diff --git a/packages/cli/bin/inquiries/starterkit.js b/packages/cli/bin/inquiries/starterkit.js index 9c4e5ca7b..c158c2189 100644 --- a/packages/cli/bin/inquiries/starterkit.js +++ b/packages/cli/bin/inquiries/starterkit.js @@ -7,48 +7,20 @@ const starterkitSetup = [ { type: 'list', name: 'starterkit', - message: 'Which starterkit do you want to use?', + message: 'What initial patterns do you want included in your project?', choices: [ { - name: 'starterkit-mustache-demo', - value: '@pattern-lab/starterkit-mustache-demo', + name: 'Handlebars base patterns (some basic patterns to get started with)', + value: '@pattern-lab/starterkit-handlebars-vanilla', }, { - name: 'starterkit-mustache-bootstrap', - value: 'starterkit-mustache-bootstrap', + name: 'Handlebars demo patterns (full demo website and patterns)', + value: '@pattern-lab/starterkit-handlebars-demo', }, { - name: 'starterkit-mustache-foundation', - value: 'starterkit-mustache-foundation', - }, - // { - // name: 'starterkit-twig-base', - // value: 'starterkit-twig-base', - // }, - { - name: 'starterkit-twig-demo', + name: 'Twig (PHP) demo patterns (full demo website and patterns)', value: '@pattern-lab/starterkit-twig-demo', }, - { - name: 'starterkit-mustache-materialdesign', - value: 'starterkit-mustache-materialdesign', - }, - // { - // name: 'starterkit-twig-drupal-demo', - // value: 'starterkit-twig-drupal-demo', - // }, - // { - // name: 'starterkit-twig-drupal-minimal', - // value: 'starterkit-twig-drupal-minimal', - // }, - { - name: 'starterkit-mustache-webdesignday', - value: 'starterkit-mustache-webdesignday', - }, - { - name: 'starterkit-mustache-base', - value: '@pattern-lab/starterkit-mustache-base', - }, new inquirer.Separator(), { name: 'Custom starterkit', @@ -56,13 +28,13 @@ const starterkitSetup = [ }, new inquirer.Separator(), { - name: 'None', + name: 'Blank project (no patterns)', value: false, }, ], default: { - name: 'starterkit-mustache-base', - value: 'starterkit-mustache-base', + name: 'Handlebars demo patterns (full demo website and patterns)', + value: '@pattern-lab/starterkit-handlebars-demo', }, }, { diff --git a/packages/cli/bin/install-edition.js b/packages/cli/bin/install-edition.js index 5e63efd28..7d39dfdd0 100644 --- a/packages/cli/bin/install-edition.js +++ b/packages/cli/bin/install-edition.js @@ -1,3 +1,4 @@ +/* eslint-disable no-param-reassign */ 'use strict'; const path = require('path'); @@ -10,11 +11,18 @@ const { writeJsonAsync, getJSONKey, } = require('./utils'); +const { + resolveFileInPackage, + resolveDirInPackage, +} = require('@pattern-lab/core/src/lib/resolver'); + +// https://github.com/TehShrike/deepmerge#overwrite-array +const overwriteMerge = (destinationArray, sourceArray) => sourceArray; const installEdition = (edition, config, projectDir) => { const pkg = require(path.resolve(projectDir, 'package.json')); - return wrapAsync(function*() { + return wrapAsync(function* () { /** * 1. Trigger edition install * 2. Copy over the mandatory edition files to sourceDir @@ -27,7 +35,7 @@ const installEdition = (edition, config, projectDir) => { const sourceDir = config.paths.source.root; yield checkAndInstallPackage(edition); // 1 yield copyAsync( - path.resolve('./node_modules', edition, 'source', '_meta'), + resolveDirInPackage(edition, 'source', '_meta'), path.resolve(sourceDir, '_meta') ); // 2 pkg.dependencies = Object.assign( @@ -35,29 +43,44 @@ const installEdition = (edition, config, projectDir) => { pkg.dependencies || {}, yield getJSONKey(edition, 'dependencies') ); // 3 - switch (edition) { // 4 + switch ( + edition // 4 + ) { // 4.1 case '@pattern-lab/edition-node-gulp': { yield copyAsync( - path.resolve('./node_modules', edition, 'gulpfile.js'), + resolveFileInPackage(edition, 'gulpfile.js'), path.resolve(sourceDir, '../', 'gulpfile.js') ); break; } // 4.2 case '@pattern-lab/edition-node': { + const editionConfigPath = resolveFileInPackage( + edition, + 'patternlab-config.json' + ); + + const editionConfig = require(editionConfigPath); + pkg.scripts = Object.assign( {}, pkg.scripts || {}, yield getJSONKey(edition, 'scripts') ); + + yield copyAsync( + resolveFileInPackage(edition, 'helpers', 'test.js'), + path.resolve(sourceDir, '../', 'helpers/test.js') + ); + + config = merge(config, editionConfig, { arrayMerge: overwriteMerge }); break; } // 4.3 case '@pattern-lab/edition-twig': { - const editionPath = path.resolve('./node_modules', edition); - const editionConfigPath = path.resolve( - editionPath, + const editionConfigPath = resolveFileInPackage( + edition, 'patternlab-config.json' ); const editionConfig = require(editionConfigPath); @@ -69,11 +92,11 @@ const installEdition = (edition, config, projectDir) => { ); yield copyAsync( - path.resolve(editionPath, 'alter-twig.php'), + resolveFileInPackage(edition, 'alter-twig.php'), path.resolve(sourceDir, '../', 'alter-twig.php') ); - config = merge(config, editionConfig); + config = merge(config, editionConfig, { arrayMerge: overwriteMerge }); break; } } diff --git a/packages/cli/bin/install-plugin.js b/packages/cli/bin/install-plugin.js index 42ea84c63..f152076b0 100644 --- a/packages/cli/bin/install-plugin.js +++ b/packages/cli/bin/install-plugin.js @@ -1,14 +1,12 @@ 'use strict'; -const path = require('path'); - const _ = require('lodash'); -const checkAndInstallPackage = require('./utils').checkAndInstallPackage; -const wrapAsync = require('./utils').wrapAsync; +const { checkAndInstallPackage, wrapAsync } = require('./utils'); +const { resolveFileInPackage } = require('@pattern-lab/core/src/lib/resolver'); const installPlugin = (plugin, config) => - wrapAsync(function*() { + wrapAsync(function* () { const name = plugin.name || plugin; yield checkAndInstallPackage(name); // Put the installed plugin in the patternlab-config.json @@ -16,13 +14,11 @@ const installPlugin = (plugin, config) => _.set(config, `plugins[${name}]['initialized']`, false); // Get the options from the plugin, if any - const pluginPathConfig = path.resolve( - path.join(process.cwd(), 'node_modules', name, 'config.json') - ); + const pluginPathConfig = resolveFileInPackage(name, 'config.json'); try { const pluginConfigJSON = require(pluginPathConfig); if (!_.has(config.plugins[name].options)) { - _.set(config, `plugins[${name}]['options]`, pluginConfigJSON); + _.set(config, `plugins[${name}][options]`, pluginConfigJSON); } } catch (ex) { //a config.json file is not required at this time diff --git a/packages/cli/bin/install-starterkit.js b/packages/cli/bin/install-starterkit.js index f9b5f6135..016548737 100644 --- a/packages/cli/bin/install-starterkit.js +++ b/packages/cli/bin/install-starterkit.js @@ -7,17 +7,25 @@ const { checkAndInstallPackage, readJsonAsync, } = require('./utils'); +const { + resolvePackageFolder, + resolveDirInPackage, +} = require('@pattern-lab/core/src/lib/resolver'); const installStarterkit = (starterkit, config) => - wrapAsync(function*() { + wrapAsync(function* () { const sourceDir = config.paths.source.root; const name = starterkit.value || starterkit; - const url = name.startsWith('@pattern-lab/') ? name : `pattern-lab/${name}`; - yield checkAndInstallPackage(name, url); - const kitPath = path.resolve('./node_modules', name); - yield copyAsync(path.resolve(kitPath, 'dist'), path.resolve(sourceDir)); + yield checkAndInstallPackage(name); + yield copyAsync( + resolveDirInPackage(name, 'dist'), + path.resolve(process.env.projectDir || '', sourceDir) + ); let kitConfig; - const kitConfigPath = path.resolve(kitPath, 'patternlab-config.json'); + const kitConfigPath = path.join( + resolvePackageFolder(name), + 'patternlab-config.json' + ); if (fs.existsSync(kitConfigPath)) { kitConfig = yield readJsonAsync(kitConfigPath); } diff --git a/packages/cli/bin/patternlab.js b/packages/cli/bin/patternlab.js index 0e7eeed22..a645f3259 100755 --- a/packages/cli/bin/patternlab.js +++ b/packages/cli/bin/patternlab.js @@ -1,6 +1,8 @@ #!/usr/bin/env node +/* eslint-disable no-unused-vars */ 'use strict'; -const cli = require('commander'); +const { Command } = require('commander'); +const cli = new Command(); const path = require('path'); const build = require('./cli-actions/build'); const disable = require('./cli-actions/disable'); @@ -15,12 +17,11 @@ const { error, log } = require('./utils'); const pkg = require('../package.json'); // Register info and error logging -log.on('patternlab.error', err => console.log(err)); // eslint-disable-line -log.on('patternlab.info', msg => console.log(msg)); // eslint-disable-line +log.on('patternlab.error', (err) => console.log(err)); // eslint-disable-line +log.on('patternlab.info', (msg) => console.log(msg)); // eslint-disable-line // Conditionally register verbose logging -const verboseLogs = verbose => - log.on('patternlab.debug', msg => console.log(msg)); // eslint-disable-line +const verboseLogs = () => log.on('patternlab.debug', (msg) => console.log(msg)); // eslint-disable-line // Conditionally unregister all logging const silenceLogs = () => { @@ -30,7 +31,7 @@ const silenceLogs = () => { }; // Split strings into an array -const list = val => val.split(','); +const list = (val) => val.split(','); /** * Hook up cli version, usage and options @@ -38,15 +39,7 @@ const list = val => val.split(','); cli .version(version(pkg), '-V, --version') .usage(' [options]') - .arguments(' [options]') - .option( - '-c, --config ', - 'Specify config file. Default looks up the project dir', - val => val.trim(), - path.resolve(process.cwd(), 'patternlab-config.json') - ) - .option('-v, --verbose', 'Show verbose console logs', verboseLogs) - .option('--silent', 'Turn off console logs', silenceLogs); + .arguments(' [options]'); /** * build @@ -57,7 +50,7 @@ cli .alias('compile') .description('Build Pattern Lab. Optionally (re-)build only the patterns') .option('-p, --patterns-only', 'Whether to only build patterns') - .option('--no-watch', 'Start watching for changes') + .option('--watch', 'Start watching for changes') .action(build); /** @@ -134,6 +127,20 @@ cli .option('--no-watch', 'Start watching for changes') .action(serve); +// Common options can be added manually after setting up program and subcommands. +// If the options are unsorted in the help, these will appear last. +cli.commands.forEach((command) => { + command + .option( + '-c, --config ', + 'Specify config file. Default looks up the project dir', + (val) => val.trim(), + path.resolve(process.cwd(), 'patternlab-config.json') + ) + .option('-v, --verbose', 'Show verbose console logs', verboseLogs) + .option('--silent', 'Turn off console logs', silenceLogs); +}); + // Show additional help cli.on('--help', help); diff --git a/packages/cli/bin/resolve-config.js b/packages/cli/bin/resolve-config.js index f34c5e083..f81ed6aba 100644 --- a/packages/cli/bin/resolve-config.js +++ b/packages/cli/bin/resolve-config.js @@ -1,5 +1,5 @@ 'use strict'; -const exists = require('path-exists'); +const fs = require('fs-extra'); const path = require('path'); const error = require('./utils').error; const readJsonAsync = require('./utils').readJsonAsync; @@ -12,14 +12,14 @@ const wrapAsync = require('./utils').wrapAsync; * @return {object|boolean} Returns the config object or false otherwise. */ function resolveConfig(configPath) { - return wrapAsync(function*() { + return wrapAsync(function* () { if (typeof configPath !== 'string') { error( 'resolveConfig: If configPath is set, it is expected to be of type string.' ); return false; } - if (!exists.sync(configPath)) { + if (!fs.existsSync(configPath)) { error(`resolveConfig: configPath ${configPath} does not exists`); return false; } diff --git a/packages/cli/bin/scaffold.js b/packages/cli/bin/scaffold.js index f817ac50d..ac2b4378b 100644 --- a/packages/cli/bin/scaffold.js +++ b/packages/cli/bin/scaffold.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); const execa = require('execa'); -const fs = require('fs'); +const fs = require('fs-extra'); const wrapAsync = require('./utils').wrapAsync; const mkdirsAsync = require('./utils').mkdirsAsync; @@ -15,9 +15,13 @@ const mkdirsAsync = require('./utils').mkdirsAsync; * @return {void} */ const scaffold = (projectDir, sourceDir, publicDir, exportDir) => - wrapAsync(function*() { - if (!fs.existsSync(path.resolve(projectDir, 'package.json'))) { - execa.sync('npm', ['init', '-y']); + wrapAsync(function* () { + const projectPath = path.join(process.cwd(), projectDir); + if (!fs.existsSync(path.join(projectPath, 'package.json'))) { + fs.ensureDirSync(projectPath); + execa.sync('npm', ['init', '-y'], { + cwd: projectPath, + }); } /** * Create mandatory files structure diff --git a/packages/cli/bin/utils.js b/packages/cli/bin/utils.js index aae408bbb..dbf6e3aa8 100644 --- a/packages/cli/bin/utils.js +++ b/packages/cli/bin/utils.js @@ -6,6 +6,10 @@ const path = require('path'); const chalk = require('chalk'); const EventEmitter = require('events').EventEmitter; const hasYarn = require('has-yarn'); +const { + resolvePackageFolder, + resolveFileInPackage, +} = require('@pattern-lab/core/src/lib/resolver'); /** * @name log @@ -62,7 +66,7 @@ const error = log.error.bind(log); * @desc Wraps an generator function to yield out promisified stuff * @param {function} fn - Takes a generator function */ -const wrapAsync = fn => +const wrapAsync = (fn) => new Promise((resolve, reject) => { const generator = fn(); /* eslint-disable */ @@ -80,9 +84,7 @@ const wrapAsync = fn => if (res.done) { return resolve(v); } - Promise.resolve(v) - .then(spwn) - .catch(spwn); + Promise.resolve(v).then(spwn).catch(spwn); })(); /* eslint-enable */ }); @@ -96,10 +98,8 @@ const wrapAsync = fn => */ const asyncGlob = (pattern, opts) => new Promise((resolve, reject) => - glob( - pattern, - opts, - (err, matches) => (err !== null ? reject(err) : resolve(matches)) + glob(pattern, opts, (err, matches) => + err !== null ? reject(err) : resolve(matches) ) ); @@ -112,13 +112,13 @@ const asyncGlob = (pattern, opts) => * @return {Promise} */ const copyWithPattern = (cwd, pattern, dest) => - wrapAsync(function*() { + wrapAsync(function* () { const files = yield asyncGlob(pattern, { cwd: cwd }); if (files.length === 0) { debug('copy: Nothing to copy'); } // Copy concurrently - const promises = files.map(file => + const promises = files.map((file) => fs.copy(path.join(cwd, file), path.join(dest, file)) ); return yield Promise.all(promises); @@ -126,18 +126,21 @@ const copyWithPattern = (cwd, pattern, dest) => /** * @func fetchPackage - * @desc Fetches and saves packages from npm into node_modules and adds a reference in the package.json under dependencies + * @desc Fetches packages from an npm package registry and adds a reference in the package.json under dependencies * @param {string} packageName - The package name - * @param {string} [url] - A URL which will be used to fetch the package from */ -const fetchPackage = (packageName, url) => - wrapAsync(function*() { +const fetchPackage = (packageName) => + wrapAsync(function* () { const useYarn = hasYarn(); const pm = useYarn ? 'yarn' : 'npm'; const installCmd = useYarn ? 'add' : 'install'; try { - if (packageName || url) { - const cmd = yield spawn(pm, [installCmd, url || packageName]); + if (packageName) { + const opts = {}; + if (process.env.projectDir) { + opts.cwd = process.env.projectDir; + } + const cmd = yield spawn(pm, [installCmd, packageName], opts); error(cmd.stderr); } } catch (err) { @@ -152,19 +155,18 @@ const fetchPackage = (packageName, url) => * @func checkAndInstallPackage * Checks whether a package for a given packageName is installed locally. If package cannot be found, fetch and install it * @param {string} packageName - The package name - * @param {string} [url] - A URL which will be used to fetch the package from * @return {boolean} */ -const checkAndInstallPackage = (packageName, url) => - wrapAsync(function*() { +const checkAndInstallPackage = (packageName) => + wrapAsync(function* () { try { - require.resolve(packageName); + resolvePackageFolder(packageName); return true; } catch (err) { debug( `checkAndInstallPackage: ${packageName} not installed. Fetching it now …` ); - yield fetchPackage(packageName, url); + yield fetchPackage(packageName); return false; } }); @@ -182,7 +184,7 @@ const noop = () => {}; * @param {object} data */ const writeJsonAsync = (filePath, data) => - wrapAsync(function*() { + wrapAsync(function* () { yield fs.outputJSON(filePath, data, { spaces: 2 }); }); @@ -194,10 +196,10 @@ const writeJsonAsync = (filePath, data) => * @param {object} fileName - the filePath of the JSON */ const getJSONKey = (packageName, key, fileName = 'package.json') => - wrapAsync(function*() { + wrapAsync(function* () { yield checkAndInstallPackage(packageName); const jsonData = yield fs.readJson( - path.resolve('node_modules', packageName, fileName) + resolveFileInPackage(packageName, fileName) ); return jsonData[key]; }); diff --git a/packages/cli/license b/packages/cli/license index ec350935b..e4746ea6b 100644 --- a/packages/cli/license +++ b/packages/cli/license @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Raphael Okon +Copyright Patternlab contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/cli/package.json b/packages/cli/package.json index 2ea9f8808..ddfe4da2e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,37 +1,35 @@ { "name": "@pattern-lab/cli", "description": "Command-line interface (CLI) for the @pattern-lab/core.", - "version": "0.0.3-alpha.0", + "version": "6.1.0", "bin": { "patternlab": "bin/patternlab.js" }, "author": { - "name": "Raphael Okon" + "name": "Patternlab contributors" }, "dependencies": { - "@pattern-lab/core": "^3.0.1-alpha.0", - "@pattern-lab/live-server": "^1.3.3-beta.1", - "archiver": "2.1.1", - "chalk": "2.4.1", - "commander": "2.15.1", - "deepmerge": "^2.1.1", - "execa": "0.10.0", - "fs-extra": "6.0.1", - "glob": "7.1.2", - "has-yarn": "1.0.0", - "inquirer": "5.1.0", - "lodash": "4.17.10", - "ora": "2.1.0", - "path-exists": "3.0.0", - "sanitize-filename": "1.6.1" + "@pattern-lab/core": "^6.1.0", + "archiver": "5.3.0", + "chalk": "4.1.0", + "commander": "9.4.1", + "deepmerge": "^4.2.2", + "execa": "5.0.0", + "fs-extra": "10.0.0", + "glob": "7.1.6", + "has-yarn": "2.1.0", + "inquirer": "8.0.0", + "lodash": "4.17.21", + "ora": "5.4.0" }, "devDependencies": { + "dos2unix-cli": "^1.0.1", "eslint": "4.18.2", "eslint-config-prettier": "2.9.0", "eslint-plugin-prettier": "2.6.0", - "prettier": "1.11.1", - "proxyquire": "2.0.1", - "tap": "11.1.1" + "prettier": "2.8.1", + "proxyquire": "2.1.3", + "tap": "14.11.0" }, "files": [ "bin" @@ -44,15 +42,17 @@ ], "scripts": { "lint": "eslint ./{bin,test}", - "test:separate": "tap './test/*.test.js' --reporter spec --timeout=120" + "test:separate": "tap './test/*.test.js' --reporter spec --timeout=120", + "prepublish": "npx dos2unix-cli bin/patternlab.js" }, "repository": "https://github.com/pattern-lab/patternlab-node/tree/master/packages/cli", "bugs": "https://github.com/pattern-lab/patternlab-node/issues", "license": "MIT", "engines": { - "node": ">=10.0" + "node": ">=16.20.0" }, "publishConfig": { "access": "public" - } + }, + "gitHead": "80f62be442223e09bafb30d0529cbd768e03f2ac" } diff --git a/packages/cli/readme.md b/packages/cli/readme.md index e5a9ae95e..b415e63dd 100644 --- a/packages/cli/readme.md +++ b/packages/cli/readme.md @@ -2,7 +2,8 @@ > Command-line interface (CLI) for the patternlab-node core. -[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) +[![Continuous Integration](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml) +[![CodeQL](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml) ## Installation @@ -93,8 +94,8 @@ Passing no options starts the init in interactive mode Options: -h, --help output usage information -p, --project-dir Specify a project directory. Default: ./ - -e, --edition Specify an edition to install. Default: edition-node - -k, --starterkit Specify a starterkit to install. Default: starterkit-mustache-base + -e, --edition Specify an edition to install. Default: @pattern-lab/edition-node + -k, --starterkit Specify a starterkit to install. Default: @pattern-lab/starterkit-handlebars-demo ``` ### Serve Pattern Lab @@ -139,4 +140,4 @@ Installs Pattern Lab related modules like starterkits or plugins $ patternlab build --config # Builds Pattern Lab from different project directory ``` ## License -MIT © [Raphael Okon](https://github.com/raphaelokon) +MIT © [Patternlab contributors](https://github.com/pattern-lab/patternlab-node/blob/master/CODEOWNERS) diff --git a/packages/cli/test/build.test.js b/packages/cli/test/build.test.js index 6a56cb6fe..8ee4770f4 100644 --- a/packages/cli/test/build.test.js +++ b/packages/cli/test/build.test.js @@ -10,7 +10,7 @@ const build = proxyquire('../bin/build', { }); const opts = { patternsOnly: true }; -tap.test('Build ->', t => { +tap.test('Build ->', (t) => { t.throws( () => { build(); diff --git a/packages/cli/test/cli-build.test.js b/packages/cli/test/cli-build.test.js index d6712deae..644d56429 100644 --- a/packages/cli/test/cli-build.test.js +++ b/packages/cli/test/cli-build.test.js @@ -1,4 +1,4 @@ -const exists = require('path-exists'); +const fs = require('fs-extra'); const getUniqueProjectPath = require('./utils/getUniqueProjectPath'); const path = require('path'); const spawnCmd = require('./utils/spawnCmd'); @@ -7,8 +7,8 @@ const wrapAsync = require('../bin/utils').wrapAsync; const projectRoot = getUniqueProjectPath(); -tap.test('Init and build ->', t => - wrapAsync(function*() { +tap.test('Init and build ->', (t) => + wrapAsync(function* () { yield spawnCmd([ 'init', '--verbose', @@ -17,7 +17,7 @@ tap.test('Init and build ->', t => '--edition', '@pattern-lab/edition-node', '--starterkit', - '@pattern-lab/starterkit-mustache-demo', + '@pattern-lab/starterkit-handlebars-demo', ]); yield spawnCmd([ 'build', @@ -25,23 +25,23 @@ tap.test('Init and build ->', t => `${projectRoot}/patternlab-config.json`, ]); t.ok( - exists.sync(path.resolve(projectRoot, 'public')), + fs.existsSync(path.resolve(projectRoot, 'public')), 'should build all files into public dir' ); t.ok( - exists.sync(path.resolve(projectRoot, 'public', 'annotations')), + fs.existsSync(path.resolve(projectRoot, 'public', 'annotations')), 'with an annotations dir' ); t.ok( - exists.sync(path.resolve(projectRoot, 'public', 'css')), + fs.existsSync(path.resolve(projectRoot, 'public', 'css')), 'with a css dir' ); t.ok( - exists.sync(path.resolve(projectRoot, 'public', 'images')), + fs.existsSync(path.resolve(projectRoot, 'public', 'images')), 'with a images dir' ); t.ok( - exists.sync(path.resolve(projectRoot, 'public', 'styleguide')), + fs.existsSync(path.resolve(projectRoot, 'public', 'styleguide')), 'with a styleguide dir' ); t.end(); diff --git a/packages/cli/test/cli-disable.test.js b/packages/cli/test/cli-disable.test.js index 64715b882..dfe2f2925 100644 --- a/packages/cli/test/cli-disable.test.js +++ b/packages/cli/test/cli-disable.test.js @@ -6,8 +6,8 @@ const wrapAsync = require('../bin/utils').wrapAsync; const projectRoot = getUniqueProjectPath(); -tap.test('Disable ->', t => - wrapAsync(function*() { +tap.test('Disable ->', (t) => + wrapAsync(function* () { yield spawnCmd([ 'init', '--verbose', @@ -16,7 +16,7 @@ tap.test('Disable ->', t => '--edition', '@pattern-lab/edition-node', '--starterkit', - '@pattern-lab/starterkit-mustache-base', + '@pattern-lab/starterkit-handlebars-vanilla', ]); yield spawnCmd([ 'install', diff --git a/packages/cli/test/cli-enable.test.js b/packages/cli/test/cli-enable.test.js index 62b7d837a..8ea48d7ef 100644 --- a/packages/cli/test/cli-enable.test.js +++ b/packages/cli/test/cli-enable.test.js @@ -6,8 +6,8 @@ const wrapAsync = require('../bin/utils').wrapAsync; const projectRoot = getUniqueProjectPath(); -tap.test('Enable ->', t => - wrapAsync(function*() { +tap.test('Enable ->', (t) => + wrapAsync(function* () { yield spawnCmd([ 'init', '--verbose', @@ -16,7 +16,7 @@ tap.test('Enable ->', t => '--edition', '@pattern-lab/edition-node', '--starterkit', - '@pattern-lab/starterkit-mustache-base', + '@pattern-lab/starterkit-handlebars-vanilla', ]); yield spawnCmd([ 'install', diff --git a/packages/cli/test/cli-export.test.js b/packages/cli/test/cli-export.test.js index 63e82ba06..e0caa8e7d 100644 --- a/packages/cli/test/cli-export.test.js +++ b/packages/cli/test/cli-export.test.js @@ -1,4 +1,4 @@ -const exists = require('path-exists'); +const fs = require('fs-extra'); const getUniqueProjectPath = require('./utils/getUniqueProjectPath'); const path = require('path'); const spawnCmd = require('./utils/spawnCmd'); @@ -7,8 +7,8 @@ const wrapAsync = require('../bin/utils').wrapAsync; const projectRoot = getUniqueProjectPath(); -tap.test('Init and export ->', t => - wrapAsync(function*() { +tap.test('Init and export ->', (t) => + wrapAsync(function* () { yield spawnCmd([ 'init', '--verbose', @@ -17,7 +17,7 @@ tap.test('Init and export ->', t => '--edition', '@pattern-lab/edition-node', '--starterkit', - '@pattern-lab/starterkit-mustache-base', + '@pattern-lab/starterkit-handlebars-vanilla', ]); yield spawnCmd([ 'export', @@ -25,7 +25,9 @@ tap.test('Init and export ->', t => `${projectRoot}/patternlab-config.json`, ]); t.ok( - exists.sync(path.resolve(projectRoot, 'pattern_exports', 'patterns.zip')), + fs.existsSync( + path.resolve(projectRoot, 'pattern_exports', 'patterns.zip') + ), ' should create patterns.zip' ); t.end(); diff --git a/packages/cli/test/cli-init.test.js b/packages/cli/test/cli-init.test.js index a80c031ff..34ad1d190 100644 --- a/packages/cli/test/cli-init.test.js +++ b/packages/cli/test/cli-init.test.js @@ -1,4 +1,4 @@ -const exists = require('path-exists'); +const fs = require('fs-extra'); const getUniqueProjectPath = require('./utils/getUniqueProjectPath'); const path = require('path'); const spawnCmd = require('./utils/spawnCmd'); @@ -7,8 +7,8 @@ const wrapAsync = require('../bin/utils').wrapAsync; const projectRoot = getUniqueProjectPath(); -tap.test('Init ->', t => - wrapAsync(function*() { +tap.test('Init ->', (t) => + wrapAsync(function* () { yield spawnCmd([ 'init', '--verbose', @@ -17,20 +17,26 @@ tap.test('Init ->', t => '--edition', '@pattern-lab/edition-node', '--starterkit', - '@pattern-lab/starterkit-mustache-base', + '@pattern-lab/starterkit-handlebars-vanilla', ]); t.ok( - exists.sync(path.resolve(projectRoot)), + fs.existsSync(path.resolve(projectRoot)), 'should initialize a Pattern Lab project' ); - t.ok(exists.sync(path.resolve(projectRoot, 'source')), 'with a source dir'); - t.ok(exists.sync(path.resolve(projectRoot, 'public')), 'with a public dir'); t.ok( - exists.sync(path.resolve(projectRoot, 'pattern_exports')), + fs.existsSync(path.resolve(projectRoot, 'source')), + 'with a source dir' + ); + t.ok( + fs.existsSync(path.resolve(projectRoot, 'public')), + 'with a public dir' + ); + t.ok( + fs.existsSync(path.resolve(projectRoot, 'pattern_exports')), 'with a pattern_exports dir' ); t.ok( - exists.sync(path.resolve(projectRoot, 'patternlab-config.json')), + fs.existsSync(path.resolve(projectRoot, 'patternlab-config.json')), 'with a pattern_exports dir' ); t.end(); diff --git a/packages/cli/test/export.test.js b/packages/cli/test/export.test.js index 169b60771..e9b600b24 100644 --- a/packages/cli/test/export.test.js +++ b/packages/cli/test/export.test.js @@ -2,10 +2,10 @@ const exportPatterns = require('../bin/cli-actions/export'); const tap = require('tap'); const wrapAsync = require('../bin/utils').wrapAsync; -tap.test('Export ->', t => { +tap.test('Export ->', (t) => { t.plan(2); - t.test('with options empty', tt => - wrapAsync(function*() { + t.test('with options empty', (tt) => + wrapAsync(function* () { try { yield exportPatterns(); } catch (err) { @@ -14,8 +14,8 @@ tap.test('Export ->', t => { } }) ); - t.test('with options not an object', tt => - wrapAsync(function*() { + t.test('with options not an object', (tt) => + wrapAsync(function* () { try { yield exportPatterns(123); } catch (err) { diff --git a/packages/cli/test/fixtures/patternlab-config.json b/packages/cli/test/fixtures/patternlab-config.json index 6102f522f..615be9273 100644 --- a/packages/cli/test/fixtures/patternlab-config.json +++ b/packages/cli/test/fixtures/patternlab-config.json @@ -46,8 +46,8 @@ "node_modules/@pattern-lab/uikit-workshop/views/partials/general-footer.mustache", "patternSection": "node_modules/@pattern-lab/uikit-workshop/views/partials/patternSection.mustache", - "patternSectionSubtype": - "node_modules/@pattern-lab/uikit-workshop/views/partials/patternSectionSubtype.mustache", + "patternSectionSubgroup": + "node_modules/@pattern-lab/uikit-workshop/views/partials/patternSectionSubgroup.mustache", "viewall": "node_modules/@pattern-lab/uikit-workshop/views/viewall.mustache" }, @@ -68,10 +68,12 @@ "css": "./test/fixtures/public/css" } }, - "patternExtension": "mustache", + "patternExtension": "hbs", "patternStateCascade": ["inprogress", "inreview", "complete"], "patternExportDirectory": "./pattern_exports/", "patternExportPatternPartials": [], + "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, @@ -81,5 +83,15 @@ "color": "dark", "density": "compact", "layout": "horizontal" - } + }, + "engines": { + "handlebars": { + "package": "@pattern-lab/engine-handlebars", + "fileExtensions": [ + "handlebars", + "hbs" + ], + "extend": "helpers/*.js" + } + } } diff --git a/packages/cli/test/install-plugin.test.js b/packages/cli/test/install-plugin.test.js index 269953007..c941d95d1 100644 --- a/packages/cli/test/install-plugin.test.js +++ b/packages/cli/test/install-plugin.test.js @@ -14,8 +14,8 @@ const minimalConfig = { }, }; -tap.test('Install plugin-tab ->', t => - wrapAsync(function*() { +tap.test('Install plugin-tab ->', (t) => + wrapAsync(function* () { yield installPlugin('@pattern-lab/plugin-tab', minimalConfig); const pkg = yield moduleExist('@pattern-lab/plugin-tab'); t.ok(pkg, 'module should exist after install'); diff --git a/packages/cli/test/install-starterkit.test.js b/packages/cli/test/install-starterkit.test.js index 0cda685c9..97a7599c1 100644 --- a/packages/cli/test/install-starterkit.test.js +++ b/packages/cli/test/install-starterkit.test.js @@ -14,64 +14,34 @@ const minimalConfig = { }, }; -tap.test('Install starterkit-mustache-demo ->', t => - wrapAsync(function*() { +tap.test('Install @pattern-lab/starterkit-handlebars-vanilla ->', (t) => + wrapAsync(function* () { yield installStarterkit( - '@pattern-lab/starterkit-mustache-demo', + '@pattern-lab/starterkit-handlebars-vanilla', minimalConfig ); - const pkg = yield moduleExist('@pattern-lab/starterkit-mustache-demo'); + const pkg = yield moduleExist('@pattern-lab/starterkit-handlebars-vanilla'); t.ok(pkg, 'module should exist after install'); t.end(); }) ); -tap.test('Install starterkit-mustache-base ->', t => - wrapAsync(function*() { +tap.test('Install @pattern-lab/starterkit-handlebars-demo ->', (t) => + wrapAsync(function* () { yield installStarterkit( - '@pattern-lab/starterkit-mustache-base', + '@pattern-lab/starterkit-handlebars-demo', minimalConfig ); - const pkg = yield moduleExist('@pattern-lab/starterkit-mustache-base'); + const pkg = yield moduleExist('@pattern-lab/starterkit-handlebars-demo'); t.ok(pkg, 'module should exist after install'); t.end(); }) ); -tap.test('Install starterkit-mustache-bootstrap ->', t => - wrapAsync(function*() { - yield installStarterkit('starterkit-mustache-bootstrap', minimalConfig); - const pkg = yield moduleExist('starterkit-mustache-bootstrap'); - t.ok(pkg, 'module should exist after install'); - t.end(); - }) -); - -tap.test('Install starterkit-mustache-foundation ->', t => - wrapAsync(function*() { - yield installStarterkit('starterkit-mustache-foundation', minimalConfig); - const pkg = yield moduleExist('starterkit-mustache-foundation'); - t.ok(pkg, 'module should exist after install'); - t.end(); - }) -); - -tap.test('Install starterkit-mustache-acidtest ->', t => - wrapAsync(function*() { - yield installStarterkit('starterkit-mustache-acidtest', minimalConfig); - const pkg = yield moduleExist('starterkit-mustache-acidtest'); - t.ok(pkg, 'module should exist after install'); - t.end(); - }) -); - -tap.test('Install starterkit-mustache-materialdesign ->', t => - wrapAsync(function*() { - yield installStarterkit( - 'starterkit-mustache-materialdesign', - minimalConfig - ); - const pkg = yield moduleExist('starterkit-mustache-materialdesign'); +tap.test('Install @pattern-lab/starterkit-twig-demo ->', (t) => + wrapAsync(function* () { + yield installStarterkit('@pattern-lab/starterkit-twig-demo', minimalConfig); + const pkg = yield moduleExist('@pattern-lab/starterkit-twig-demo'); t.ok(pkg, 'module should exist after install'); t.end(); }) diff --git a/packages/cli/test/mocks/liverserver.mock.js b/packages/cli/test/mocks/liverserver.mock.js index 754fd5fc1..868f34fd5 100644 --- a/packages/cli/test/mocks/liverserver.mock.js +++ b/packages/cli/test/mocks/liverserver.mock.js @@ -1,12 +1,12 @@ function liveServerMock() { return { - reload: function() { + reload: function () { return true; }, - refreshCSS: function() { + refreshCSS: function () { return true; }, - start: function() { + start: function () { return true; }, }; diff --git a/packages/cli/test/mocks/patternlab.mock.js b/packages/cli/test/mocks/patternlab.mock.js index 7186ca734..718767245 100644 --- a/packages/cli/test/mocks/patternlab.mock.js +++ b/packages/cli/test/mocks/patternlab.mock.js @@ -1,18 +1,18 @@ function patternLabMock() { return { - build: function() { + build: function () { return true; }, - help: function() { + help: function () { return true; }, - patternsonly: function() { + patternsonly: function () { return true; }, - liststarterkits: function() { + liststarterkits: function () { return true; }, - loadstarterkit: function() { + loadstarterkit: function () { return true; }, }; diff --git a/packages/cli/test/replace_config_paths.test.js b/packages/cli/test/replace_config_paths.test.js index 6a98385ac..11d5bd84d 100644 --- a/packages/cli/test/replace_config_paths.test.js +++ b/packages/cli/test/replace_config_paths.test.js @@ -3,7 +3,7 @@ const tap = require('tap'); const replaceConfigPaths = require('../bin/replace-config'); const config = patternlab.getDefaultConfig(); -tap.test('replaceConfigPaths ->', t => { +tap.test('replaceConfigPaths ->', (t) => { const newConfig = replaceConfigPaths( config, 'projectDir', diff --git a/packages/cli/test/resolve_config.test.js b/packages/cli/test/resolve_config.test.js index 36c250d9a..87feb8231 100644 --- a/packages/cli/test/resolve_config.test.js +++ b/packages/cli/test/resolve_config.test.js @@ -2,8 +2,8 @@ const tap = require('tap'); const wrapAsync = require('../bin/utils').wrapAsync; const resolveConfig = require('../bin/resolve-config'); -tap.test('resolveConfig ->', t => - wrapAsync(function*() { +tap.test('resolveConfig ->', (t) => + wrapAsync(function* () { const config = yield resolveConfig( './test/fixtures/patternlab-config.json' ); diff --git a/packages/cli/test/scaffold.test.js b/packages/cli/test/scaffold.test.js index c63d2365d..f1f3037d5 100644 --- a/packages/cli/test/scaffold.test.js +++ b/packages/cli/test/scaffold.test.js @@ -1,6 +1,6 @@ const tap = require('tap'); const path = require('path'); -const exists = require('path-exists'); +const fs = require('fs-extra'); const scaffold = require('../bin/scaffold'); const getUniqueProjectPath = require('./utils/getUniqueProjectPath'); const wrapAsync = require('../bin/utils').wrapAsync; @@ -10,20 +10,20 @@ const sourceDir = 'source'; const publicDir = 'public'; const exportDir = 'patterns_export'; -tap.test('Scaffold ->', t => - wrapAsync(function*() { +tap.test('Scaffold ->', (t) => + wrapAsync(function* () { yield scaffold(projectDir, sourceDir, publicDir, exportDir); - t.ok(exists.sync(path.resolve(projectDir)), 'should create project dir'); + t.ok(fs.existsSync(path.resolve(projectDir)), 'should create project dir'); t.ok( - exists.sync(path.resolve(projectDir, sourceDir)), + fs.existsSync(path.resolve(projectDir, sourceDir)), 'should create source dir' ); t.ok( - exists.sync(path.resolve(projectDir, publicDir)), + fs.existsSync(path.resolve(projectDir, publicDir)), 'should create public dir' ); t.ok( - exists.sync(path.resolve(projectDir, exportDir)), + fs.existsSync(path.resolve(projectDir, exportDir)), 'should create export dir' ); t.end(); diff --git a/packages/cli/test/serve.test.js b/packages/cli/test/serve.test.js index c322cc41d..0d733cde0 100644 --- a/packages/cli/test/serve.test.js +++ b/packages/cli/test/serve.test.js @@ -10,8 +10,8 @@ const preview = proxyquire('../bin/serve', { '@pattern-lab/core': patternLabMock, }); -tap.test('Serve ->', t => - wrapAsync(function*() { +tap.test('Serve ->', (t) => + wrapAsync(function* () { const config = yield resolveConfig( './test/fixtures/patternlab-config.json' ); diff --git a/packages/cli/test/utils/spawnCmd.js b/packages/cli/test/utils/spawnCmd.js index 4d0623515..f02cb91d4 100644 --- a/packages/cli/test/utils/spawnCmd.js +++ b/packages/cli/test/utils/spawnCmd.js @@ -4,8 +4,8 @@ const wrapAsync = require('../../bin/utils').wrapAsync; const cli = path.resolve(__dirname, '../../bin/patternlab.js'); const spawnCmd = (args, endFn) => - wrapAsync(function*() { - const fn = endFn || function() {}; + wrapAsync(function* () { + const fn = endFn || function () {}; yield spawn('node', [cli].concat(args)); fn(); }); diff --git a/packages/core/.eslintrc.js b/packages/core/.eslintrc.js new file mode 100644 index 000000000..5a2cc7f1e --- /dev/null +++ b/packages/core/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['../../.eslintrc.js'], +}; diff --git a/packages/core/.npmignore b/packages/core/.npmignore new file mode 100644 index 000000000..c1e1ac97f --- /dev/null +++ b/packages/core/.npmignore @@ -0,0 +1,2 @@ +test +.nyc_output diff --git a/packages/core/.nvmrc b/packages/core/.nvmrc index 95c4e8d27..59ea99ee6 100644 --- a/packages/core/.nvmrc +++ b/packages/core/.nvmrc @@ -1 +1 @@ -10.0.0 \ No newline at end of file +16.20 diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 9da413dfa..1dbed1bf9 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -3,6 +3,373 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + + +### Bug Fixes + +* **twig engine:** startup and running problems ([#1478](https://github.com/pattern-lab/patternlab-node/issues/1478)) ([e5a1904](https://github.com/pattern-lab/patternlab-node/commit/e5a19049f083315939406677b1c0480f4b420569)) + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + + +### Features + +* integrate @hadl/patternlab-plugin-pattern-wrap into core ([#1433](https://github.com/pattern-lab/patternlab-node/issues/1433)) ([414e038](https://github.com/pattern-lab/patternlab-node/commit/414e0383732b4bc4682981000908d1e0d1292703)), closes [#1432](https://github.com/pattern-lab/patternlab-node/issues/1432) [#1432](https://github.com/pattern-lab/patternlab-node/issues/1432) + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + + +### Bug Fixes + +* code scanning alert ([#1442](https://github.com/pattern-lab/patternlab-node/issues/1442)) ([749a3e7](https://github.com/pattern-lab/patternlab-node/commit/749a3e722249846c522e3f7de6e73b5afa8531b1)) + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + + +### Bug Fixes + +* transformed asset types is ignored ([#1426](https://github.com/pattern-lab/patternlab-node/issues/1426)) ([8cbe189](https://github.com/pattern-lab/patternlab-node/commit/8cbe189d45afaa753ce6de41bdd9de1596e074f3)), closes [#1339](https://github.com/pattern-lab/patternlab-node/issues/1339) + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.15.1...v5.15.2) (2021-11-03) + + +### Bug Fixes + +* **core:** Subgroup cannot be hidden ([#1368](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1368)) ([3ce13ab](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/3ce13abffaab2810194003aeca88be671fedd38f)) + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.15.0...v5.15.1) (2021-10-16) + + +### Bug Fixes + +* **node16:** prevent warning on installation process ([#1352](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1352)) ([d58e4c6](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/d58e4c6f2979f5e0bba9a14e17e0dbc4afc64f75)) + + +### Features + +* added https description to the docs ([#1355](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1355)) ([4118f74](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/4118f740810842b16cf86b9ee28bda2a623aa9c7)) + + +### Reverts + +* Revert "refactor: optimized engines directory retrieval (#1359)" (#1363) ([a275d36](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/a275d36c50c3846fc51c78baf6e11dba5309f5dc)), closes [#1359](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1359) [#1363](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1363) + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.14.3...v5.15.0) (2021-07-01) + + +### Features + +* **documentation:** added (sub)groups documentation again [#1262](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1262) ([#1334](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1334)) ([9fac269](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/9fac2699d2f6c64c4544e8e4d8e18c1a1ce7e49f)) + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.14.1...v5.14.2) (2021-03-28) + + +### Bug Fixes + +* **core:** ReadDocumentation throw error on older node versions ([#1295](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1295)) ([399d0e1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/399d0e118ab77a414a926b078da9abbcb5347969)) + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.10.2...v5.11.1) (2020-06-28) + + +### Bug Fixes + +* enable partial build via option ([8aaa533](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/8aaa53398563ade14123c481bf509f9ee0c768f5)) + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.10.2...v5.11.0) (2020-06-28) + + +### Bug Fixes + +* enable partial build via option ([8aaa533](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/8aaa53398563ade14123c481bf509f9ee0c768f5)) + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1192) ([cae9420](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/cae94208c52e4068430e048e729f4ff97847715a)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/issues/1192) ([b4eb12e](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/b4eb12e68ceb402964a7e303610e5b0c008876ba)) + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package @pattern-lab/core + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.8.0...v5.9.0) (2020-04-24) + + +### Bug Fixes + +* **core:** do not warn about uikit-polyfills ([6bb68e7](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/6bb68e763769969546542bf7aaf6d1f4235c6622)) + + + + + +# [5.7.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.6.0...v5.7.0) (2020-02-17) + +**Note:** Version bump only for package @pattern-lab/core + + + + + + +# [5.4.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.3.3...v5.4.0) (2019-11-26) + + +### Bug Fixes + +* add a new method to check if PL is currently compiling + add new method to get the config PL is using ([26e886c](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/26e886c93db5d135c91de648724f7278c4d5b3e9)) + + + + + +# [5.3.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.2.0...v5.3.0) (2019-11-13) + + +### Bug Fixes + +* **core:** re-add cleanPublic fix ([c100bbc](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/c100bbca3f339e9132acb9c482e98c1c8a66b8b5)) + + + + + +# [5.1.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v5.0.2...v5.1.0) (2019-10-29) + + +### Features + +* **config:** add new default pattern export options ([a7487a0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/a7487a0681cb11e6f3c5c8eaefd62e5648ad5ea3)) +* **core:** fix pattern export all conflicts ([b210d82](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/b210d820ba8ac0b64c82c7ff0f18c9f8a900fce2)) + + + + + +# [5.0.0](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + + +### Bug Fixes + +* add eslint fixes ([00d7bbe](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/00d7bbe319ea77a6ee8cc9cd0348856feaaf13ad)) +* correct typo in build logging ([96d989f](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/96d989f8869630ba9f59705bfca66755f20e35ab)) +* updates to address eslint / prettier issues ([d945acc](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/d945acc13b8e4e36f3815b017fbc12266c323d1f)) +* updates to fix eslint / prettier issues; update packages/core to reuse root .eslintrc.js file ([5b7a057](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/5b7a057d46ccd16b5832af1441030c7b76f237a8)) +* **1049:** Treat folders like patterns only if they're subfolders of pattern groupings ([4eb79ab](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/4eb79ab48b335a35b2e5ed3b7053974b8e8bb6b6)) +* **core:** allow plugin resolution to follow normal algorithm ([3f6b83b](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/3f6b83be080c88aec1d8b73bececb76f0f57a79d)) +* **core:** find plugins from config only and with simpler args ([fe7351c](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/fe7351cba346425512cbb2ef3a1b7728ab06ae60)) +* **plugin:** correct spelling error and function locations ([d4abd88](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/d4abd88cb017550002407241b5045a2ad1adb1dc)) + + +### Features + +* **core:** invoke registered plugin hooks ([a54d775](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/a54d7753b6939fe6a58da543f4fb34f64dd8901a)) +* **plugin-tab, core:** initial plugin hook exploration ([2f3d39a](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/2f3d39ac6b125ad4c6b872e27ee224ce2ea33a12)) + + +### BREAKING CHANGES + +* **core:** plugins now use async functions instead of events + + + + + + +## [3.0.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/@pattern-lab/core@3.0.1...@pattern-lab/core@3.0.2) (2019-08-23) + + +### Bug Fixes + +* add eslint fixes ([00d7bbe](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/00d7bbe)) +* correct typo in build logging ([96d989f](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/96d989f)) +* updates to address eslint / prettier issues ([d945acc](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/d945acc)) +* updates to fix eslint / prettier issues; update packages/core to reuse root .eslintrc.js file ([5b7a057](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/commit/5b7a057)) + + + + + + +## [3.0.1](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/@pattern-lab/core@3.0.1-alpha.0...@pattern-lab/core@3.0.1) (2019-05-16) + +**Note:** Version bump only for package @pattern-lab/core + + + + + # [3.0.0-beta.2](https://github.com/pattern-lab/patternlab-node/tree/master/packages/core/compare/@pattern-lab/core@3.0.0-beta.0...@pattern-lab/core@3.0.0-beta.2) (2019-02-09) diff --git a/packages/core/LICENSE b/packages/core/LICENSE index c9b8c1daa..3bb526cd2 100644 --- a/packages/core/LICENSE +++ b/packages/core/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2018 Brian Muenzenmeyer, http://brianmuenzenmeyer.com & Brad Frost, http://bradfrostweb.com +Copyright (c) 2018 Brian Muenzenmeyer, https://brianmuenzenmeyer.com & Brad Frost, https://bradfrost.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/packages/core/README.md b/packages/core/README.md index f6a81c7bd..1cc57aaf0 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,6 +1,7 @@ ![Pattern Lab Logo](https://github.com/pattern-lab/patternlab-node/raw/master/patternlab.png 'Pattern Lab Logo') -[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) +[![Continuous Integration](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/continuous-integration.yml) +[![CodeQL](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml/badge.svg?branch=dev)](https://github.com/pattern-lab/patternlab-node/actions/workflows/codeql-analysis.yml) ![current release](https://img.shields.io/npm/v/@pattern-lab/core.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Coverage Status](https://coveralls.io/repos/github/pattern-lab/patternlab-node/badge.svg?branch=master)](https://coveralls.io/github/pattern-lab/patternlab-node?branch=master) @@ -10,7 +11,7 @@ # Pattern Lab Node Core -This is the core API and orchestrator of the [Pattern Lab ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). +This is the core API and orchestrator of the [Pattern Lab ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). ## Installation @@ -35,9 +36,9 @@ For users wanting a more pre-packaged experience several editions are available. ## Ecosystem -![Pattern Lab Ecosystem](http://patternlab.io/assets/pattern-lab-2-image_18-large-opt.png) +![Pattern Lab Ecosystem](https://patternlab.io/images/pattern-lab-2-image_18-large-opt.png) -Core, and Editions, are part of the [Pattern Lab Ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). With this architecture, we encourage people to write and maintain their own Editions, Starterkits, and even PatternEngines. +Core, and Editions, are part of the [Pattern Lab Ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). With this architecture, we encourage people to write and maintain their own Editions, Starterkits, and even PatternEngines. ## Usage @@ -59,7 +60,7 @@ patternlab.serve({ }); ``` -* Read more about [configuration](http://patternlab.io/docs/advanced-config-options.html#node) via `patternlab-config.json`. +* Read more about [configuration](https://patternlab.io/docs/editing-the-configuration-options/) via `patternlab-config.json`. * Read more about the rest of [Public API](./docs), and already implemented for you within [Editions](#editions). @@ -102,9 +103,7 @@ Please read the [contribution guidelines](https://github.com/pattern-lab/pattern ## Core Team -* [@bmuenzenmeyer](https://github.com/bmuenzenmeyer) - Lead Maintainer * [@geoffp](https://github.com/geoffp) - Core Contributor -* [@raphaelokon](https://github.com/raphaelokon) - CLI Contributor * [@tburny](https://github.com/tburny) - Core Contributor ## Community @@ -113,7 +112,7 @@ The Pattern Lab Node team uses [our gitter.im channel, pattern-lab/node](https:/ There is also a dedicated Pattern Lab channel on the [design system slack](http://designsystems.herokuapp.com) run by [@jina](https://twitter.com/jina). -Ask or answer Pattern Lab questions on Stack Overflow: http://stackoverflow.com/questions/tagged/patternlab.io +Ask or answer Pattern Lab questions on Stack Overflow: https://stackoverflow.com/questions/tagged/patternlab.io ## License diff --git a/packages/core/docs/README.md b/packages/core/docs/README.md index 7317083f6..34c17b12b 100644 --- a/packages/core/docs/README.md +++ b/packages/core/docs/README.md @@ -19,13 +19,13 @@ const patternlab = require('@pattern-lab/core')(config); Build thoughtful, pattern-driven user interfaces using atomic design principles. Many of these functions are exposed to users within [Editions](https://github.com/pattern-lab/patternlab-node#editions), but [direct consumption](https://github.com/pattern-lab/patternlab-node#direct-consumption) is also encouraged. -**Kind**: global namespace +**Kind**: global namespace **See** - [patternlab.io](patternlab.io) for more documentation. - [https://github.com/pattern-lab/patternlab-node](https://github.com/pattern-lab/patternlab-node) for code, issues, and releases -**License**: MIT +**License**: MIT * [`patternlab`](#patternlab) : object * _instance_ @@ -33,7 +33,6 @@ Many of these functions are exposed to users within [Editions](https://github.co * [`.build`](#patternlab+build) ⇒ Promise * [`.getDefaultConfig`](#patternlab+getDefaultConfig) ⇒ object * [`.getSupportedTemplateExtensions`](#patternlab+getSupportedTemplateExtensions) ⇒ Array.<string> - * [`.installplugin`](#patternlab+installplugin) ⇒ void * [`.liststarterkits`](#patternlab+liststarterkits) ⇒ Promise * [`.loadstarterkit`](#patternlab+loadstarterkit) ⇒ void * [`.patternsonly`](#patternlab+patternsonly) ⇒ Promise @@ -51,17 +50,17 @@ Many of these functions are exposed to users within [Editions](https://github.co ### `patternlab.version` ⇒ string Returns current version -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: string - current patternlab-node version as defined in `package.json`, as string +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: string - current patternlab-node version as defined in `package.json`, as string ### `patternlab.build` ⇒ Promise Builds patterns, copies assets, and constructs user interface -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: Promise - a promise fulfilled when build is complete -**Emits**: event:PATTERNLAB_BUILD_START, event:PATTERNLAB_BUILD_END -**See**: [all events](./events.md) +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: Promise - a promise fulfilled when build is complete +**Emits**: event:PATTERNLAB_BUILD_START, event:PATTERNLAB_BUILD_END +**See**: [all events](./events.md) | Param | Type | Default | Description | | --- | --- | --- | --- | @@ -75,39 +74,29 @@ Builds patterns, copies assets, and constructs user interface ### `patternlab.getDefaultConfig` ⇒ object Returns the standardized default config used to run Pattern Lab. This method can be called statically or after instantiation. -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: object - Returns the object representation of the `patternlab-config.json` +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: object - Returns the object representation of the `patternlab-config.json` ### `patternlab.getSupportedTemplateExtensions` ⇒ Array.<string> Returns all file extensions supported by installed PatternEngines -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: Array.<string> - all supported file extensions - - -### `patternlab.installplugin` ⇒ void -Installs plugin already available via `node_modules/` - -**Kind**: instance property of [patternlab](#patternlab) - -| Param | Type | Description | -| --- | --- | --- | -| pluginName | string | name of plugin | +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: Array.<string> - all supported file extensions ### `patternlab.liststarterkits` ⇒ Promise Fetches starterkit repositories from pattern-lab github org that contain 'starterkit' in their name -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: Promise - Returns an Array<{name,url}> for the starterkit repos +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: Promise - Returns an Array<{name,url}> for the starterkit repos ### `patternlab.loadstarterkit` ⇒ void Loads starterkit already available via `node_modules/` -**Kind**: instance property of [patternlab](#patternlab) +**Kind**: instance property of [patternlab](#patternlab) | Param | Type | Description | | --- | --- | --- | @@ -119,8 +108,8 @@ Loads starterkit already available via `node_modules/` ### `patternlab.patternsonly` ⇒ Promise Builds patterns only, leaving existing user interface files intact -**Kind**: instance property of [patternlab](#patternlab) -**Returns**: Promise - a promise fulfilled when build is complete +**Kind**: instance property of [patternlab](#patternlab) +**Returns**: Promise - a promise fulfilled when build is complete | Param | Type | Default | Description | | --- | --- | --- | --- | @@ -133,21 +122,21 @@ Builds patterns only, leaving existing user interface files intact ### `patternlab.getDefaultConfig` ⇒ object Static method that returns the standardized default config used to run Pattern Lab. This method can be called statically or after instantiation. -**Kind**: static property of [patternlab](#patternlab) -**Returns**: object - Returns the object representation of the `patternlab-config.json` +**Kind**: static property of [patternlab](#patternlab) +**Returns**: object - Returns the object representation of the `patternlab-config.json` ### `patternlab.getVersion` ⇒ string Static method that returns current version -**Kind**: static property of [patternlab](#patternlab) -**Returns**: string - current @pattern-lab/core version as defined in `package.json` +**Kind**: static property of [patternlab](#patternlab) +**Returns**: string - current @pattern-lab/core version as defined in `package.json` ### `patternlab.server` : object Server module -**Kind**: static property of [patternlab](#patternlab) +**Kind**: static property of [patternlab](#patternlab) * [`.server`](#patternlab.server) : object * [`.serve(options)`](#patternlab.server.serve) ⇒ Promise @@ -159,8 +148,8 @@ Server module #### `server.serve(options)` ⇒ Promise Build patterns, copies assets, and constructs user interface. Watches configured `source/` directories, and serves all output locally -**Kind**: static method of [server](#patternlab.server) -**Returns**: Promise - a promise fulfilled when build is complete +**Kind**: static method of [server](#patternlab.server) +**Returns**: Promise - a promise fulfilled when build is complete | Param | Type | Default | Description | | --- | --- | --- | --- | @@ -174,19 +163,19 @@ Build patterns, copies assets, and constructs user interface. Watches configured #### `server.reload()` ⇒ Promise Reloads any active live-server instances -**Kind**: static method of [server](#patternlab.server) -**Returns**: Promise - a promise fulfilled when operation is complete +**Kind**: static method of [server](#patternlab.server) +**Returns**: Promise - a promise fulfilled when operation is complete #### `server.refreshCSS()` ⇒ Promise Reloads CSS on any active live-server instances -**Kind**: static method of [server](#patternlab.server) -**Returns**: Promise - a promise fulfilled when operation is complete +**Kind**: static method of [server](#patternlab.server) +**Returns**: Promise - a promise fulfilled when operation is complete ### `patternlab.events` : EventEmitter -**Kind**: static property of [patternlab](#patternlab) +**Kind**: static property of [patternlab](#patternlab) **See** - [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) @@ -195,4 +184,4 @@ Reloads CSS on any active live-server instances * * * -[Pattern Lab](http://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) +[Pattern Lab](https://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) diff --git a/packages/core/docs/events.md b/packages/core/docs/events.md index 2df8191d1..62dda5ff2 100644 --- a/packages/core/docs/events.md +++ b/packages/core/docs/events.md @@ -61,7 +61,7 @@ Emitted after patterns are iterated over to gather data about them. Right before #### `EVENTS~PATTERNLAB_BUILD_GLOBAL_DATA_END` -Emitted after global `data.json` and `listitems.json` are read, and the supporting Pattern Lab templates are loaded into memory (header, footer, patternSection, patternSectionSubType, viewall). Right before patterns are iterated over to gather data about them. +Emitted after global `data.json` and `listitems.json` are read, and the supporting Pattern Lab templates are loaded into memory (header, footer, patternSection, patternSectionSubgroup, viewall). Right before patterns are iterated over to gather data about them. **Kind**: inner property of [EVENTS](#exp_module_Events--EVENTS) **Properties** @@ -77,7 +77,7 @@ Emitted after global `data.json` and `listitems.json` are read, and the supporti Emitted before all data is merged prior to a Pattern's render. Global `data.json` is merged with any pattern `.json`. Global `listitems.json` is merged with any pattern `.listitems.json`. **Kind**: inner property of [EVENTS](#exp_module_Events--EVENTS) -**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16) +**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16) **Properties** | Name | Type | Description | @@ -92,7 +92,7 @@ Emitted before all data is merged prior to a Pattern's render. Global `data.json Emitted before a pattern's template, HTML, and encoded HTML files are written to their output location **Kind**: inner property of [EVENTS](#exp_module_Events--EVENTS) -**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16) +**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16) **Properties** | Name | Type | Description | @@ -107,7 +107,7 @@ Emitted before a pattern's template, HTML, and encoded HTML files are written to Emitted after a pattern's template, HTML, and encoded HTML files are written to their output location **Kind**: inner property of [EVENTS](#exp_module_Events--EVENTS) -**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16) +**See**: [Pattern](https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16) **Properties** | Name | Type | Description | @@ -156,4 +156,4 @@ Invoked when a pattern changes. --- -[Pattern Lab](http://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) +[Pattern Lab](https://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) diff --git a/packages/core/package.json b/packages/core/package.json index 38ea422ac..74b3555ed 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,36 +1,39 @@ { "name": "@pattern-lab/core", "description": "Create atomic design systems with Pattern Lab. This is the core API and orchestrator of the ecosystem.", - "version": "3.0.1-alpha.0", + "version": "6.1.0", "main": "./src/index.js", "dependencies": { - "@pattern-lab/engine-mustache": "^2.0.1-alpha.0", - "@pattern-lab/live-server": "^1.3.3-beta.1", - "chalk": "1.1.3", - "chokidar": "1.7.0", + "@pattern-lab/engine-handlebars": "^6.1.0", + "@pattern-lab/engine-mustache": "^6.1.0", + "@pattern-lab/live-server": "^6.1.0", + "chalk": "4.1.0", + "chokidar": "3.5.1", "dive": "0.5.0", - "fs-extra": "5.0.0", - "glob": "7.0.0", - "graphlib": "2.1.1", - "js-beautify": "1.6.3", - "js-yaml": "3.6.1", - "lodash": "4.17.5", - "markdown-it": "6.0.1", - "node-fetch": "1.6.0", - "recursive-copy": "2.0.8", - "update-notifier": "2.2.0" + "fs-extra": "10.0.0", + "glob": "7.1.6", + "graphlib": "2.1.8", + "js-beautify": "1.13.5", + "js-yaml": "4.1.0", + "lodash": "4.17.21", + "markdown-it": "12.3.2", + "node-fetch": "2.6.7", + "recursive-copy": "2.0.13", + "update-notifier": "5.1.0" }, "devDependencies": { - "eslint": "4.18.2", - "eslint-config-prettier": "2.9.0", - "eslint-plugin-prettier": "2.6.0", - "husky": "0.14.3", - "jsdoc-to-markdown": "3.0.0", - "prettier": "1.11.1", - "pretty-quick": "1.2.2", + "@babel/core": "^7.13.14", + "@babel/plugin-proposal-decorators": "^7.13.5", + "@babel/plugin-syntax-jsx": "^7.12.13", + "babel-eslint": "^10.0.2", + "eslint": "^6.1.0", + "eslint-config-prettier": "^6.0.0", + "eslint-plugin-prettier": "^3.1.0", + "jsdoc-to-markdown": "6.0.1", + "prettier": "^2.8.1", "rewire": "2.5.2", - "standard-version": "4.3.0", - "tap": "11.1.1" + "standard-version": "9.1.1", + "tap": "14.11.0" }, "keywords": [ "Pattern Lab", @@ -49,9 +52,6 @@ { "name": "Geoff Pursell" }, - { - "name": "Raphael Okon" - }, { "name": "tburny" } @@ -59,15 +59,16 @@ "license": "MIT", "scripts": { "docs": "node ./scripts/docs.js", - "lint": "eslint src/**/*.js", + "lint": "eslint -c ../../.eslintrc.js src/**/*.js", "pretest": "npm run lint", "release": "standard-version", "test": "tap test/*_tests.js --reporter spec --coverage" }, "engines": { - "node": ">=10.0" + "node": ">=16.20.0" }, "publishConfig": { "access": "public" - } + }, + "gitHead": "80f62be442223e09bafb30d0529cbd768e03f2ac" } diff --git a/packages/core/patternlab-config.json b/packages/core/patternlab-config.json index 80669ea5f..d3022f24b 100644 --- a/packages/core/patternlab-config.json +++ b/packages/core/patternlab-config.json @@ -46,8 +46,8 @@ "views/partials/general-footer.mustache", "patternSection": "views/partials/patternSection.mustache", - "patternSectionSubtype": - "views/partials/patternSectionSubtype.mustache", + "patternSectionSubgroup": + "views/partials/patternSectionSubgroup.mustache", "viewall": "views/viewall.mustache" }, @@ -70,8 +70,13 @@ }, "patternExtension": "mustache", "patternStateCascade": ["inprogress", "inreview", "complete"], - "patternExportDirectory": "./pattern_exports/", + "patternExportAll": false, + "patternExportDirectory": "pattern_exports", "patternExportPatternPartials": [], + "patternExportPreserveDirectoryStructure": true, + "patternExportRaw": false, + "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, @@ -83,13 +88,26 @@ "density": "compact", "layout": "horizontal" }, + "engines": { + "handlebars": { + "package": "@pattern-lab/engine-handlebars", + "fileExtensions": [ + "handlebars", + "hbs" + ], + "extend": "helpers/*.js" + } + }, "uikits": [ { "name": "uikit-workshop", + "package": "@pattern-lab/uikit-workshop", "outputDir": "", "enabled": true, "excludedPatternStates": [], "excludedTags": [] } - ] + ], + "patternWrapClassesEnable": false, + "patternWrapClassesKey": [] } diff --git a/packages/core/scripts/api.handlebars b/packages/core/scripts/api.handlebars index 8959ef5cf..db5192088 100644 --- a/packages/core/scripts/api.handlebars +++ b/packages/core/scripts/api.handlebars @@ -17,4 +17,4 @@ const patternlab = require('@pattern-lab/core')(config); * * * -[Pattern Lab](http://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) +[Pattern Lab](https://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) diff --git a/packages/core/scripts/docs.js b/packages/core/scripts/docs.js index 8b0907aca..92d16092c 100644 --- a/packages/core/scripts/docs.js +++ b/packages/core/scripts/docs.js @@ -18,7 +18,7 @@ doc 'name-format': 'backticks', template: fs.readFileSync('./scripts/api.handlebars', 'utf8'), }) - .then(x => { + .then((x) => { fs.outputFile(path.resolve(process.cwd(), './docs/README.md'), x); }); @@ -29,6 +29,6 @@ doc 'name-format': 'backticks', template: fs.readFileSync('./scripts/events.handlebars', 'utf8'), }) - .then(x => { + .then((x) => { fs.outputFile(path.resolve(process.cwd(), './docs/events.md'), x); }); diff --git a/packages/core/scripts/events.handlebars b/packages/core/scripts/events.handlebars index 667e8c9bf..7dcec0dc8 100644 --- a/packages/core/scripts/events.handlebars +++ b/packages/core/scripts/events.handlebars @@ -16,4 +16,4 @@ Learn more about [Creating Plugins](https://github.com/pattern-lab/patternlab-no * * * -[Pattern Lab](http://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) +[Pattern Lab](https://patternlab.io) Node is [MIT Licensed](https://github.com/pattern-lab/patternlab-node/blob/master/LICENSE) diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 653a9f731..1d46b5788 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -10,14 +10,11 @@ 'use strict'; -const path = require('path'); - const updateNotifier = require('update-notifier'); const packageInfo = require('../package.json'); const events = require('./lib/events'); const pe = require('./lib/pattern_exporter'); -const pm = require('./lib/plugin_manager'); const defaultConfig = require('../patternlab-config.json'); @@ -43,7 +40,7 @@ updateNotifier({ * @static * @return {object} Returns the object representation of the `patternlab-config.json` */ -const getDefaultConfig = function() { +const getDefaultConfig = function () { return defaultConfig; }; @@ -55,11 +52,11 @@ const getDefaultConfig = function() { * @static * @returns {string} current @pattern-lab/core version as defined in `package.json` */ -const getVersion = function() { +const getVersion = function () { return packageInfo.version; }; -const patternlab_module = function(config) { +const patternlab_module = function (config) { const PatternLabClass = require('./lib/patternlab'); const patternlab = new PatternLabClass(config); const server = serverModule(patternlab); @@ -73,10 +70,34 @@ const patternlab_module = function(config) { * @instance * @returns {string} current patternlab-node version as defined in `package.json`, as string */ - version: function() { + version: function () { return patternlab.getVersion(); }, + /** + * Returns the current pattern lab configuration being used + * + * @memberof patternlab + * @name getConfig + * @instance + * @returns {object} the current patternlab-node config (defaults + customizations) + */ + getConfig() { + return config; + }, + + /** + * Returns if Pattern Lab is busy compiling or not + * + * @memberof patternlab + * @name isBusy + * @instance + * @returns {boolean} if pattern lab is currently busy compiling + */ + isBusy: function () { + return patternlab.isBusy; + }, + /** * Builds patterns, copies assets, and constructs user interface * @@ -92,7 +113,7 @@ const patternlab_module = function(config) { * @see {@link ./events.md|all events} * @returns {Promise} a promise fulfilled when build is complete */ - build: function(options) { + build: async function (options) { // process.on('unhandledRejection', (reason, p) => { // console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); // // application specific logging, throwing an error, or other logic here @@ -109,53 +130,51 @@ const patternlab_module = function(config) { } patternlab.isBusy = true; - return buildPatterns(options.cleanPublic, patternlab, options.data).then( - () => { - return new ui_builder().buildFrontend(patternlab).then(() => { - copier() - .copyAndWatch(patternlab.config.paths, patternlab, options) - .then(() => { - patternlab.isBusy = false; - // only wire up this listener and the one inside serve.js - // figure out how to detect if serve was called. we should not assume it was - if ( - patternlab.serverReady //check for server presence - ? this.events.listenerCount( - events.PATTERNLAB_PATTERN_CHANGE - ) === 1 //if the server is started, it has already setup one listener - : !this.events.listenerCount( - events.PATTERNLAB_PATTERN_CHANGE - ) // else, check for the presnce of none - ) { - this.events.on(events.PATTERNLAB_PATTERN_CHANGE, () => { - if (!patternlab.isBusy) { - return this.build(options).then(() => { - patternlab.isBusy = false; - }); - } - return Promise.resolve(); - }); - } + return await buildPatterns( + options.cleanPublic, + patternlab, + options.data + ).then(() => { + return new ui_builder().buildFrontend(patternlab).then(() => { + copier() + .copyAndWatch(patternlab.config.paths, patternlab, options) + .then(() => { + patternlab.isBusy = false; + // only wire up this listener and the one inside serve.js + // figure out how to detect if serve was called. we should not assume it was + if ( + patternlab.serverReady //check for server presence + ? this.events.listenerCount( + events.PATTERNLAB_PATTERN_CHANGE + ) === 1 //if the server is started, it has already setup one listener + : !this.events.listenerCount(events.PATTERNLAB_PATTERN_CHANGE) // else, check for the presnce of none + ) { + this.events.on(events.PATTERNLAB_PATTERN_CHANGE, () => { + if (!patternlab.isBusy) { + return this.build(options).then(() => { + patternlab.isBusy = false; + }); + } + return Promise.resolve(); + }); + } - if ( - !this.events.listenerCount(events.PATTERNLAB_GLOBAL_CHANGE) - ) { - this.events.on(events.PATTERNLAB_GLOBAL_CHANGE, () => { - if (!patternlab.isBusy) { - return this.build( - Object.assign({}, options, { cleanPublic: true }) // rebuild everything - ); - } - return Promise.resolve(); - }); - } - }) - .then(() => { - this.events.emit(events.PATTERNLAB_BUILD_END, patternlab); - }); - }); - } - ); + if (!this.events.listenerCount(events.PATTERNLAB_GLOBAL_CHANGE)) { + this.events.on(events.PATTERNLAB_GLOBAL_CHANGE, () => { + if (!patternlab.isBusy) { + return this.build( + Object.assign({}, options, { cleanPublic: true }) // rebuild everything + ); + } + return Promise.resolve(); + }); + } + }) + .then(() => { + this.events.emit(events.PATTERNLAB_BUILD_END, patternlab); + }); + }); + }); }, /** @@ -166,7 +185,7 @@ const patternlab_module = function(config) { * @instance * @return {object} Returns the object representation of the `patternlab-config.json` */ - getDefaultConfig: function() { + getDefaultConfig: function () { return getDefaultConfig(); }, @@ -178,27 +197,10 @@ const patternlab_module = function(config) { * @instance * @returns {Array} all supported file extensions */ - getSupportedTemplateExtensions: function() { + getSupportedTemplateExtensions: function () { return patternlab.getSupportedTemplateExtensions(); }, - /** - * Installs plugin already available via `node_modules/` - * - * @memberof patternlab - * @name installplugin - * @instance - * @param {string} pluginName name of plugin - * @returns {void} - */ - installplugin: function(pluginName) { - //get the config - const configPath = path.resolve(process.cwd(), 'patternlab-config.json'); - const plugin_manager = new pm(config, configPath); - - plugin_manager.install_plugin(pluginName); - }, - /** * Fetches starterkit repositories from pattern-lab github org that contain 'starterkit' in their name * @@ -207,12 +209,12 @@ const patternlab_module = function(config) { * @instance * @returns {Promise} Returns an Array<{name,url}> for the starterkit repos */ - liststarterkits: function() { + liststarterkits: function () { return patternlab.listStarterkits(); }, /** - * Loads starterkit already available via `node_modules/` + * Loads starterkit already available as a package dependency * * @memberof patternlab * @name loadstarterkit @@ -221,7 +223,7 @@ const patternlab_module = function(config) { * @param {boolean} clean whether or not to delete contents of source/ before load * @returns {void} */ - loadstarterkit: function(starterkitName, clean) { + loadstarterkit: function (starterkitName, clean) { patternlab.loadStarterKit(starterkitName, clean); }, @@ -236,7 +238,7 @@ const patternlab_module = function(config) { * @param {bool} [options.watch=true] whether or not Pattern Lab should watch configured `source/` directories for changes to rebuild * @returns {Promise} a promise fulfilled when build is complete */ - patternsonly: function(options) { + patternsonly: async function (options) { if (patternlab && patternlab.isBusy) { logger.info( 'Pattern Lab is busy building a previous run - returning early.' @@ -244,11 +246,13 @@ const patternlab_module = function(config) { return Promise.resolve(); } patternlab.isBusy = true; - return buildPatterns(options.cleanPublic, patternlab, options.data).then( - () => { - patternlab.isBusy = false; - } - ); + return await buildPatterns( + options.cleanPublic, + patternlab, + options.data + ).then(() => { + patternlab.isBusy = false; + }); }, /** @@ -269,11 +273,11 @@ const patternlab_module = function(config) { * @param {bool} [options.watch=true] whether or not Pattern Lab should watch configured `source/` directories for changes to rebuild * @returns {Promise} a promise fulfilled when build is complete */ - serve: options => { + serve: (options) => { return _api .build(options) .then(() => server.serve()) - .catch(e => + .catch((e) => logger.error(`error inside core index.js server serve: ${e}`) ); }, diff --git a/packages/core/src/lib/addPattern.js b/packages/core/src/lib/addPattern.js index af6886466..0534c5dfd 100644 --- a/packages/core/src/lib/addPattern.js +++ b/packages/core/src/lib/addPattern.js @@ -1,10 +1,8 @@ 'use strict'; -const _ = require('lodash'); - const logger = require('./log'); -module.exports = function(pattern, patternlab) { +module.exports = function (pattern, patternlab) { //add the link to the global object if (!patternlab.data.link) { patternlab.data.link = {}; diff --git a/packages/core/src/lib/annotation_exporter.js b/packages/core/src/lib/annotationExporter.js similarity index 65% rename from packages/core/src/lib/annotation_exporter.js rename to packages/core/src/lib/annotationExporter.js index 8fb22470d..ffd16eb15 100644 --- a/packages/core/src/lib/annotation_exporter.js +++ b/packages/core/src/lib/annotationExporter.js @@ -6,43 +6,47 @@ const _ = require('lodash'); const mp = require('./markdown_parser'); const logger = require('./log'); -const annotations_exporter = function(pl) { +const annotationExporter = function (pl) { const paths = pl.config.paths; - let oldAnnotations; /** * Parses JS annotations. * @returns array of comments that used to be wrapped in raw JS */ - function parseAnnotationsJS() { + function parseAnnotationsJSON() { + const jsonPath = path.resolve(paths.source.annotations, 'annotations.json'); + let annotations; + //attempt to read the file try { - oldAnnotations = fs.readFileSync( - path.resolve(paths.source.annotations, 'annotations.js'), - 'utf8' - ); + if (fs.pathExistsSync(jsonPath)) { + //read the new file + annotations = fs.readFileSync(jsonPath, 'utf8'); + } else { + //read the old file + const jsPath = path.resolve(paths.source.annotations, 'annotations.js'); + + annotations = fs + .readFileSync(jsPath, 'utf8') + .replace(/^\s*var comments ?= ?/, '') + .replace(/};\s*$/, '}'); + + logger.info( + `Please convert ${jsPath} to JSON and rename it annotations.json.` + ); + } } catch (ex) { logger.debug( - `annotations.js file missing from ${ - paths.source.annotations - }. This may be expected if you do not use annotations or are using markdown.` + `annotations.json file missing from ${paths.source.annotations}. This may be expected if you do not use annotations or are using markdown.` ); return []; } - //parse as JSON by removing the old wrapping js syntax. comments and the trailing semi-colon - oldAnnotations = oldAnnotations.replace('var comments = ', ''); - oldAnnotations = oldAnnotations.replace('};', '}'); - try { - const oldAnnotationsJSON = JSON.parse(oldAnnotations); - return oldAnnotationsJSON.comments; + const annotationsJSON = JSON.parse(annotations); + return annotationsJSON.comments; } catch (ex) { - logger.error( - `There was an error parsing JSON for ${ - paths.source.annotations - }annotations.js` - ); + logger.error(`There was an error parsing JSON for ${jsonPath}`); return []; } } @@ -72,7 +76,7 @@ const annotations_exporter = function(pl) { //let annotations = annotations; const markdown_parser = parser; - return function(filePath) { + return function (filePath) { const annotationsMD = fs.readFileSync(path.resolve(filePath), 'utf8'); //take the annotation snippets and split them on our custom delimiter @@ -108,22 +112,22 @@ const annotations_exporter = function(pl) { * @returns array of annotations */ function gatherAnnotations() { - const annotationsJS = parseAnnotationsJS(); + const annotationsJS = parseAnnotationsJSON(); const annotationsMD = parseAnnotationsMD(); return _.unionBy(annotationsJS, annotationsMD, 'el'); } return { - gather: function() { + gather: function () { return gatherAnnotations(); }, - gatherJS: function() { - return parseAnnotationsJS(); + gatherJSON: function () { + return parseAnnotationsJSON(); }, - gatherMD: function() { + gatherMD: function () { return parseAnnotationsMD(); }, }; }; -module.exports = annotations_exporter; +module.exports = annotationExporter; diff --git a/packages/core/src/lib/buildFooter.js b/packages/core/src/lib/buildFooter.js index 5a3eb6217..c70cfe249 100644 --- a/packages/core/src/lib/buildFooter.js +++ b/packages/core/src/lib/buildFooter.js @@ -10,10 +10,10 @@ let render = require('./render'); //eslint-disable-line prefer-const /** * Builds footer HTML from the general footer and user-defined footer * @param patternlab - global data store - * @param patternPartial - the partial key to build this for, either viewall-patternPartial or a viewall-patternType-all + * @param patternPartial - the partial key to build this for, either viewall-patternPartial or a viewall-patternGroup-all * @returns A promise which resolves with the HTML */ -module.exports = function(patternlab, patternPartial, uikit) { +module.exports = function (patternlab, patternPartial, uikit) { //first render the general footer return render(Pattern.createEmpty({ extendedTemplate: uikit.footer }), { patternData: JSON.stringify({ @@ -21,7 +21,7 @@ module.exports = function(patternlab, patternPartial, uikit) { }), cacheBuster: patternlab.cacheBuster, }) - .then(footerPartial => { + .then((footerPartial) => { let allFooterData; try { allFooterData = jsonCopy( @@ -29,14 +29,14 @@ module.exports = function(patternlab, patternPartial, uikit) { 'config.paths.source.data plus patterns data' ); } catch (err) { - logger.warning('There was an error parsing JSON for patternlab.data'); - logger.warning(err); + logger.error('There was an error parsing JSON for patternlab.data'); + logger.error(err); } allFooterData.patternLabFoot = footerPartial; return render(patternlab.userFoot, allFooterData); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error building buildFooterHTML'); }); diff --git a/packages/core/src/lib/buildListItems.js b/packages/core/src/lib/buildListItems.js index af9ba783d..7eb214f12 100644 --- a/packages/core/src/lib/buildListItems.js +++ b/packages/core/src/lib/buildListItems.js @@ -26,7 +26,7 @@ const items = [ 'twenty', ]; -module.exports = function(container) { +module.exports = function (container) { //combine all list items into one structure const list = []; for (const item in container.listitems) { diff --git a/packages/core/src/lib/buildPatterns.js b/packages/core/src/lib/buildPatterns.js index 51dcea8b3..476a373c6 100644 --- a/packages/core/src/lib/buildPatterns.js +++ b/packages/core/src/lib/buildPatterns.js @@ -14,6 +14,8 @@ const CompileState = require('./object_factory').CompileState; const processMetaPattern = require('./processMetaPattern'); const pe = require('./pattern_exporter'); const lh = require('./lineage_hunter'); +const pm = require('./plugin_manager'); +const pluginManager = new pm(); const markModifiedPatterns = require('./markModifiedPatterns'); const parseAllLinks = require('./parseAllLinks'); const render = require('./render'); @@ -24,8 +26,12 @@ let pattern_exporter = new pe(); // eslint-disable-line const lineage_hunter = new lh(); -module.exports = (deletePatternDir, patternlab, additionalData) => { - patternlab.events.emit(events.PATTERNLAB_BUILD_START, patternlab); +module.exports = async (deletePatternDir, patternlab, additionalData) => { + await pluginManager.raiseEvent( + patternlab, + events.PATTERNLAB_BUILD_START, + patternlab + ); const paths = patternlab.config.paths; @@ -34,7 +40,7 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { // const graph = (patternlab.graph = loadPatternGraph( patternlab, - deletePatternDir + patternlab.config.cleanPublic )); const graphNeedsUpgrade = !PatternGraph.checkVersion(graph); if (graphNeedsUpgrade) { @@ -49,7 +55,9 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { // Flags patternlab.incrementalBuildsEnabled = !( - deletePatternDir || graphNeedsUpgrade + patternlab.config.cleanPublic || + graphNeedsUpgrade || + deletePatternDir ); // @@ -63,8 +71,9 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { return patternlab .processAllPatternsIterative(paths.source.patterns) - .then(() => { - patternlab.events.emit( + .then(async () => { + await pluginManager.raiseEvent( + patternlab, events.PATTERNLAB_PATTERN_ITERATION_END, patternlab ); @@ -85,12 +94,12 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { //perhaps we can check for a convention like [uikitname]_00-head.mustache, and if found, add them to patternlab.uikits[uikitname].userFoot //then, if present, use those during compose() const headPatternPromise = processMetaPattern( - `_00-head.${patternlab.config.patternExtension}`, + `_head.${patternlab.config.patternExtension}`, 'userHead', patternlab ); const footPatternPromise = processMetaPattern( - `_01-foot.${patternlab.config.patternExtension}`, + `_foot.${patternlab.config.patternExtension}`, 'userFoot', patternlab ); @@ -110,7 +119,7 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { cacheBuster: patternlab.cacheBuster, } ) - .then(results => { + .then((results) => { patternlab.data.patternLabHead = results; // If deletePatternDir == true or graph needs to be updated @@ -124,7 +133,7 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { if (patternlab.incrementalBuildsEnabled) { // When the graph was loaded from file, some patterns might have been moved/deleted between runs // so the graph data become out of sync - patternlab.graph.sync().forEach(n => { + patternlab.graph.sync().forEach((n) => { logger.info('[Deleted/Moved] ' + n); }); @@ -140,11 +149,11 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { } } //render all patterns last, so lineageR works - const allPatternsPromise = patternsToBuild.map(pattern => - compose(pattern, patternlab) + const allPatternsPromise = patternsToBuild.map( + async (pattern) => await compose(pattern, patternlab) ); //copy non-pattern files like JavaScript - const allJS = patternsToBuild.map(pattern => { + const allJS = patternsToBuild.map((pattern) => { const { name, patternPartial, subdir } = pattern; const { source: { patterns: sourceDir }, @@ -152,7 +161,7 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { } = patternlab.config.paths; const src = path.join(sourceDir, subdir); const dest = path.join(publicDir, name); - return map(patternlab.uikits, uikit => { + return map(patternlab.uikits, (uikit) => { return copy( src, path.resolve(process.cwd(), uikit.outputDir, dest), @@ -190,27 +199,27 @@ module.exports = (deletePatternDir, patternlab, additionalData) => { //export patterns if necessary pattern_exporter.export_patterns(patternlab); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error rendering patterns'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error rendering pattern lab header'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error processing meta patterns'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error processing patterns recursively'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error in buildPatterns()'); }); diff --git a/packages/core/src/lib/changes_hunter.js b/packages/core/src/lib/changes_hunter.js index 038be8b41..ee4a4d52c 100644 --- a/packages/core/src/lib/changes_hunter.js +++ b/packages/core/src/lib/changes_hunter.js @@ -12,7 +12,7 @@ let fs = require('fs-extra'); //eslint-disable-line prefer-const * For detecting changed patterns. * @constructor */ -const ChangesHunter = function() {}; +const ChangesHunter = function () {}; ChangesHunter.prototype = { /** @@ -25,7 +25,7 @@ ChangesHunter.prototype = { * * @see {@link CompileState} */ - checkBuildState: function(pattern, patternlab) { + checkBuildState: function (pattern, patternlab) { //write the compiled template to the public patterns directory const renderedTemplatePath = patternlab.config.paths.public.patterns + @@ -40,12 +40,12 @@ ChangesHunter.prototype = { pattern.compileState = CompileState.NEEDS_REBUILD; } - _.each(patternlab.uikits, uikit => { + _.each(patternlab.uikits, (uikit) => { try { // renderedTemplatePath required to display a single element // Markup only is required for "View All" pages. It will get loaded later on. // If any of these is missing, mark pattern for recompile - [renderedTemplatePath, markupOnlyPath].forEach(renderedFile => { + [renderedTemplatePath, markupOnlyPath].forEach((renderedFile) => { // Prevent error message if file does not exist fs.accessSync( path.join(process.cwd(), uikit.outputDir, renderedFile), @@ -94,7 +94,7 @@ ChangesHunter.prototype = { * @param {Pattern} currentPattern * @param {string} file */ - checkLastModified: function(currentPattern, file) { + checkLastModified: function (currentPattern, file) { if (file && fs.pathExistsSync(file)) { try { const stat = fs.statSync(file); @@ -110,7 +110,7 @@ ChangesHunter.prototype = { } }, - needsRebuild: function(lastModified, p) { + needsRebuild: function (lastModified, p) { if (p.compileState !== CompileState.CLEAN || !p.lastModified) { return true; } diff --git a/packages/core/src/lib/cleanBuildDirectory.js b/packages/core/src/lib/cleanBuildDirectory.js index 11d78c01e..0cfc300e0 100644 --- a/packages/core/src/lib/cleanBuildDirectory.js +++ b/packages/core/src/lib/cleanBuildDirectory.js @@ -15,12 +15,12 @@ module.exports = (incrementalBuildsEnabled, patternlab) => { return Promise.resolve(); } else { return Promise.all( - _.map(patternlab.uikits, uikit => { + _.map(patternlab.uikits, (uikit) => { return fs.emptyDir( path.join(process.cwd(), uikit.outputDir, paths.public.patterns) ); }) - ).catch(reason => { + ).catch((reason) => { logger.error(reason); }); } diff --git a/packages/core/src/lib/compose.js b/packages/core/src/lib/compose.js index 86b2f8f91..c3494e123 100644 --- a/packages/core/src/lib/compose.js +++ b/packages/core/src/lib/compose.js @@ -8,11 +8,15 @@ const logger = require('./log'); const parseLink = require('./parseLink'); const render = require('./render'); const uikitExcludePattern = require('./uikitExcludePattern'); +const pm = require('./plugin_manager'); +const dataMerger = require('./dataMerger'); +const patternWrapClassesChangePatternTemplate = require('./patternWrapClasses'); +const pluginManager = new pm(); const Pattern = require('./object_factory').Pattern; const CompileState = require('./object_factory').CompileState; -module.exports = function(pattern, patternlab) { +module.exports = async function (pattern, patternlab) { // Pattern does not need to be built and recompiled more than once if (!pattern.isPattern || pattern.compileState === CompileState.CLEAN) { return Promise.resolve(false); @@ -30,14 +34,15 @@ module.exports = function(pattern, patternlab) { pattern.patternLineageEExists = pattern.patternLineageExists || pattern.patternLineageRExists; - patternlab.events.emit( + await pluginManager.raiseEvent( + patternlab, events.PATTERNLAB_PATTERN_BEFORE_DATA_MERGE, patternlab, pattern ); return Promise.all( - _.map(patternlab.uikits, uikit => { + _.map(patternlab.uikits, (uikit) => { // exclude pattern from uikit rendering if (uikitExcludePattern(pattern, uikit)) { return Promise.resolve(); @@ -53,8 +58,14 @@ module.exports = function(pattern, patternlab) { 'listitems.json + any pattern listitems.json' ); - allData = _.merge({}, patternlab.data, pattern.jsonFileData); - allData = _.merge({}, allData, allListItems); + allData = dataMerger( + patternlab.data, + pattern.jsonFileData, + patternlab.config + ); + // _.merge({}, patternlab.data, pattern.jsonFileData); + allData = dataMerger(allData, allListItems, patternlab.config); + // _.merge({}, allData, allListItems); allData.cacheBuster = patternlab.cacheBuster; allData.patternPartial = pattern.patternPartial; @@ -113,13 +124,13 @@ module.exports = function(pattern, patternlab) { pattern.patternLineageExists || pattern.patternLineageRExists, patternDesc: pattern.patternDescExists ? pattern.patternDesc : '', patternBreadcrumb: - pattern.patternGroup === pattern.patternSubGroup + pattern.patternGroup === pattern.patternSubgroup ? { - patternType: pattern.patternGroup, + patternGroup: pattern.patternGroup, } : { - patternType: pattern.patternGroup, - patternSubtype: pattern.patternSubGroup, + patternGroup: pattern.patternGroup, + patternSubgroup: pattern.patternSubgroup, }, patternExtension: pattern.fileExtension.substr(1), //remove the dot because styleguide asset default adds it for us patternName: pattern.patternName, @@ -144,11 +155,12 @@ module.exports = function(pattern, patternlab) { patternPartialPromise, footerPartialPromise, ]) - .then(intermediateResults => { + .then((intermediateResults) => { // retrieve results of promises const headHTML = intermediateResults[0]; //headPromise pattern.patternPartialCode = intermediateResults[1]; //patternPartialPromise const footerPartial = intermediateResults[2]; //footerPartialPromise + patternWrapClassesChangePatternTemplate(patternlab, pattern); //finish up our footer data let allFooterData; @@ -158,46 +170,50 @@ module.exports = function(pattern, patternlab) { 'config.paths.source.data global data' ); } catch (err) { - logger.info( + logger.error( 'There was an error parsing JSON for ' + pattern.relPath ); - logger.info(err); + logger.error(err); } allFooterData = _.merge(allFooterData, pattern.jsonFileData); + allFooterData.cacheBuster = patternlab.cacheBuster; allFooterData.patternLabFoot = footerPartial; - return render(patternlab.userFoot, allFooterData).then(footerHTML => { - /////////////// - // WRITE FILES - /////////////// - - patternlab.events.emit( - events.PATTERNLAB_PATTERN_WRITE_BEGIN, - patternlab, - pattern - ); - - //write the compiled template to the public patterns directory - patternlab.writePatternFiles( - headHTML, - pattern, - footerHTML, - uikit.outputDir - ); - - patternlab.events.emit( - events.PATTERNLAB_PATTERN_WRITE_END, - patternlab, - pattern - ); - - // Allows serializing the compile state - patternlab.graph.node(pattern).compileState = pattern.compileState = - CompileState.CLEAN; - logger.info('Built pattern: ' + pattern.patternPartial); - }); + return render(patternlab.userFoot, allFooterData).then( + async (footerHTML) => { + /////////////// + // WRITE FILES + /////////////// + await pluginManager.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_WRITE_BEGIN, + patternlab, + pattern + ); + + //write the compiled template to the public patterns directory + patternlab.writePatternFiles( + headHTML, + pattern, + footerHTML, + uikit.outputDir + ); + + await pluginManager.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_WRITE_END, + patternlab, + pattern + ); + + // Allows serializing the compile state + patternlab.graph.node(pattern).compileState = + pattern.compileState = CompileState.CLEAN; + logger.info('Built pattern: ' + pattern.patternPartial); + } + ); }) - .catch(reason => { + .catch((reason) => { console.log(reason); }); }) diff --git a/packages/core/src/lib/copier.js b/packages/core/src/lib/copier.js index 441ffdf5b..ba1c22788 100644 --- a/packages/core/src/lib/copier.js +++ b/packages/core/src/lib/copier.js @@ -8,7 +8,7 @@ const watchAssets = require('./watchAssets'); const watchPatternLabFiles = require('./watchPatternLabFiles'); const copier = () => { - const transform_paths = directories => { + const transform_paths = (directories) => { //create array with all source keys minus our blacklist const dirs = {}; const blackList = [ @@ -55,6 +55,14 @@ const copier = () => { debug: patternlab.config.logLevel === 'debug', }; + // Adding assets to filter for in case of transformedAssetTypes defined; adapted regex from https://stackoverflow.com/a/6745455 + if (patternlab.config.transformedAssetTypes) { + copyOptions.filter = new RegExp( + `.*(? { } else { //just copy copyPromises.push( - _.map(patternlab.uikits, uikit => { + _.map(patternlab.uikits, (uikit) => { copyFile( dir.source, path.join(basePath, uikit.outputDir, dir.public), @@ -79,7 +87,7 @@ const copier = () => { // copy the styleguide copyPromises.push( - _.map(patternlab.uikits, uikit => { + _.map(patternlab.uikits, (uikit) => { copyFile( path.join(uikit.modulePath, assetDirectories.source.styleguide), path.join(basePath, uikit.outputDir, assetDirectories.public.root), @@ -90,9 +98,9 @@ const copier = () => { // copy the favicon copyPromises.push( - _.map(patternlab.uikits, uikit => { + _.map(patternlab.uikits, (uikit) => { copyFile( - `${assetDirectories.source.root}/favicon.ico`, + `${assetDirectories.source.root}favicon.ico`, path.join( basePath, uikit.outputDir, @@ -116,7 +124,7 @@ const copier = () => { copyAndWatch: (assetDirectories, patternlab, options) => { return copyAndWatch(assetDirectories, patternlab, options); }, - transformConfigPaths: paths => { + transformConfigPaths: (paths) => { return transform_paths(paths); }, }; diff --git a/packages/core/src/lib/copyFile.js b/packages/core/src/lib/copyFile.js index ce1bc056a..c8202afe1 100644 --- a/packages/core/src/lib/copyFile.js +++ b/packages/core/src/lib/copyFile.js @@ -7,10 +7,10 @@ let copy = require('recursive-copy'); // eslint-disable-line prefer-const const copyFile = (p, dest, options) => { return copy(p, dest, options) - .on(copy.events.ERROR, function(error, copyOperation) { + .on(copy.events.ERROR, function (error, copyOperation) { logger.error('Unable to copy ' + copyOperation.dest); }) - .on(copy.events.COPY_FILE_ERROR, error => { + .on(copy.events.COPY_FILE_ERROR, (error) => { logger.error(error); }) .on(copy.events.COPY_FILE_COMPLETE, () => { diff --git a/packages/core/src/lib/dataMerger.js b/packages/core/src/lib/dataMerger.js new file mode 100644 index 000000000..08544c320 --- /dev/null +++ b/packages/core/src/lib/dataMerger.js @@ -0,0 +1,36 @@ +const _ = require('lodash'); + +/** + * Merges two objects depending on the configuration and will either merge + * arrays and only replaces items on the index or replace the entire + * collection of the different parameters + * + * @param {*} dataObject the object that contains the main data + * @param {*} dataToMergeWithObject the object that should be merged with the original data + * @param {*} patternlabConfig the patternlab configuration object + */ +module.exports = function ( + dataObject, + dataToMergeWithObject, + patternlabConfig +) { + return _.mergeWith( + {}, + dataObject, + dataToMergeWithObject, + (objValue, srcValue) => { + if ( + _.isArray(objValue) && + // If the parameter is not available after updating pattern lab but + // not the patternlab-config it should not override arrays. + patternlabConfig.hasOwnProperty('patternMergeVariantArrays') && + !patternlabConfig.patternMergeVariantArrays + ) { + return srcValue; + } + // Lodash will only check for "undefined" and eslint needs a consistent + // return so do not remove + return undefined; + } + ); +}; diff --git a/packages/core/src/lib/data_loader.js b/packages/core/src/lib/data_loader.js index f1ac874c2..573edd04e 100644 --- a/packages/core/src/lib/data_loader.js +++ b/packages/core/src/lib/data_loader.js @@ -21,9 +21,7 @@ function loadFile(dataFilePath, fsDep) { if (dataFile && fsDep.existsSync(path.resolve(dataFile))) { try { - return yaml.safeLoad( - fsDep.readFileSync(path.resolve(dataFile), 'utf8') - ); + return yaml.load(fsDep.readFileSync(path.resolve(dataFile), 'utf8')); } catch (err) { throw new Error(`Error loading file: ${dataFile} - ${err.message}`); } @@ -53,9 +51,9 @@ function loadDataFromFolder(dataFilesPath, excludeFileNames, fsDep) { const dataFiles = glob.sync(dataFilesFullPath, globOptions); let mergeObject = {}; - dataFiles.forEach(function(filePath) { + dataFiles.forEach(function (filePath) { try { - const jsonData = yaml.safeLoad( + const jsonData = yaml.load( fsDep.readFileSync(path.resolve(filePath), 'utf8') ); mergeObject = _.merge(mergeObject, jsonData); diff --git a/packages/core/src/lib/decompose.js b/packages/core/src/lib/decompose.js index e541708b5..4c35cd694 100644 --- a/packages/core/src/lib/decompose.js +++ b/packages/core/src/lib/decompose.js @@ -16,7 +16,7 @@ const list_item_hunter = new lih(); * @param patternlab - global data store * @param ignoreLineage - whether or not to hunt for lineage for this pattern */ -module.exports = function(pattern, patternlab, ignoreLineage) { +module.exports = function (pattern, patternlab, ignoreLineage) { //set the extendedTemplate to operate on later if we find partials to replace if (!pattern.extendedTemplate) { pattern.extendedTemplate = pattern.template; @@ -51,7 +51,7 @@ module.exports = function(pattern, patternlab, ignoreLineage) { expandPartialPromise, lineagePromise, addPromise, - ]).catch(reason => { + ]).catch((reason) => { logger.error(reason); }); }; diff --git a/packages/core/src/lib/events.js b/packages/core/src/lib/events.js index b1653b3c8..9eda9005f 100644 --- a/packages/core/src/lib/events.js +++ b/packages/core/src/lib/events.js @@ -30,7 +30,7 @@ const EVENTS = Object.freeze({ PATTERNLAB_PATTERN_ITERATION_END: 'patternlab-pattern-iteration-end', /** - * @desc Emitted after global `data.json` and `listitems.json` are read, and the supporting Pattern Lab templates are loaded into memory (header, footer, patternSection, patternSectionSubType, viewall). Right before patterns are iterated over to gather data about them. + * @desc Emitted after global `data.json` and `listitems.json` are read, and the supporting Pattern Lab templates are loaded into memory (header, footer, patternSection, patternSectionSubgroup, viewall). Right before patterns are iterated over to gather data about them. * @property {object} patternlab - global data store */ PATTERNLAB_BUILD_GLOBAL_DATA_END: 'patternlab-build-global-data-end', @@ -39,7 +39,7 @@ const EVENTS = Object.freeze({ * @desc Emitted before all data is merged prior to a Pattern's render. Global `data.json` is merged with any pattern `.json`. Global `listitems.json` is merged with any pattern `.listitems.json`. * @property {object} patternlab - global data store * @property {Pattern} pattern - current pattern - * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16|Pattern} + * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16|Pattern} */ PATTERNLAB_PATTERN_BEFORE_DATA_MERGE: 'patternlab-pattern-before-data-merge', @@ -47,7 +47,7 @@ const EVENTS = Object.freeze({ * @desc Emitted before a pattern's template, HTML, and encoded HTML files are written to their output location * @property {object} patternlab - global data store * @property {Pattern} pattern - current pattern - * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16|Pattern} + * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16|Pattern} */ PATTERNLAB_PATTERN_WRITE_BEGIN: 'patternlab-pattern-write-begin', @@ -55,7 +55,7 @@ const EVENTS = Object.freeze({ * @desc Emitted after a pattern's template, HTML, and encoded HTML files are written to their output location * @property {object} patternlab - global data store * @property {Pattern} pattern - current pattern - * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/src/lib/object_factory.js#L16|Pattern} + * @see {@link https://github.com/pattern-lab/patternlab-node/blob/master/packages/core/src/lib/object_factory.js#L16|Pattern} */ PATTERNLAB_PATTERN_WRITE_END: 'patternlab-pattern-write-end', diff --git a/packages/core/src/lib/expandPartials.js b/packages/core/src/lib/expandPartials.js index a42df2cbc..e4976fe8b 100644 --- a/packages/core/src/lib/expandPartials.js +++ b/packages/core/src/lib/expandPartials.js @@ -1,15 +1,11 @@ 'use strict'; const logger = require('./log'); -const ph = require('./parameter_hunter'); -const smh = require('./style_modifier_hunter'); const jsonCopy = require('./json_copy'); const getPartial = require('./get'); -const parameter_hunter = new ph(); -const style_modifier_hunter = new smh(); - -module.exports = function(currentPattern, patternlab) { +// TODO: remove when removing mustache +module.exports = function (currentPattern, patternlab) { const processRecursive = require('./processRecursive'); //find how many partials there may be for the given pattern @@ -20,75 +16,51 @@ module.exports = function(currentPattern, patternlab) { // results if ( currentPattern.engine.expandPartials && - (foundPatternPartials !== null && foundPatternPartials.length > 0) + foundPatternPartials !== null && + foundPatternPartials.length > 0 ) { logger.debug(`found partials for ${currentPattern.patternPartial}`); - // determine if the template contains any pattern parameters. if so they - // must be immediately consumed - return parameter_hunter - .find_parameters(currentPattern, patternlab) - .then(() => { - //do something with the regular old partials - foundPatternPartials.forEach(foundPartial => { - const partial = currentPattern.findPartial(foundPartial); - const partialPattern = getPartial(partial, patternlab); - - //recurse through nested partials to fill out this extended template. - return processRecursive(partialPattern.relPath, patternlab) - .then(() => { - //eslint-disable-line no-loop-func + //do something with the regular old partials + foundPatternPartials.forEach((foundPartial) => { + const partial = currentPattern.findPartial(foundPartial); + const partialPattern = getPartial(partial, patternlab); - //complete assembly of extended template - //create a copy of the partial so as to not pollute it after the getPartial call. - const cleanPartialPattern = jsonCopy( - partialPattern, - `partial pattern ${partial}` - ); + //recurse through nested partials to fill out this extended template. + return processRecursive(partialPattern.relPath, patternlab) + .then(() => { + //eslint-disable-line no-loop-func - //if partial has style modifier data, replace the styleModifier value - if ( - currentPattern.stylePartials && - currentPattern.stylePartials.length > 0 - ) { - style_modifier_hunter.consume_style_modifier( - cleanPartialPattern, - foundPartial, - patternlab - ); - } + //complete assembly of extended template + //create a copy of the partial so as to not pollute it after the getPartial call. + const cleanPartialPattern = jsonCopy( + partialPattern, + `partial pattern ${partial}` + ); - //this is what we came here for - logger.debug( - `within ${ - currentPattern.patternPartial - }, replacing extendedTemplate partial ${foundPartial} with ${ - cleanPartialPattern.patternPartial - }'s extendedTemplate` - ); + //this is what we came here for + logger.debug( + `within ${currentPattern.patternPartial}, replacing extendedTemplate partial ${foundPartial} with ${cleanPartialPattern.patternPartial}'s extendedTemplate` + ); - currentPattern.extendedTemplate = currentPattern.extendedTemplate.replace( - foundPartial, - cleanPartialPattern.extendedTemplate - ); + currentPattern.extendedTemplate = + currentPattern.extendedTemplate.replace( + foundPartial, + cleanPartialPattern.extendedTemplate + ); - // update the extendedTemplate in the partials object in case this - // pattern is consumed later - patternlab.partials[currentPattern.patternPartial] = - currentPattern.extendedTemplate; + // update the extendedTemplate in the partials object in case this + // pattern is consumed later + patternlab.partials[currentPattern.patternPartial] = + currentPattern.extendedTemplate; - return Promise.resolve(); - }) - .catch(reason => { - console.log(reason); - logger.error(reason); - }); + return Promise.resolve(); + }) + .catch((reason) => { + console.log(reason); + logger.error(reason); }); - }) - .catch(reason => { - console.log(reason); - logger.error(reason); - }); + }); } return Promise.resolve(); }; diff --git a/packages/core/src/lib/exportData.js b/packages/core/src/lib/exportData.js index 51b166a08..aeef0a845 100644 --- a/packages/core/src/lib/exportData.js +++ b/packages/core/src/lib/exportData.js @@ -1,10 +1,9 @@ 'use strict'; -const eol = require('os').EOL; const path = require('path'); -const _ = require('lodash'); +const eol = require('os').EOL; -const ae = require('./annotation_exporter'); +const ae = require('./annotationExporter'); let fs = require('fs-extra'); //eslint-disable-line prefer-const @@ -12,8 +11,8 @@ let fs = require('fs-extra'); //eslint-disable-line prefer-const * Write out our pattern information for use by the front end * @param patternlab - global data store */ -module.exports = function(patternlab) { - const annotation_exporter = new ae(patternlab); +module.exports = function (patternlab, uikit) { + const annotationExporter = new ae(patternlab); const paths = patternlab.config.paths; @@ -32,8 +31,8 @@ module.exports = function(patternlab) { //navItems output += - 'var navItems = {"patternTypes": ' + - JSON.stringify(patternlab.patternTypes) + + 'var navItems = {"patternGroups": ' + + JSON.stringify(patternlab.patternGroups) + ', "ishControlsHide": ' + JSON.stringify(patternlab.config.ishControlsHide) + '};' + @@ -68,34 +67,41 @@ module.exports = function(patternlab) { eol; //annotations - const annotationsJSON = annotation_exporter.gather(); + const annotationsJSON = annotationExporter.gather(); const annotations = 'var comments = { "comments" : ' + JSON.stringify(annotationsJSON) + '};'; - _.each(patternlab.uikits, uikit => { - fs.outputFileSync( - path.resolve( - path.join( - process.cwd(), - uikit.outputDir, - paths.public.annotations, - 'annotations.js' - ) - ), - annotations - ); - }); + fs.outputFileSync( + path.resolve( + path.join( + process.cwd(), + uikit.outputDir, + paths.public.annotations, + 'annotations.js' + ) + ), + annotations + ); + + // add module.export to the Nodejs-specific file generated. + const exportedOutput = + output + + 'module.exports = { config, ishControls, navItems, patternPaths, viewAllPaths, plugins, defaultShowPatternInfo, defaultPattern };'; //write all output to patternlab-data - - _.each(patternlab.uikits, uikit => { - fs.outputFileSync( - path.resolve( - path.join(process.cwd(), uikit.outputDir, paths.public.data), - 'patternlab-data.js' - ), - output - ); - }); + fs.outputFileSync( + path.resolve( + path.join(process.cwd(), uikit.outputDir, paths.public.data), + 'patternlab-data.js' + ), + output + ); + fs.outputFileSync( + path.resolve( + path.join(process.cwd(), uikit.outputDir, paths.public.data), + 'patternlab-data.cjs.js' + ), + exportedOutput + ); return output; }; diff --git a/packages/core/src/lib/findModules.js b/packages/core/src/lib/findModules.js index 246612ec8..f54f80d4f 100644 --- a/packages/core/src/lib/findModules.js +++ b/packages/core/src/lib/findModules.js @@ -6,7 +6,7 @@ const isScopedPackage = require('./isScopedPackage'); let fs = require('fs-extra'); // eslint-disable-line -const isDir = fPath => { +const isDir = (fPath) => { const stats = fs.lstatSync(fPath); return stats.isDirectory() || stats.isSymbolicLink(); }; @@ -27,7 +27,7 @@ module.exports = (dir, filter) => { */ const dirList = fs .readdirSync(fPath) - .filter(p => isDir(path.join(fPath, p))); + .filter((p) => isDir(path.join(fPath, p))); /** * @name m @@ -35,7 +35,7 @@ module.exports = (dir, filter) => { * @type {Array} */ const m = foundModules.concat( - dirList.filter(filter).map(mod => { + dirList.filter(filter).map((mod) => { return { name: filter(mod), modulePath: path.join(fPath, mod), @@ -52,7 +52,7 @@ module.exports = (dir, filter) => { ...m, ...dirList .filter(isScopedPackage) // 2 - .map(scope => findModules(path.join(fPath, scope), m)) // 3 + .map((scope) => findModules(path.join(fPath, scope), m)) // 3 ); }; diff --git a/packages/core/src/lib/get.js b/packages/core/src/lib/get.js index 2feccc135..2f180a77f 100644 --- a/packages/core/src/lib/get.js +++ b/packages/core/src/lib/get.js @@ -2,7 +2,7 @@ const logger = require('./log'); -module.exports = function(partialName, patternlab, reportWarning = true) { +module.exports = function (partialName, patternlab, reportWarning = true) { //look for exact partial matches for (let i = 0; i < patternlab.patterns.length; i++) { if (patternlab.patterns[i].patternPartial === partialName) { @@ -35,7 +35,7 @@ module.exports = function(partialName, patternlab, reportWarning = true) { } if (reportWarning) { logger.warning( - `Could not find pattern referenced with partial syntax ${partialName}. + `Could not find pattern referenced with partial syntax "${partialName}" from "${patternlab.config.paths.source.patterns}". This can occur when a pattern was renamed, moved, or no longer exists but it still referenced within a different template or within data as a link.` ); } diff --git a/packages/core/src/lib/isScopedPackage.js b/packages/core/src/lib/isScopedPackage.js index cffd1d811..53b607ad7 100644 --- a/packages/core/src/lib/isScopedPackage.js +++ b/packages/core/src/lib/isScopedPackage.js @@ -10,7 +10,7 @@ const scopeMatch = /^@(.*)$/; * @param {string} filePath - The pathname to check * @return {Boolean} - Returns a bool when found, false othersie */ -module.exports = filePath => { +module.exports = (filePath) => { const baseName = path.basename(filePath); return scopeMatch.test(baseName); }; diff --git a/packages/core/src/lib/lineage_hunter.js b/packages/core/src/lib/lineage_hunter.js index 0b844fcc9..3a90a0f65 100644 --- a/packages/core/src/lib/lineage_hunter.js +++ b/packages/core/src/lib/lineage_hunter.js @@ -2,7 +2,7 @@ const getPartial = require('./get'); const logger = require('./log'); -const lineage_hunter = function() { +const lineage_hunter = function () { function findlineage(pattern, patternlab) { // As we are adding edges from pattern to ancestor patterns, ensure it is known to the graph patternlab.graph.add(pattern); @@ -10,7 +10,7 @@ const lineage_hunter = function() { //find the {{> template-name }} within patterns const matches = pattern.findPartials(); if (matches !== null) { - matches.forEach(function(match) { + matches.forEach(function (match) { //get the ancestorPattern const ancestorPattern = getPartial( pattern.findPartial(match), @@ -131,13 +131,7 @@ const lineage_hunter = function() { ? '<>' : lineageRPattern.patternState; logger.info( - `Found a lower common denominator pattern state: ${ - pattern.patternState - } on ${ - pattern.patternPartial - }. Setting reverse lineage pattern ${ - lineageRPattern.patternPartial - } from ${oldState}` + `Found a lower common denominator pattern state: ${pattern.patternState} on ${pattern.patternPartial}. Setting reverse lineage pattern ${lineageRPattern.patternPartial} from ${oldState}` ); lineageRPattern.patternState = pattern.patternState; @@ -164,10 +158,10 @@ const lineage_hunter = function() { } return { - find_lineage: function(pattern, patternlab) { + find_lineage: function (pattern, patternlab) { findlineage(pattern, patternlab); }, - cascade_pattern_states: function(patternlab) { + cascade_pattern_states: function (patternlab) { cascadePatternStates(patternlab); }, }; diff --git a/packages/core/src/lib/list_item_hunter.js b/packages/core/src/lib/list_item_hunter.js index 167c8e55c..7d6346161 100644 --- a/packages/core/src/lib/list_item_hunter.js +++ b/packages/core/src/lib/list_item_hunter.js @@ -1,6 +1,6 @@ 'use strict'; -const list_item_hunter = function() { +const list_item_hunter = function () { const logger = require('./log'); function processListItemPartials(pattern) { @@ -11,9 +11,7 @@ const list_item_hunter = function() { return matches.reduce((previousMatchPromise, liMatchStart) => { return previousMatchPromise.then(() => { logger.debug( - `found listItem of size ${liMatchStart} inside ${ - pattern.patternPartial - }` + `found listItem of size ${liMatchStart} inside ${pattern.patternPartial}` ); //we found a listitem match @@ -41,7 +39,7 @@ const list_item_hunter = function() { } return { - process_list_item_partials: function(pattern) { + process_list_item_partials: function (pattern) { return processListItemPartials(pattern); }, }; diff --git a/packages/core/src/lib/loadPattern.js b/packages/core/src/lib/loadPattern.js index 6eae3843e..b5990fecf 100644 --- a/packages/core/src/lib/loadPattern.js +++ b/packages/core/src/lib/loadPattern.js @@ -3,7 +3,6 @@ const path = require('path'); const Pattern = require('./object_factory').Pattern; -const mp = require('./markdown_parser'); const logger = require('./log'); const patternEngines = require('./pattern_engines'); const ch = require('./changes_hunter'); @@ -12,7 +11,6 @@ const addPattern = require('./addPattern'); const buildListItems = require('./buildListItems'); const readDocumentation = require('./readDocumentation'); -const markdown_parser = new mp(); const changes_hunter = new ch(); const dataLoader = new da(); @@ -21,15 +19,28 @@ let fs = require('fs-extra'); //eslint-disable-line prefer-const // loads a pattern from disk, creates a Pattern object from it and // all its associated files, and records it in patternlab.patterns[] -module.exports = function(relPath, patternlab) { +module.exports = function (relPath, patternlab) { + const fileObject = path.parse(relPath); + + //extract some information + const filename = fileObject.base; + const ext = fileObject.ext; + const patternsPath = patternlab.config.paths.source.patterns; + + // skip non-pattern files + if (!patternEngines.isPatternFile(filename, patternlab)) { + return null; + } + + // Determine patterns nested too deep and show a warning const relativeDepth = (relPath.match(/\w(?=\\)|\w(?=\/)/g) || []).length; - if (relativeDepth > 2) { + if (relativeDepth > 3) { logger.warning(''); logger.warning('Warning:'); logger.warning( 'A pattern file: ' + relPath + - ' was found greater than 2 levels deep from ' + + ' was found greater than 3 levels deep from ' + patternlab.config.paths.source.patterns + '.' ); @@ -37,69 +48,22 @@ module.exports = function(relPath, patternlab) { "It's strongly suggested to not deviate from the following structure under _patterns/" ); logger.warning( - '[patternType]/[patternSubtype]/[patternName].[patternExtension]' + '[patternGroup]/[patternSubgroup]/[patternName].[patternExtension]' + ); + logger.warning('or'); + logger.warning( + '[patternGroup]/[patternSubgroup]/[patternName]/[patternName].[patternExtension]' ); logger.warning(''); logger.warning( 'While Pattern Lab may still function, assets may 404 and frontend links may break. Consider yourself warned. ' ); logger.warning( - 'Read More: http://patternlab.io/docs/pattern-organization.html' + 'Read More: https://patternlab.io/docs/overview-of-patterns/' ); logger.warning(''); } - //check if the found file is a top-level markdown file - const fileObject = path.parse(relPath); - if (fileObject.ext === '.md') { - try { - const proposedDirectory = path.resolve( - patternlab.config.paths.source.patterns, - fileObject.dir, - fileObject.name - ); - const proposedDirectoryStats = fs.statSync(proposedDirectory); - if (proposedDirectoryStats.isDirectory()) { - const subTypeMarkdownFileContents = fs.readFileSync( - proposedDirectory + '.md', - 'utf8' - ); - const subTypeMarkdown = markdown_parser.parse( - subTypeMarkdownFileContents - ); - const subTypePattern = new Pattern(relPath, null, patternlab); - subTypePattern.patternSectionSubtype = true; - subTypePattern.patternDesc = subTypeMarkdown - ? subTypeMarkdown.markdown - : ''; - subTypePattern.flatPatternPath = - subTypePattern.flatPatternPath + '-' + subTypePattern.fileName; - subTypePattern.isPattern = false; - subTypePattern.engine = null; - patternlab.subtypePatterns[ - subTypePattern.patternPartial - ] = subTypePattern; - - return subTypePattern; - } - } catch (err) { - // no file exists, meaning it's a pattern markdown file - if (err.code !== 'ENOENT') { - logger.warning(err); - } - } - } - - //extract some information - const filename = fileObject.base; - const ext = fileObject.ext; - const patternsPath = patternlab.config.paths.source.patterns; - - // skip non-pattern files - if (!patternEngines.isPatternFile(filename, patternlab)) { - return null; - } - //make a new Pattern Object const currentPattern = new Pattern(relPath, null, patternlab); @@ -130,10 +94,10 @@ module.exports = function(relPath, patternlab) { ); } } catch (err) { - logger.warning( + logger.error( `There was an error parsing sibling JSON for ${currentPattern.relPath}` ); - logger.warning(err); + logger.error(err); } //look for a listitems.json file for this template @@ -148,20 +112,16 @@ module.exports = function(relPath, patternlab) { if (listItemsData) { logger.debug( - `found pattern-specific listitems data for ${ - currentPattern.patternPartial - }` + `found pattern-specific listitems data for ${currentPattern.patternPartial}` ); currentPattern.listitems = listItemsData; buildListItems(currentPattern); } } catch (err) { - logger.warning( - `There was an error parsing sibling listitem JSON for ${ - currentPattern.relPath - }` + logger.error( + `There was an error parsing sibling listitem JSON for ${currentPattern.relPath}` ); - logger.warning(err); + logger.error(err); } //look for a markdown file for this template @@ -172,11 +132,9 @@ module.exports = function(relPath, patternlab) { currentPattern.template = fs.readFileSync(templatePath, 'utf8'); - //find any stylemodifiers that may be in the current pattern - currentPattern.stylePartials = currentPattern.findPartialsWithStyleModifiers(); - //find any pattern parameters that may be in the current pattern - currentPattern.parameteredPartials = currentPattern.findPartialsWithPatternParameters(); + currentPattern.parameteredPartials = + currentPattern.findPartialsWithPatternParameters(); [ templatePath, @@ -186,7 +144,7 @@ module.exports = function(relPath, patternlab) { `${listJsonFileName}.json`, `${listJsonFileName}.yml`, `${listJsonFileName}.yaml`, - ].forEach(file => { + ].forEach((file) => { changes_hunter.checkLastModified(currentPattern, file); }); diff --git a/packages/core/src/lib/loaduikits.js b/packages/core/src/lib/loaduikits.js index 1f97564a2..79de4556f 100644 --- a/packages/core/src/lib/loaduikits.js +++ b/packages/core/src/lib/loaduikits.js @@ -5,92 +5,110 @@ const _ = require('lodash'); const logger = require('./log'); -let findModules = require('./findModules'); //eslint-disable-line prefer-const -let fs = require('fs-extra'); // eslint-disable-line - -const uiKitMatcher = /^uikit-(.*)$/; -const nodeModulesPath = path.join(process.cwd(), 'node_modules'); - -/** - * Given a path: return the uikit name if the path points to a valid uikit - * module directory, or false if it doesn't. - * @param filePath - * @returns UIKit name if exists or FALSE - */ -const isUIKitModule = filePath => { - const baseName = path.basename(filePath); - const engineMatch = baseName.match(uiKitMatcher); +const { resolvePackageFolder } = require('./resolver'); - if (engineMatch) { - return engineMatch[1]; - } - return false; -}; +let fs = require('fs-extra'); // eslint-disable-line -const readModuleFile = (kit, subPath) => { +const readModuleFile = (uikitLocation, subPath) => { return fs.readFileSync( - path.resolve(path.join(kit.modulePath, subPath)), + path.resolve(path.join(uikitLocation, subPath)), 'utf8' ); }; /** * Loads uikits, connecting configuration and installed modules - * [1] Looks in node_modules for uikits. - * [2] Only continue if uikit is enabled in patternlab-config.json - * [3] Reads files from uikit that apply to every template + * [1] Lists the enabled uikits from patternlab-config.json + * [2] Try to resolve the location of the uikit in the package dependencies + * [3] Warn when the uikit couldn't be loaded + * [4] Reads files from uikit that apply to every template * @param {object} patternlab */ -module.exports = patternlab => { +module.exports = (patternlab) => { const paths = patternlab.config.paths; - const uikits = findModules(nodeModulesPath, isUIKitModule); // [1] - - uikits.forEach(kit => { - const configEntry = _.find(_.filter(patternlab.config.uikits, 'enabled'), { - name: `uikit-${kit.name}`, - }); // [2] - - if (!configEntry) { - logger.warning( - `Could not find uikit with name uikit-${ - kit.name - } defined within patternlab-config.json, or it is not enabled.` - ); - return; + const uikitConfigs = _.filter(patternlab.config.uikits, 'enabled'); // [1] + uikitConfigs.forEach((uikitConfig) => { + let uikitLocation = null; + if ('package' in uikitConfig) { + try { + uikitLocation = resolvePackageFolder(uikitConfig.package); + } catch (ex) { + logger.warning( + `Could not find uikit with package name ${uikitConfig.package}. Did you add it to the 'dependencies' section in your 'package.json' file?` + ); + return; + } + } else { + // For backwards compatibility, name to package calculation is: + // 1. name -> name + // 2. name -> uikit-name + // 3. name -> @pattern-lab/name + // 4. name -> @pattern-lab/uikit-name + for (const packageName of [ + uikitConfig.name, + `uikit-${uikitConfig.name}`, + `@pattern-lab/${uikitConfig.name}`, + `@pattern-lab/uikit-${uikitConfig.name}`, + ]) { + try { + uikitLocation = resolvePackageFolder(packageName); // [2] + } catch (ex) { + // Ignore + } + if (uikitLocation != null) { + uikitConfig.package = packageName; + logger.info(`Found uikit package ${packageName}`); + break; + } + } + if (uikitLocation == null) { + logger.warning( + `Could not find uikit with package name ${uikitConfig.name}, uikit-${uikitConfig.name}, @pattern-lab/${uikitConfig.name} or @pattern-lab/uikit-${uikitConfig.name} defined within patternlab-config.json in the package dependencies.` + ); + return; + } else { + logger.warning( + `Please update the configuration of UIKit ${uikitConfig.name} with property 'package: ${uikitConfig.package}' in patternlab-config.json. Lookup by 'name' is deprecated and will be removed in the future.` + ); + } // [3] } try { - patternlab.uikits[`uikit-${kit.name}`] = { - name: `uikit-${kit.name}`, - modulePath: kit.modulePath, + patternlab.uikits[uikitConfig.name] = { + name: uikitConfig.name, + package: uikitConfig.package, + modulePath: uikitLocation, enabled: true, - outputDir: configEntry.outputDir, - excludedPatternStates: configEntry.excludedPatternStates, - excludedTags: configEntry.excludedTags, + outputDir: uikitConfig.outputDir, + excludedPatternStates: uikitConfig.excludedPatternStates, + excludedTags: uikitConfig.excludedTags, header: readModuleFile( - kit, + uikitLocation, paths.source.patternlabFiles['general-header'] ), footer: readModuleFile( - kit, + uikitLocation, paths.source.patternlabFiles['general-footer'] ), patternSection: readModuleFile( - kit, + uikitLocation, paths.source.patternlabFiles.patternSection ), - patternSectionSubType: readModuleFile( - kit, - paths.source.patternlabFiles.patternSectionSubtype + patternSectionSubgroup: readModuleFile( + uikitLocation, + paths.source.patternlabFiles.patternSectionSubgroup + ), + viewAll: readModuleFile( + uikitLocation, + paths.source.patternlabFiles.viewall ), - viewAll: readModuleFile(kit, paths.source.patternlabFiles.viewall), - }; // [3] + }; // [4] } catch (ex) { logger.error(ex); logger.error( '\nERROR: missing an essential file from ' + - kit.modulePath + + uikitLocation + paths.source.patternlabFiles + ". Pattern Lab won't work without this file.\n" ); diff --git a/packages/core/src/lib/log.js b/packages/core/src/lib/log.js index 87a7cd587..f55ff4aa1 100644 --- a/packages/core/src/lib/log.js +++ b/packages/core/src/lib/log.js @@ -63,8 +63,8 @@ const error = log.error.bind(log); * @param {string} - a message to report * @returns {function} - a callback to be passed to a Promise's .catch() */ -const reportError = function(message) { - return function(err) { +const reportError = function (message) { + return function (err) { console.log(message); console.log(err); }; diff --git a/packages/core/src/lib/markModifiedPatterns.js b/packages/core/src/lib/markModifiedPatterns.js index 00ed51de1..6eede313e 100644 --- a/packages/core/src/lib/markModifiedPatterns.js +++ b/packages/core/src/lib/markModifiedPatterns.js @@ -17,7 +17,7 @@ let fs = require('fs-extra'); //eslint-disable-line prefer-const * @param lastModified * @param patternlab */ -module.exports = function(lastModified, patternlab) { +module.exports = function (lastModified, patternlab) { /** * If the given array exists, apply a function to each of its elements * @param {Array} array @@ -28,15 +28,13 @@ module.exports = function(lastModified, patternlab) { array.forEach(func); } }; - const modifiedOrNot = _.groupBy( - patternlab.patterns, - p => - changes_hunter.needsRebuild(lastModified, p) ? 'modified' : 'notModified' + const modifiedOrNot = _.groupBy(patternlab.patterns, (p) => + changes_hunter.needsRebuild(lastModified, p) ? 'modified' : 'notModified' ); // For all unmodified patterns load their rendered template output - forEachExisting(modifiedOrNot.notModified, cleanPattern => { - _.each(patternlab.uikits, uikit => { + forEachExisting(modifiedOrNot.notModified, (cleanPattern) => { + _.each(patternlab.uikits, (uikit) => { const xp = path.join( process.cwd(), uikit.outputDir, @@ -52,7 +50,7 @@ module.exports = function(lastModified, patternlab) { // For all patterns that were modified, schedule them for rebuild forEachExisting( modifiedOrNot.modified, - p => (p.compileState = CompileState.NEEDS_REBUILD) + (p) => (p.compileState = CompileState.NEEDS_REBUILD) ); return modifiedOrNot; }; diff --git a/packages/core/src/lib/markdown_parser.js b/packages/core/src/lib/markdown_parser.js index c940a5f67..f2c0e7b42 100644 --- a/packages/core/src/lib/markdown_parser.js +++ b/packages/core/src/lib/markdown_parser.js @@ -3,7 +3,7 @@ const md = require('markdown-it')(); const yaml = require('js-yaml'); const logger = require('./log'); -const markdown_parser = function() { +const markdown_parser = function () { /** * Converts a markdown block with frontmatter (each is optional, technically) to a well-formed object. * @param block - the ".md" file, which can contain frontmatter or not, or only frontmatter. @@ -13,8 +13,9 @@ const markdown_parser = function() { let returnObject = {}; try { - //for each block process the yaml frontmatter and markdown - const frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; + // for each block process the yaml frontmatter and markdown + // even if the pattern only has pattern data without further documentation + const frontmatterRE = /---\r?\n{1}([\s\S]*)^---([\s\S]*)+/gm; const chunks = frontmatterRE.exec(block); if (chunks) { @@ -22,7 +23,7 @@ const markdown_parser = function() { if (chunks && chunks[1]) { //parse the yaml if we got it const frontmatter = chunks[1]; - returnObject = yaml.safeLoad(frontmatter); + returnObject = yaml.load(frontmatter); } if (chunks[2]) { @@ -46,7 +47,7 @@ const markdown_parser = function() { } return { - parse: function(block) { + parse: function (block) { return parseMarkdownBlock(block); }, }; diff --git a/packages/core/src/lib/object_factory.js b/packages/core/src/lib/object_factory.js index 0c3ffe5d2..318b4cd25 100644 --- a/packages/core/src/lib/object_factory.js +++ b/packages/core/src/lib/object_factory.js @@ -1,82 +1,129 @@ 'use strict'; -const patternEngines = require('./pattern_engines'); + +const _ = require('lodash'); const path = require('path'); -const extend = require('util')._extend; +const logger = require('./log'); +const patternEngines = require('./pattern_engines'); -// patternPrefixMatcher is intended to match the leading maybe-underscore, +// prefixMatcher is intended to match the leading maybe-underscore, // zero or more digits, and maybe-dash at the beginning of a pattern file name we can hack them // off and get at the good part. -const patternPrefixMatcher = /^_?(\d+-)?/; +const prefixMatcher = /^_?(\d+-)?/; +const prefixMatcherDeprecationCheckOrder = /^(\d+-).+/; +const prefixMatcherDeprecationCheckHidden = /^_.+/; -// Pattern properties /** - * Pattern constructor - * @constructor + * Pattern constructor / Pattern properties + * + * Before changing functionalities of the pattern object please read the following pull requests + * to get more details about the behavior of the folder structure + * https://patternlab.io/docs/overview-of-patterns/#heading-deeper-nesting + * https://github.com/pattern-lab/patternlab-node/pull/992 + * https://github.com/pattern-lab/patternlab-node/pull/1016 + * https://github.com/pattern-lab/patternlab-node/pull/1143 + * + * @param {string} relPath relative directory + * @param {Object} jsonFileData The JSON used to render values in the pattern. + * @param {Patternlab} patternlab The actual pattern lab instance + * @param {boolean} isPromoteToFlatPatternRun specifies if the pattern needs to be removed from its deep nesting folder */ -const Pattern = function(relPath, data, patternlab) { +const Pattern = function ( + relPath, + jsonFileData, + patternlab, + isPromoteToFlatPatternRun +) { + this.relPath = path.normalize(relPath); // 'atoms/global/colors.mustache' + /** * We expect relPath to be the path of the pattern template, relative to the * root of the pattern tree. Parse out the path parts and save the useful ones. - * @param {relPath} relative directory - * @param {data} The JSON used to render values in the pattern. - * @param {patternlab} rendered html files for the pattern */ - const pathObj = path.parse(path.normalize(relPath)); - this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' - this.fileName = pathObj.name; // '00-colors' - this.subdir = pathObj.dir; // '00-atoms/00-global' + const pathObj = path.parse(this.relPath); + + const info = this.getPatternInfo( + pathObj, + patternlab, + isPromoteToFlatPatternRun || + (patternlab && + patternlab.config && + patternlab.config.allPatternsAreDeeplyNested) + ); + + this.fileName = pathObj.name; // 'colors' + this.subdir = pathObj.dir; // 'atoms/global' this.fileExtension = pathObj.ext; // '.mustache' - // this is the unique name, subDir + fileName (sans extension) - this.name = - this.subdir.replace(path.sep, '-') + '-' + this.fileName.replace('~', '-'); // '00-atoms-00-global-00-colors' + // TODO: Remove if block when dropping ordering by prefix and keep else code + // (When we drop the info about the old ordering is deprecated) + if ( + (prefixMatcherDeprecationCheckOrder.test(this.getDirLevel(0, info)) || + prefixMatcherDeprecationCheckOrder.test(this.getDirLevel(1, info)) || + prefixMatcherDeprecationCheckOrder.test(this.fileName)) && + patternlab && + patternlab.config && + !patternlab.config.disableDeprecationWarningForOrderPatterns + ) { + logger.warning( + `${info.shortNotation}-${this.fileName} "Pattern", "Group" and "Subgroup" ordering by number prefix (##-) will be deprecated in the future.\n See https://patternlab.io/docs/reorganizing-patterns/` + ); + } + + if ( + (prefixMatcherDeprecationCheckHidden.test(this.getDirLevel(0, info)) || + prefixMatcherDeprecationCheckHidden.test(this.getDirLevel(1, info)) || + prefixMatcherDeprecationCheckHidden.test(this.fileName)) && + !info.isMetaPattern && + patternlab && + patternlab.config && + !patternlab.config.disableDeprecationWarningForHiddenPatterns + ) { + logger.warning( + `${info.shortNotation}/${this.fileName} "Pattern", "Group" and "Subgroup" hiding by underscore prefix (_*) will be deprecated in the future.\n See https://patternlab.io/docs/hiding-patterns-in-the-navigation/` + ); + } + + // TODO: Remove if when dropping ordering by prefix and keep else code + if (info.patternHasOwnDir) { + // Since there is still the requirement of having the numbers provided for sorting + // this will be required to keep the folder prefix and the variant name + // /00-atoms/00-global/00-colors/colors~variant.hbs + // -> 00-atoms-00-global-00-colors-variant + this.name = `${info.shortNotation}-${path.parse(pathObj.dir).base}${ + this.fileName.indexOf('~') !== -1 ? '-' + this.fileName.split('~')[1] : '' + }`; + } else { + // this is the unique name, subDir + fileName (sans extension) + this.name = `${info.shortNotation}-${this.fileName.replace('~', '-')}`; + } // the JSON used to render values in the pattern - this.jsonFileData = data || {}; + this.jsonFileData = jsonFileData || {}; - // strip leading "00-" from the file name and flip tildes to dashes + // flip tildes to dashes this.patternBaseName = this.fileName - .replace(patternPrefixMatcher, '') + .replace(prefixMatcher, '') .replace('~', '-'); // 'colors' - // Fancy name. No idea how this works. 'Colors' - this.patternName = this.patternBaseName - .split('-') - .reduce(function(val, working) { - return ( - val.charAt(0).toUpperCase() + - val.slice(1) + - ' ' + - working.charAt(0).toUpperCase() + - working.slice(1) - ); - }, '') - .trim(); //this is the display name for the ui. strip numeric + hyphen prefixes + // Fancy name - Uppercase letters of pattern name partials. + // global-colors -> 'Global Colors' + // this is the display name for the ui. strip numeric + hyphen prefixes + this.patternName = _.startCase(this.patternBaseName); // the top-level pattern group this pattern belongs to. 'atoms' - this.patternGroup = this.subdir - .split(path.sep)[0] - .replace(patternPrefixMatcher, ''); - - //00-atoms if needed - this.patternType = this.subdir.split(path.sep)[0]; + this.patternGroup = this.getDirLevel(0, info).replace(prefixMatcher, ''); // the sub-group this pattern belongs to. - this.patternSubGroup = path - .basename(this.subdir) - .replace(patternPrefixMatcher, ''); // 'global' - - //00-colors if needed - this.patternSubType = path.basename(this.subdir); + this.patternSubgroup = this.getDirLevel(1, info).replace(prefixMatcher, ''); // 'global' // the joined pattern group and subgroup directory - this.flatPatternPath = this.subdir.replace(/[\/\\]/g, '-'); // '00-atoms-00-global' + this.flatPatternPath = info.shortNotation; // 'atoms-global' - // calculated path from the root of the public directory to the generated + // Calculated path from the root of the public directory to the generated // (rendered!) html file for this pattern, to be shown in the iframe - this.patternLink = this.patternSectionSubtype - ? `$${this.name}/index.html` - : patternlab ? this.getPatternLink(patternlab, 'rendered') : null; + this.patternLink = patternlab + ? this.getPatternLink(patternlab, 'rendered') + : null; // The canonical "key" by which this pattern is known. This is the callable // name of the pattern. UPDATE: this.key is now known as this.patternPartial @@ -84,11 +131,24 @@ const Pattern = function(relPath, data, patternlab) { // Let's calculate the verbose name ahead of time! We don't use path.sep here // on purpose. This isn't a file name! - this.verbosePartial = - this.subdir.split(path.sep).join('/') + '/' + this.fileName; + this.verbosePartial = `${info.shortNotation}/${this.fileName}`; + + /** + * Definition of flat pattern: + * The flat pattern is a high level pattern which is attached directly to + * the main root folder or to a root directory. + * --- This --- + * root + * flatPattern + * --- OR That --- + * root + * molecules + * flatPattern + */ + this.isFlatPattern = + this.patternGroup === this.patternSubgroup || !this.patternSubgroup; this.isPattern = true; - this.isFlatPattern = this.patternGroup === this.patternSubGroup; this.patternState = ''; this.template = ''; this.patternPartialCode = ''; @@ -97,17 +157,39 @@ const Pattern = function(relPath, data, patternlab) { this.lineageR = []; this.lineageRIndex = []; this.isPseudoPattern = false; - this.order = Number.MAX_SAFE_INTEGER; + this.order = 0; + this.variantOrder = 0; this.engine = patternEngines.getEngineForPattern(this); + // TODO: Remove the following when ordering by file prefix gets obsolete + this.patternGroupData = this.patternGroupData || {}; + if (!this.patternGroupData.order && info.patternGroupOrder) { + this.patternGroupData.order = info.patternGroupOrder; + } + + // TODO: Remove the following when ordering by file prefix gets obsolete + this.patternSubgroupData = this.patternSubgroupData || {}; + if (!this.patternSubgroupData.order && info.patternSubgroupOrder) { + this.patternGroupData.order = info.patternSubgroupOrder; + } + + // TODO: Remove the following when ordering by file prefix gets obsolete + if (prefixMatcherDeprecationCheckOrder.test(this.fileName)) { + if (this.fileName.indexOf('~') === -1) { + this.order = this.setPatternOrderDataForInfo(this.fileName); + } else { + this.variantOrder = this.setPatternOrderDataForInfo(this.fileName); + } + } + /** * Determines if this pattern needs to be recompiled. * - * @ee {@link CompileState}*/ + * @see {@link CompileState}*/ this.compileState = null; /** - * Timestamp in milliseconds when the pattern template or auxilary file (e.g. json) were modified. + * Timestamp in milliseconds when the pattern template or auxiliary file (e.g. json) were modified. * If multiple files are affected, this is the timestamp of the most recent change. * * @see {@link pattern} @@ -119,7 +201,7 @@ const Pattern = function(relPath, data, patternlab) { Pattern.prototype = { // render function - acts as a proxy for the PatternEngine's - render: function(data, partials) { + render: function (data, partials) { if (!this.extendedTemplate) { this.extendedTemplate = this.template; } @@ -131,26 +213,33 @@ Pattern.prototype = { partials ); return promise - .then(results => { + .then((results) => { return results; }) - .catch(reason => { + .catch((reason) => { return Promise.reject(reason); }); } return Promise.reject('where is the engine?'); }, - registerPartial: function() { + registerPartial: function () { if (this.engine && typeof this.engine.registerPartial === 'function') { this.engine.registerPartial(this); } }, - // calculated path from the root of the public directory to the generated html - // file for this pattern. - // Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' - getPatternLink: function(patternlab, suffixType, customfileExtension) { + /** + * calculated path from the root of the public directory to the generated html + * file for this pattern. + * + * Should look something like 'atoms-global-colors/atoms-global-colors.html' + * + * @param {Patternlab} patternlab Current patternlab instance + * @param {string} suffixType File suffix + * @param {string} customFileExtension Custom extension + */ + getPatternLink: function (patternlab, suffixType, customFileExtension) { // if no suffixType is provided, we default to rendered const suffixConfig = patternlab.config.outputFileSuffixes; const suffix = suffixType @@ -162,59 +251,188 @@ Pattern.prototype = { } if (suffixType === 'custom') { - return this.name + path.sep + this.name + customfileExtension; + return this.name + path.sep + this.name + customFileExtension; } return this.name + path.sep + this.name + suffix + '.html'; }, - // the finders all delegate to the PatternEngine, which also encapsulates all - // appropriate regexes - findPartials: function() { + /** + * The finders all delegate to the PatternEngine, which also + * encapsulates all appropriate regex's + */ + findPartials: function () { return this.engine.findPartials(this); }, - findPartialsWithStyleModifiers: function() { - return this.engine.findPartialsWithStyleModifiers(this); - }, - - findPartialsWithPatternParameters: function() { + findPartialsWithPatternParameters: function () { return this.engine.findPartialsWithPatternParameters(this); }, - findListItems: function() { + findListItems: function () { return this.engine.findListItems(this); }, - findPartial: function(partialString) { + findPartial: function (partialString) { return this.engine.findPartial(partialString); }, + + /** + * Get a directory on a specific level of the pattern path + * + * @param {Number} level Level of folder to get + * @param {Object} pInfo general information about the pattern + */ + getDirLevel: function (level, pInfo) { + const items = this.subdir.split(path.sep); + pInfo && pInfo.patternHasOwnDir && items.pop(); + + if (items[level]) { + return items[level]; + } else if (level >= 1) { + return ''; + } else { + // I'm not quite sure about that but its better than empty node + // TODO: verify + return 'root'; + } + }, + + /** + * Reset the information that the pattern has it's own directory, + * so that this pattern will not be handled as flat pattern if it + * is located on a top level folder. + * + * @param {Patternlab} patternlab Current patternlab instance + */ + promoteFromDirectoryToFlatPattern: function (patternlab) { + const p = new Pattern(this.relPath, this.jsonFileData, patternlab, true); + // Only reset the specific fields, not everything + Object.assign(this, { + name: p.name, + patternLink: p.patternLink, + patternGroup: p.patternGroup, + patternSubgroup: p.patternSubgroup, + isFlatPattern: p.isFlatPattern, + flatPatternPath: p.flatPatternPath, + patternPartial: p.patternPartial, + verbosePartial: p.verbosePartial, + }); + }, + + /** + * Retrieves the number prefix, which later is used for sorting. + * (Can be removed when sorting by number prefix becomes obsolete) + * @param {*} pathStr the path that needs to be checked for number prefixes + * @returns the order number or 0 when no prefix is available + */ + setPatternOrderDataForInfo: (pathStr) => { + const match = pathStr.match(prefixMatcherDeprecationCheckOrder); + return match && match.length >= 1 + ? pathStr.match(prefixMatcherDeprecationCheckOrder)[1].replace('-', '') + : 0; + }, + + /** + * The "info" object contains information about pattern structure if it is + * a nested pattern or if it just a sub folder structure. It's just used for + * internal purposes. Remember every pattern information based on "this.*" + * will be used by other functions + * + * @param pathObj path.parse() object containing useful path information + */ + getPatternInfo: (pathObj, patternlab, isPromoteToFlatPatternRun) => { + const info = { + // colors(.mustache) is deeply nested in atoms-/global/colors + patternlab: patternlab, + patternHasOwnDir: isPromoteToFlatPatternRun + ? path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.replace(prefixMatcher, '') || + path.basename(pathObj.dir).replace(prefixMatcher, '') === + pathObj.name.split('~')[0].replace(prefixMatcher, '') + : false, + }; + + info.dir = info.patternHasOwnDir ? pathObj.dir.split(path.sep).pop() : ''; + info.dirLevel = pathObj.dir.split(path.sep).filter((s) => !!s).length; + + // Only relevant for deprecation check and message + if (path.parse(pathObj.dir).base === '_meta') { + info.isMetaPattern = true; + } + + if (info.dirLevel === 0 || (info.dirLevel === 1 && info.patternHasOwnDir)) { + // -> ./ + info.shortNotation = 'root'; + } else if (info.dirLevel === 2 && info.patternHasOwnDir) { + // -> ./folder + info.shortNotation = path.dirname(pathObj.dir).replace(prefixMatcher, ''); + info.patternGroupOrder = Pattern.prototype.setPatternOrderDataForInfo( + path.dirname(pathObj.dir) + ); + } else { + // -> ./folder/folder + info.shortNotation = pathObj.dir + .split(/\/|\\/, 2) + .map((o, i) => { + if (i === 0) { + // TODO: Remove when prefix gets deprecated + info.patternGroupOrder = + Pattern.prototype.setPatternOrderDataForInfo(o); + } + + if (i === 1) { + // TODO: Remove when prefix gets deprecated + info.patternSubgroupOrder = + Pattern.prototype.setPatternOrderDataForInfo(o); + } + + return o.replace(prefixMatcher, ''); + }) + .join('-') + .replace(new RegExp(`-${info.dir}$`), ''); + info.verbosePartial = pathObj.dir + .split(/\/|\\/, 2) + .map((o) => o.replace(prefixMatcher, '')) + .join('/') + .replace(new RegExp(`-${info.dir}$`), ''); + } + + return info; + }, }; // Pattern static methods -// factory: creates an empty Pattern for miscellaneous internal use, such as -// by list_item_hunter -Pattern.createEmpty = function(customProps, patternlab) { +/** + * factory: creates an empty Pattern for miscellaneous internal use, such as + * by list_item_hunter + * + * @param {Object} customProps Properties to apply to new pattern + * @param {Patternlab} patternlab Current patternlab instance + */ +Pattern.createEmpty = function (customProps, patternlab) { let relPath = ''; if (customProps) { if (customProps.relPath) { relPath = customProps.relPath; } else if (customProps.subdir && customProps.filename) { - relPath = customProps.subdir + path.sep + customProps.filename; + relPath = path.join(customProps.subdir, customProps.filename); } } const pattern = new Pattern(relPath, null, patternlab); - return extend(pattern, customProps); + return Object.assign(pattern, customProps); }; -// factory: creates an Pattern object on-demand from a hash; the hash accepts -// parameters that replace the positional parameters that the Pattern -// constructor takes. -Pattern.create = function(relPath, data, customProps, patternlab) { +/** + * factory: creates a Pattern object on-demand from a hash; the hash accepts + * parameters that replace the positional parameters that the Pattern + * constructor takes. + */ +Pattern.create = function (relPath, data, customProps, patternlab) { const newPattern = new Pattern(relPath || '', data || null, patternlab); - return extend(newPattern, customProps); + return Object.assign(newPattern, customProps); }; const CompileState = { diff --git a/packages/core/src/lib/parameter_hunter.js b/packages/core/src/lib/parameter_hunter.js deleted file mode 100644 index eeec121dc..000000000 --- a/packages/core/src/lib/parameter_hunter.js +++ /dev/null @@ -1,351 +0,0 @@ -'use strict'; - -const smh = require('./style_modifier_hunter'); -const style_modifier_hunter = new smh(); - -const getPartial = require('./get'); -const logger = require('./log'); -const parseLink = require('./parseLink'); -const jsonCopy = require('./json_copy'); -const replaceParameter = require('./replaceParameter'); - -const parameter_hunter = function() { - /** - * This function is really to accommodate the lax JSON-like syntax allowed by - * Pattern Lab PHP for parameter submissions to partials. Unfortunately, no - * easily searchable library was discovered for this. What we had to do was - * write a custom script to crawl through the parameter string, and wrap the - * keys and values in double-quotes as necessary. - * The steps on a high-level are as follows: - * * Further escape all escaped quotes and colons. Use the string - * representation of their unicodes for this. This has the added bonus - * of being interpreted correctly by JSON.parse() without further - * modification. This will be useful later in the function. - * * Once escaped quotes are out of the way, we know the remaining quotes - * are either key/value wrappers or wrapped within those wrappers. We know - * that remaining commas and colons are either delimiters, or wrapped - * within quotes to not be recognized as such. - * * A do-while loop crawls paramString to write keys to a keys array and - * values to a values array. - * * Start by parsing the first key. Determine the type of wrapping quote, - * if any. - * * By knowing the open wrapper, we know that the next quote of that kind - * (if the key is wrapped in quotes), HAS to be the close wrapper. - * Similarly, if the key is unwrapped, we know the next colon HAS to be - * the delimiter between key and value. - * * Save the key to the keys array. - * * Next, search for a value. It will either be the next block wrapped in - * quotes, or a string of alphanumerics, decimal points, or minus signs. - * * Save the value to the values array. - * * The do-while loop truncates the paramString value while parsing. Its - * condition for completion is when the paramString is whittled down to an - * empty string. - * * After the keys and values arrays are built, a for loop iterates through - * them to build the final paramStringWellFormed string. - * * No quote substitution had been done prior to this loop. In this loop, - * all keys are ensured to be wrapped in double-quotes. String values are - * also ensured to be wrapped in double-quotes. - * * Unescape escaped unicodes except for double-quotes. Everything beside - * double-quotes will be wrapped in double-quotes without need for escape. - * * Return paramStringWellFormed. - * - * @param {string} pString - * @returns {string} paramStringWellFormed - */ - function paramToJson(pString) { - let colonPos = -1; - const keys = []; - let paramString = pString; // to not reassign param - let paramStringWellFormed; - let quotePos = -1; - let regex; - const values = []; - let wrapper; - - // attempt to parse the data in case it is already well formed JSON - try { - paramStringWellFormed = JSON.stringify(JSON.parse(pString)); - return paramStringWellFormed; - } catch (err) { - logger.debug( - `Not valid JSON found for passed pattern parameter ${pString} will attempt to parse manually...` - ); - } - - //replace all escaped double-quotes with escaped unicode - paramString = paramString.replace(/\\"/g, '\\u0022'); - - //replace all escaped single-quotes with escaped unicode - paramString = paramString.replace(/\\'/g, '\\u0027'); - - //replace all escaped colons with escaped unicode - paramString = paramString.replace(/\\:/g, '\\u0058'); - - //with escaped chars out of the way, crawl through paramString looking for - //keys and values - do { - //check if searching for a key - if (paramString[0] === '{' || paramString[0] === ',') { - paramString = paramString.substring(1, paramString.length).trim(); - - //search for end quote if wrapped in quotes. else search for colon. - //everything up to that position will be saved in the keys array. - switch (paramString[0]) { - //need to search for end quote pos in case the quotes wrap a colon - case '"': - case "'": - wrapper = paramString[0]; - quotePos = paramString.indexOf(wrapper, 1); - break; - - default: - colonPos = paramString.indexOf(':'); - } - - if (quotePos > -1) { - keys.push(paramString.substring(0, quotePos + 1).trim()); - - //truncate the beginning from paramString and look for a value - paramString = paramString - .substring(quotePos + 1, paramString.length) - .trim(); - - //unset quotePos - quotePos = -1; - } else if (colonPos > -1) { - keys.push(paramString.substring(0, colonPos).trim()); - - //truncate the beginning from paramString and look for a value - paramString = paramString.substring(colonPos, paramString.length); - - //unset colonPos - colonPos = -1; - - //if there are no more colons, and we're looking for a key, there is - //probably a problem. stop any further processing. - } else { - paramString = ''; - break; - } - } - - //now, search for a value - if (paramString[0] === ':') { - paramString = paramString.substring(1, paramString.length).trim(); - - //the only reason we're using regexes here, instead of indexOf(), is - //because we don't know if the next delimiter is going to be a comma or - //a closing curly brace. since it's not much of a performance hit to - //use regexes as sparingly as here, and it's much more concise and - //readable, we'll use a regex for match() and replace() instead of - //performing conditional logic with indexOf(). - switch (paramString[0]) { - //since a quote of same type as its wrappers would be escaped, and we - //escaped those even further with their unicodes, it is safe to look - //for wrapper pairs and conclude that their contents are values - case '"': - regex = /^"(.|\s)*?"/; - break; - case "'": - regex = /^'(.|\s)*?'/; - break; - - //if there is no value wrapper, regex for alphanumerics, decimal - //points, and minus signs for exponential notation. - default: - regex = /^[\w\-\.]*/; - } - values.push(paramString.match(regex)[0].trim()); - - //truncate the beginning from paramString and continue either - //looking for a key, or returning - paramString = paramString.replace(regex, '').trim(); - - //exit do while if the final char is '}' - if (paramString === '}') { - paramString = ''; - break; - } - - //if there are no more colons, and we're looking for a value, there is - //probably a problem. stop any further processing. - } else { - paramString = ''; - break; - } - } while (paramString); - - //build paramStringWellFormed string for JSON parsing - paramStringWellFormed = '{'; - for (let i = 0; i < keys.length; i++) { - //keys - //replace single-quote wrappers with double-quotes - if (keys[i][0] === "'" && keys[i][keys[i].length - 1] === "'") { - paramStringWellFormed += '"'; - - //any enclosed double-quotes must be escaped - paramStringWellFormed += keys[i] - .substring(1, keys[i].length - 1) - .replace(/"/g, '\\"'); - paramStringWellFormed += '"'; - } else { - //open wrap with double-quotes if no wrapper - if (keys[i][0] !== '"' && keys[i][0] !== "'") { - paramStringWellFormed += '"'; - - //this is to clean up vestiges from Pattern Lab PHP's escaping scheme. - //F.Y.I. Pattern Lab PHP would allow special characters like question - //marks in parameter keys so long as the key was unwrapped and the - //special character escaped with a backslash. In Node, we need to wrap - //those keys and unescape those characters. - keys[i] = keys[i].replace(/\\/g, ''); - } - - paramStringWellFormed += keys[i]; - - //close wrap with double-quotes if no wrapper - if ( - keys[i][keys[i].length - 1] !== '"' && - keys[i][keys[i].length - 1] !== "'" - ) { - paramStringWellFormed += '"'; - } - } - - //colon delimiter. - paramStringWellFormed += ':'; - - //values - //replace single-quote wrappers with double-quotes - if (values[i][0] === "'" && values[i][values[i].length - 1] === "'") { - paramStringWellFormed += '"'; - - //any enclosed double-quotes must be escaped - paramStringWellFormed += values[i] - .substring(1, values[i].length - 1) - .replace(/"/g, '\\"'); - paramStringWellFormed += '"'; - - //for everything else, just add the value however it's wrapped - } else { - paramStringWellFormed += values[i]; - } - - //comma delimiter - if (i < keys.length - 1) { - paramStringWellFormed += ','; - } - } - paramStringWellFormed += '}'; - - //unescape escaped unicode except for double-quotes - paramStringWellFormed = paramStringWellFormed.replace(/\\u0027/g, "'"); - paramStringWellFormed = paramStringWellFormed.replace(/\\u0058/g, ':'); - - return paramStringWellFormed; - } - - //compile this partial immeadiately, essentially consuming it. - function findparameters(pattern, patternlab) { - if (pattern.parameteredPartials && pattern.parameteredPartials.length > 0) { - logger.debug(`processing patternParameters for ${pattern.partialName}`); - - return pattern.parameteredPartials.reduce((previousPromise, pMatch) => { - return previousPromise - .then(() => { - logger.debug(`processing patternParameter ${pMatch}`); - - //find the partial's name and retrieve it - const partialName = pMatch.match(/([\w\-\.\/~]+)/g)[0]; - const partialPattern = jsonCopy( - getPartial( - partialName, - patternlab, - `partial pattern ${partialName}` - ) - ); - - //if we retrieved a pattern we should make sure that its extendedTemplate is reset. looks to fix #190 - if (!partialPattern.extendedTemplate) { - partialPattern.extendedTemplate = partialPattern.template; - } - - if (!pattern.extendedTemplate) { - pattern.extendedTemplate = pattern.template; - } - - logger.debug(`retrieved pattern ${partialName}`); - - //strip out the additional data, convert string to JSON. - const leftParen = pMatch.indexOf('('); - const rightParen = pMatch.lastIndexOf(')'); - const paramString = - '{' + pMatch.substring(leftParen + 1, rightParen) + '}'; - const paramStringWellFormed = paramToJson(paramString); - - let paramData = {}; - - try { - paramData = JSON.parse(paramStringWellFormed); - } catch (err) { - logger.warning( - `There was an error parsing JSON for ${pattern.relPath}` - ); - logger.warning(err); - } - - // resolve any pattern links that might be present - paramData = parseLink( - patternlab, - paramData, - pattern.patternPartial - ); - - // for each property in paramData - for (const prop in paramData) { - if (paramData.hasOwnProperty(prop)) { - // find it within partialPattern.extendedTemplate and replace its value - partialPattern.extendedTemplate = replaceParameter( - partialPattern.extendedTemplate, - prop, - paramData[prop] - ); - } - } - - //if partial has style modifier data, replace the styleModifier value - if (pattern.stylePartials && pattern.stylePartials.length > 0) { - style_modifier_hunter.consume_style_modifier( - partialPattern, - pMatch, - patternlab - ); - } - - // set pattern.extendedTemplate pMatch with replacedPartial - pattern.extendedTemplate = pattern.extendedTemplate.replace( - pMatch, - partialPattern.extendedTemplate - ); - - //todo: this no longer needs to be a promise - return Promise.resolve(); - }) - .catch(reason => { - console.log(reason); - logger.error(reason); - }); - }, Promise.resolve()); - } - logger.debug(`pattern has no partials ${pattern.patternPartial}`); - return Promise.resolve(); - } - - return { - find_parameters: function(pattern, patternlab) { - return findparameters(pattern, patternlab); - }, - }; -}; - -module.exports = parameter_hunter; diff --git a/packages/core/src/lib/parseAllLinks.js b/packages/core/src/lib/parseAllLinks.js index 894ad6f83..e69383bd7 100644 --- a/packages/core/src/lib/parseAllLinks.js +++ b/packages/core/src/lib/parseAllLinks.js @@ -4,7 +4,7 @@ const parseLink = require('./parseLink'); //look for pattern links included in data files. //these will be in the form of link.* WITHOUT {{}}, which would still be there from direct pattern inclusion -module.exports = function(patternlab) { +module.exports = function (patternlab) { //look for link.* such as link.pages-blog as a value patternlab.data = parseLink(patternlab, patternlab.data, 'data.json'); diff --git a/packages/core/src/lib/parseLink.js b/packages/core/src/lib/parseLink.js index d3d0c455e..be8ac61b5 100644 --- a/packages/core/src/lib/parseLink.js +++ b/packages/core/src/lib/parseLink.js @@ -5,9 +5,9 @@ const path = require('path'); const logger = require('./log'); const getPartial = require('./get'); -module.exports = function(patternlab, obj, key) { +module.exports = function (patternlab, obj, key) { //check for 'link.patternPartial' - const linkRE = /(?:'|")(link\.[A-z0-9-_]+)(?:'|")/g; + const linkRE = /(?:'|")(link\.[\w-]+)(?:'|")/g; //stringify the passed in object let dataObjAsString; @@ -20,45 +20,72 @@ module.exports = function(patternlab, obj, key) { const linkMatches = dataObjAsString.match(linkRE); if (linkMatches) { - for (let i = 0; i < linkMatches.length; i++) { - const dataLink = linkMatches[i]; + linkMatches.forEach((dataLink) => { if (dataLink && dataLink.split('.').length >= 2) { //get the partial the link refers to - const linkPatternPartial = dataLink - .split('.')[1] - .replace('"', '') - .replace("'", ''); - const pattern = getPartial(linkPatternPartial, patternlab); - if (pattern !== undefined) { - //get the full built link and replace it - let fullLink = patternlab.data.link[linkPatternPartial]; - if (fullLink) { - fullLink = path.normalize(fullLink).replace(/\\/g, '/'); + const linkPatternPartial = dataLink.split('.')[1].replace(/'|"/g, ''); + const rawLink = `link.${linkPatternPartial}`; + let replacement = null; - logger.debug( - `expanded data link from ${dataLink} to ${fullLink} inside ${key}` - ); + if (linkPatternPartial.match(/viewall\-.+\-all/)) { + // Reverse engineer viewall-group-all link (if there is a pattern with that + // group there will be a view all page for that group) + const partial = linkPatternPartial + .replace('viewall-', '') + .replace('-all', ''); + const pattern = patternlab.patterns.find( + (p) => p.patternGroup === partial + ); - //also make sure our global replace didn't mess up a protocol - fullLink = fullLink.replace(/:\//g, '://'); - dataObjAsString = dataObjAsString.replace( - 'link.' + linkPatternPartial, - fullLink - ); + if (pattern) { + replacement = `/patterns/${partial}/index.html`; } + } else if (linkPatternPartial.match(/viewall\-.+/)) { + // Reverse engineer viewall-group-subgroup link (if there is a pattern with that + // group and subgroup there will be a view all page for that group) + const partial = linkPatternPartial.replace('viewall-', ''); + const pattern = patternlab.patterns.find( + (p) => `${p.patternGroup}-${p.patternSubgroup}` === partial + ); + + if (pattern) { + replacement = `/patterns/${pattern.flatPatternPath}/index.html`; + } + } else { + // Just search for the pattern partial + const pattern = getPartial(linkPatternPartial, patternlab); + + if (pattern) { + // get the full built link and replace it + let fullLink = patternlab.data.link[linkPatternPartial]; + if (fullLink) { + fullLink = path.normalize(fullLink).replace(/\\/g, '/'); + + logger.debug( + `expanded data link from ${dataLink} to ${fullLink} inside ${key}` + ); + + // also make sure our global replace didn't mess up a protocol + replacement = fullLink.replace(/:\//g, '://'); + } + } + } + + if (replacement) { + dataObjAsString = dataObjAsString.replace(rawLink, replacement); } else { logger.warning(`pattern not found for ${dataLink} inside ${key}`); } } - } + }); } let dataObj; try { dataObj = JSON.parse(dataObjAsString); } catch (err) { - logger.warning(`There was an error parsing JSON for ${key}`); - logger.warning(err); + logger.error(`There was an error parsing JSON for ${key}`); + logger.error(err); } return dataObj; diff --git a/packages/core/src/lib/patternWrapClasses.js b/packages/core/src/lib/patternWrapClasses.js new file mode 100644 index 000000000..2810eef6b --- /dev/null +++ b/packages/core/src/lib/patternWrapClasses.js @@ -0,0 +1,45 @@ +/** + * get the classes from pattern markdown and/or json + * @param {PatternLab} patternlab + * @param {Pattern} pattern + * @return {string} + */ +function getPatternWrapClasses(patternlab, pattern) { + const { patternWrapClassesEnable, patternWrapClassesKey } = patternlab.config; + if ( + !patternWrapClassesEnable || + !patternWrapClassesKey || + patternWrapClassesKey.length === 0 + ) { + return ''; + } + + const classes = []; + patternWrapClassesKey.forEach((key) => { + const { allMarkdown, jsonFileData } = pattern; + + if (allMarkdown && allMarkdown[key]) { + classes.push(allMarkdown[key]); + } + + if (jsonFileData && jsonFileData[key]) { + classes.push(jsonFileData[key]); + } + }); + + return classes.join(' '); +} + +/** + * change pattern template and wrap with classes pattern wrapper + * @param {PatternLab} patternlab + * @param {Pattern} pattern + */ +function patternWrapClassesChangePatternTemplate(patternlab, pattern) { + const classes = getPatternWrapClasses(patternlab, pattern); + if (classes.length !== 0) { + pattern.patternPartialCode = `
${pattern.patternPartialCode}
`; + } +} + +module.exports = patternWrapClassesChangePatternTemplate; diff --git a/packages/core/src/lib/pattern_engines.js b/packages/core/src/lib/pattern_engines.js index cde010125..71d4da883 100644 --- a/packages/core/src/lib/pattern_engines.js +++ b/packages/core/src/lib/pattern_engines.js @@ -9,6 +9,8 @@ const engineMatcher = /^engine-(.*)$/; const logger = require('./log'); +const { resolvePackageFolder } = require('@pattern-lab/core/src/lib/resolver'); + const enginesDirectories = [ { displayName: 'the core', @@ -18,6 +20,10 @@ const enginesDirectories = [ displayName: 'the edition or test directory', path: path.join(process.cwd(), 'node_modules'), }, + { + displayName: 'the general node_modules directory', + path: path.resolve(resolvePackageFolder('@pattern-lab/core'), '..', '..'), + }, ]; /** @@ -56,6 +62,19 @@ function findEngineModulesInDirectory(dir) { return foundEngines; } +function findEnginesInConfig(config) { + if ('engines' in config) { + return config.engines; + } + logger.warning( + "Scanning the 'node_modules' folder for pattern engines is deprecated and will be removed in v7." + ); + logger.warning( + 'To configure your engines in patternlab-config.json, see https://patternlab.io/docs/editing-the-configuration-options/#heading-engines' + ); + return null; +} + // // PatternEngines: the main export of this module // @@ -77,53 +96,109 @@ const PatternEngines = Object.create({ * @param patternLabConfig * @memberof PatternEngines */ - loadAllEngines: function(patternLabConfig) { + loadAllEngines: function (patternLabConfig) { const self = this; - // Try to load engines! We scan for engines at each path specified above. This - // function is kind of a big deal. - enginesDirectories.forEach(function(engineDirectory) { - const enginesInThisDir = findEngineModulesInDirectory( - engineDirectory.path - ); + // Try to load engines! We load the engines configured in patternlab-config.json + const enginesInConfig = findEnginesInConfig(patternLabConfig); - logger.debug(`Loading engines from ${engineDirectory.displayName}...`); + if (enginesInConfig) { + // Quick fix until we've removed @pattern-lab/engine-mustache, starting with https://github.com/pattern-lab/patternlab-node/issues/1239 & https://github.com/pattern-lab/patternlab-node/pull/1455 + // @TODO: Remove after removing @pattern-lab/engine-mustache dependency + enginesInConfig.mustache = enginesInConfig.mustache || {}; + enginesInConfig.mustache.package = + enginesInConfig.mustache.package || '@pattern-lab/engine-mustache'; + enginesInConfig.mustache.extensions = + enginesInConfig.mustache.extensions || 'mustache'; - // find all engine-named things in this directory and try to load them, - // unless it's already been loaded. - enginesInThisDir.forEach(function(engineDiscovery) { + // Try loading each of the configured pattern engines + // eslint-disable-next-line guard-for-in + for (const name in enginesInConfig) { + const engineConfig = enginesInConfig[name]; let errorMessage; const successMessage = 'good to go'; try { // Give it a try! load 'er up. But not if we already have, - // of course. Also pass the pattern lab config object into + // of course. Also pass the Pattern Lab config object into // the engine's closure scope so it can know things about // things. - if (self[engineDiscovery.name]) { + if (self[name]) { throw new Error('already loaded, skipping.'); } - self[engineDiscovery.name] = require(engineDiscovery.modulePath); - if ( - typeof self[engineDiscovery.name].usePatternLabConfig === 'function' - ) { - self[engineDiscovery.name].usePatternLabConfig(patternLabConfig); - } - if (typeof self[engineDiscovery.name].spawnMeta === 'function') { - self[engineDiscovery.name].spawnMeta(patternLabConfig); + if ('package' in engineConfig) { + self[name] = require(engineConfig.package); + if (typeof self[name].usePatternLabConfig === 'function') { + self[name].usePatternLabConfig(patternLabConfig); + } + if (typeof self[name].spawnMeta === 'function') { + self[name].spawnMeta(patternLabConfig); + } + } else { + logger.warning( + `Engine ${name} not configured correctly. Please configure your engines in patternlab-config.json as documented in https://patternlab.io/docs/editing-the-configuration-options/#heading-engines` + ); } } catch (err) { errorMessage = err.message; } finally { // report on the status of the engine, one way or another! logger.info( - `Pattern Engine ${engineDiscovery.name}: ${ + `Pattern Engine ${name} / package ${engineConfig.package}: ${ errorMessage ? errorMessage : successMessage }` ); } + } + } else { + // Try to load engines! We scan for engines at each path specified above. This + // function is kind of a big deal. + enginesDirectories.forEach(function (engineDirectory) { + const enginesInThisDir = findEngineModulesInDirectory( + engineDirectory.path + ); + + `Loading engines from ${engineDirectory.displayName}: ${engineDirectory.path} ...`; + + // find all engine-named things in this directory and try to load them, + // unless it's already been loaded. + enginesInThisDir.forEach(function (engineDiscovery) { + let errorMessage; + const successMessage = 'good to go'; + + try { + // Give it a try! load 'er up. But not if we already have, + // of course. Also pass the Pattern Lab config object into + // the engine's closure scope so it can know things about + // things. + if (self[engineDiscovery.name]) { + throw new Error('already loaded, skipping.'); + } + self[engineDiscovery.name] = require(engineDiscovery.modulePath); + if ( + typeof self[engineDiscovery.name].usePatternLabConfig === + 'function' + ) { + self[engineDiscovery.name].usePatternLabConfig(patternLabConfig); + } + if (typeof self[engineDiscovery.name].spawnMeta === 'function') { + self[engineDiscovery.name].spawnMeta(patternLabConfig); + } + } catch (err) { + errorMessage = err.message; + } finally { + // report on the status of the engine, one way or another! + logger.info( + `Pattern Engine ${ + engineDiscovery.name + } by discovery (deprecated): ${ + errorMessage ? errorMessage : successMessage + }` + ); + } + }); }); - }); + } // Complain if for some reason we haven't loaded any engines. if (Object.keys(self).length === 0) { @@ -138,7 +213,7 @@ const PatternEngines = Object.create({ * @param pattern * @returns engine name matching pattern */ - getEngineNameForPattern: function(pattern) { + getEngineNameForPattern: function (pattern) { // avoid circular dependency by putting this in here. TODO: is this slow? const of = require('./object_factory'); if ( @@ -175,7 +250,7 @@ const PatternEngines = Object.create({ * @param pattern * @returns name of engine for pattern */ - getEngineForPattern: function(pattern) { + getEngineForPattern: function (pattern) { if (pattern.isPseudoPattern) { return this.getEngineForPattern(pattern.basePattern); } else { @@ -189,9 +264,9 @@ const PatternEngines = Object.create({ * @memberof PatternEngines * @returns Array all supported file extensions */ - getSupportedFileExtensions: function() { + getSupportedFileExtensions: function () { const engineNames = Object.keys(PatternEngines); - const allEnginesExtensions = engineNames.map(engineName => { + const allEnginesExtensions = engineNames.map((engineName) => { return PatternEngines[engineName].engineFileExtension; }); return [].concat.apply([], allEnginesExtensions); @@ -203,7 +278,7 @@ const PatternEngines = Object.create({ * @param fileExtension * @returns Boolean */ - isFileExtensionSupported: function(fileExtension) { + isFileExtensionSupported: function (fileExtension) { const supportedExtensions = PatternEngines.getSupportedFileExtensions(); return supportedExtensions.lastIndexOf(fileExtension) !== -1; }, @@ -214,7 +289,7 @@ const PatternEngines = Object.create({ * @param filename * @return boolean */ - isPseudoPatternJSON: function(filename) { + isPseudoPatternJSON: function (filename) { const extension = path.extname(filename); return extension === '.json' && filename.indexOf('~') > -1; }, @@ -229,7 +304,7 @@ const PatternEngines = Object.create({ * @param filename * @returns boolean */ - isPatternFile: function(filename) { + isPatternFile: function (filename) { // skip hidden patterns/files without a second thought const extension = path.extname(filename); if ( @@ -240,7 +315,8 @@ const PatternEngines = Object.create({ } // not a hidden pattern, let's dig deeper - const supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions(); + const supportedPatternFileExtensions = + PatternEngines.getSupportedFileExtensions(); return ( supportedPatternFileExtensions.lastIndexOf(extension) !== -1 || PatternEngines.isPseudoPatternJSON(filename) diff --git a/packages/core/src/lib/pattern_exporter.js b/packages/core/src/lib/pattern_exporter.js index 9bfc85ce3..221415bf8 100644 --- a/packages/core/src/lib/pattern_exporter.js +++ b/packages/core/src/lib/pattern_exporter.js @@ -1,8 +1,34 @@ 'use strict'; const fs = require('fs-extra'); +const path = require('path'); -const pattern_exporter = function() { +function exportSinglePattern(patternlab, pattern) { + const preserveDirStructure = + patternlab.config.patternExportPreserveDirectoryStructure; + let patternName = pattern.patternPartial; + let patternDir = patternlab.config.patternExportDirectory; + let patternCode = pattern.patternPartialCode; + let patternFileExtension = '.html'; + if (preserveDirStructure) { + // Extract the first part of the pattern partial as the directory in which + // it should go. + patternDir = path.join(patternDir, pattern.patternPartial.split('-')[0]); + patternName = pattern.patternPartial.split('-').slice(1).join('-'); + } + + if (patternlab.config.patternExportRaw) { + patternCode = pattern.extendedTemplate; + patternFileExtension = `.${patternlab.config.patternExtension}`; + } + + fs.outputFileSync( + path.join(patternDir, patternName) + patternFileExtension, + patternCode + ); +} + +const pattern_exporter = function () { /** * Exports all pattern's final HTML as defined in patternlab-config.json to desired location. * Originally created to help facilitate easier consumption by jekyll. @@ -13,25 +39,31 @@ const pattern_exporter = function() { function exportPatterns(patternlab) { //read the config export options const exportPartials = patternlab.config.patternExportPatternPartials; + const exportAll = patternlab.config.patternExportAll; + + if (exportAll) { + for (let i = 0; i < patternlab.patterns.length; i++) { + if (!patternlab.patterns[i].patternPartial.startsWith('-')) { + exportSinglePattern(patternlab, patternlab.patterns[i]); + } + } + + return; + } //find the chosen patterns to export for (let i = 0; i < exportPartials.length; i++) { for (let j = 0; j < patternlab.patterns.length; j++) { if (exportPartials[i] === patternlab.patterns[j].patternPartial) { //write matches to the desired location - fs.outputFileSync( - patternlab.config.patternExportDirectory + - patternlab.patterns[j].patternPartial + - '.html', - patternlab.patterns[j].patternPartialCode - ); + exportSinglePattern(patternlab, patternlab.patterns[j]); } } } } return { - export_patterns: function(patternlab) { + export_patterns: function (patternlab) { exportPatterns(patternlab); }, }; diff --git a/packages/core/src/lib/pattern_graph.js b/packages/core/src/lib/pattern_graph.js index 6ad17d012..a5320292d 100644 --- a/packages/core/src/lib/pattern_graph.js +++ b/packages/core/src/lib/pattern_graph.js @@ -35,7 +35,7 @@ const PATTERN_GRAPH_VERSION = 1; * @see PatternGraph#fromJson * @see #540 */ -const PatternGraph = function(graph, timestamp, version) { +const PatternGraph = function (graph, timestamp, version) { this.graph = graph || new Graph({ @@ -50,8 +50,8 @@ const PatternGraph = function(graph, timestamp, version) { this.version = version || PATTERN_GRAPH_VERSION; }; -// shorthand. Use relPath as it is always unique, even with subPatternType -const nodeName = p => (p instanceof Pattern ? p.relPath : p); +// shorthand. Use relPath as it is always unique, even with subPatternGroup +const nodeName = (p) => (p instanceof Pattern ? p.relPath : p); PatternGraph.prototype = { /** @@ -61,11 +61,11 @@ PatternGraph.prototype = { * * @see {@link https://github.com/pattern-lab/patternlab-node/issues/580|Issue #580} */ - sync: function() { + sync: function () { // Remove any patterns that are in the graph data, but that haven't been discovered when // walking all patterns iteratively - const nodesToRemove = this.nodes().filter(n => !this.patterns.has(n)); - nodesToRemove.forEach(n => this.remove(n)); + const nodesToRemove = this.nodes().filter((n) => !this.patterns.has(n)); + nodesToRemove.forEach((n) => this.remove(n)); return nodesToRemove; }, @@ -73,7 +73,7 @@ PatternGraph.prototype = { * Creates an independent copy of the graph where nodes and edges can be modified without * affecting the source. */ - clone: function() { + clone: function () { const json = graphlib.json.write(this.graph); const graph = graphlib.json.read(json); return new PatternGraph(graph, this.timestamp, this.version); @@ -85,7 +85,7 @@ PatternGraph.prototype = { * * @param {Pattern} pattern */ - add: function(pattern) { + add: function (pattern) { const n = nodeName(pattern); if (!this.patterns.has(n)) { this.graph.setNode(n, { @@ -96,7 +96,7 @@ PatternGraph.prototype = { } }, - remove: function(pattern) { + remove: function (pattern) { const n = nodeName(pattern); this.graph.removeNode(n); this.patterns.remove(n); @@ -106,8 +106,8 @@ PatternGraph.prototype = { * Removes nodes from this graph for which the given predicate function returns false. * @param {function} fn which takes a node name as argument */ - filter: function(fn) { - this.graph.nodes().forEach(n => { + filter: function (fn) { + this.graph.nodes().forEach((n) => { if (!fn(n)) { this.remove(n); } @@ -123,7 +123,7 @@ PatternGraph.prototype = { * * @throws {Error} If the pattern is unknown */ - link: function(patternFrom, patternTo) { + link: function (patternFrom, patternTo) { const nameFrom = nodeName(patternFrom); const nameTo = nodeName(patternTo); for (const name of [nameFrom, nameTo]) { @@ -141,7 +141,7 @@ PatternGraph.prototype = { * * @return {boolean} */ - hasLink: function(patternFrom, patternTo) { + hasLink: function (patternFrom, patternTo) { const nameFrom = nodeName(patternFrom); const nameTo = nodeName(patternTo); return this.graph.hasEdge(nameFrom, nameTo); @@ -157,8 +157,8 @@ PatternGraph.prototype = { * @return {Array} An Array of {@link Pattern}s in the order by which the changed patters must be * compiled. */ - compileOrder: function() { - const compileStateFilter = function(patterns, n) { + compileOrder: function () { + const compileStateFilter = function (patterns, n) { const node = patterns.get(n); return node.compileState !== CompileState.CLEAN; }; @@ -173,10 +173,10 @@ PatternGraph.prototype = { }); const nodes = this.graph.nodes(); - const changedNodes = nodes.filter(n => + const changedNodes = nodes.filter((n) => compileStateFilter(this.patterns, n) ); - this.nodes2patterns(changedNodes).forEach(pattern => { + this.nodes2patterns(changedNodes).forEach((pattern) => { const patternNode = nodeName(pattern); if (!compileGraph.hasNode(patternNode)) { compileGraph.setNode(patternNode); @@ -211,7 +211,7 @@ PatternGraph.prototype = { * @param fn A function that takes the currently viewed pattern and node data. Allows synching data * between patterns and node metadata. */ - applyReverse: function(pattern, fn) { + applyReverse: function (pattern, fn) { for (const p of this.lineageR(pattern)) { fn(p, pattern); this.applyReverse(p, fn); @@ -225,7 +225,7 @@ PatternGraph.prototype = { * * @return [null|Pattern] */ - node: function(pattern) { + node: function (pattern) { return this.graph.node(nodeName(pattern)); }, @@ -234,8 +234,8 @@ PatternGraph.prototype = { * @param nodes {Array} * @return {Array} An Array of Patterns */ - nodes2patterns: function(nodes) { - return nodes.map(n => this.patterns.get(n)); + nodes2patterns: function (nodes) { + return nodes.map((n) => this.patterns.get(n)); }, // TODO cache result in a Map[String, Array]? @@ -246,7 +246,7 @@ PatternGraph.prototype = { * @param pattern * @return {*|Array} */ - lineage: function(pattern) { + lineage: function (pattern) { const nodes = this.graph.successors(nodeName(pattern)); return this.nodes2patterns(nodes); }, @@ -256,7 +256,7 @@ PatternGraph.prototype = { * @param {Pattern} pattern * @return {*|Array} */ - lineageR: function(pattern) { + lineageR: function (pattern) { const nodes = this.graph.predecessors(nodeName(pattern)); return this.nodes2patterns(nodes); }, @@ -267,9 +267,9 @@ PatternGraph.prototype = { * * @see {@link PatternGraph.lineage(pattern)} */ - lineageIndex: function(pattern) { + lineageIndex: function (pattern) { const lineage = this.lineage(pattern); - return lineage.map(p => p.patternPartial); + return lineage.map((p) => p.patternPartial); }, /** @@ -280,16 +280,16 @@ PatternGraph.prototype = { * * @see {@link PatternGraph.lineageRIndex(pattern)} */ - lineageRIndex: function(pattern) { + lineageRIndex: function (pattern) { const lineageR = this.lineageR(pattern); - return lineageR.map(p => p.patternPartial); + return lineageR.map((p) => p.patternPartial); }, /** * Creates an object representing the graph and meta data. * @returns {{timestamp: number, graph}} */ - toJson: function() { + toJson: function () { return { version: this.version, timestamp: this.timestamp, @@ -300,14 +300,14 @@ PatternGraph.prototype = { /** * @return {Array} An array of all node names. */ - nodes: function() { + nodes: function () { return this.graph.nodes(); }, /** * Updates the version to the most recent one */ - upgradeVersion: function() { + upgradeVersion: function () { this.version = PATTERN_GRAPH_VERSION; }, }; @@ -317,7 +317,7 @@ PatternGraph.prototype = { * @param {int} [version=PATTERN_GRAPH_VERSION] * @return {PatternGraph} */ -PatternGraph.empty = function(version) { +PatternGraph.empty = function (version) { return new PatternGraph(null, 0, version || PATTERN_GRAPH_VERSION); }; @@ -326,7 +326,7 @@ PatternGraph.empty = function(version) { * @param {PatternGraph|Object} graphOrJson * @return {boolean} */ -PatternGraph.checkVersion = function(graphOrJson) { +PatternGraph.checkVersion = function (graphOrJson) { return graphOrJson.version === PATTERN_GRAPH_VERSION; }; @@ -346,7 +346,7 @@ function VersionMismatch(oldVersion) { * @param {object} o The JSON object to read from * @return {PatternGraph} */ -PatternGraph.fromJson = function(o) { +PatternGraph.fromJson = function (o) { if (!PatternGraph.checkVersion(o)) { throw new VersionMismatch(o.version); } @@ -360,7 +360,7 @@ PatternGraph.fromJson = function(o) { * @param {string} [fileName='dependencyGraph.json'] Name of the graph file * @return {string} */ -PatternGraph.resolveJsonGraphFile = function( +PatternGraph.resolveJsonGraphFile = function ( filePath = process.cwd(), fileName = 'dependencyGraph.json' ) { @@ -377,7 +377,7 @@ PatternGraph.resolveJsonGraphFile = function( * @see {@link PatternGraph.fromJson} * @see {@link PatternGraph.resolveJsonGraphFile} */ -PatternGraph.loadFromFile = function(filePath, fileName) { +PatternGraph.loadFromFile = function (filePath, fileName) { const jsonGraphFile = this.resolveJsonGraphFile(filePath, fileName); // File is fresh, so simply construct an empty graph in memory @@ -399,7 +399,7 @@ PatternGraph.loadFromFile = function(filePath, fileName) { * * @see {@link PatternGraph.resolveJsonGraphFile} */ -PatternGraph.storeToFile = function(patternlab) { +PatternGraph.storeToFile = function (patternlab) { if (process.env.PATTERNLAB_ENV === 'CI') { return; } @@ -413,7 +413,7 @@ PatternGraph.storeToFile = function(patternlab) { * @param patternlab @ @param {string} fileName Output filename */ -PatternGraph.exportToDot = function(patternlab, fileName) { +PatternGraph.exportToDot = function (patternlab, fileName) { const dotFile = this.resolveJsonGraphFile(undefined, fileName); const g = PatternGraphDot.generate(patternlab.graph); fs.outputFileSync(dotFile, g); diff --git a/packages/core/src/lib/pattern_graph_dot.js b/packages/core/src/lib/pattern_graph_dot.js index c2e865203..f4da40e18 100644 --- a/packages/core/src/lib/pattern_graph_dot.js +++ b/packages/core/src/lib/pattern_graph_dot.js @@ -23,7 +23,7 @@ function header() { * @param name * @return {string} */ -const niceKey = function(name) { +const niceKey = function (name) { return 'O' + name.replace('-', ''); }; @@ -84,7 +84,7 @@ const PatternGraphDot = {}; * @param patternGraph * @return {string} */ -PatternGraphDot.generate = function(patternGraph) { +PatternGraphDot.generate = function (patternGraph) { const g = patternGraph.graph; const patterns = patternGraph.patterns; const buckets = new Map(); @@ -98,20 +98,20 @@ PatternGraphDot.generate = function(patternGraph) { const colorMap = new Map(); let colIdx = 0; for (const p of patterns.partials.values()) { - if (p.isPseudoPattern || !p.patternType) { + if (p.isPseudoPattern || !p.patternGroup) { continue; } - let bucket = buckets.get(p.patternType); + let bucket = buckets.get(p.patternGroup); if (bucket) { bucket.push(p); } else { bucket = [p]; - colorMap.set(p.patternType, colors[colIdx++]); + colorMap.set(p.patternGroup, colors[colIdx++]); // Repeat if there are more categories colIdx = colIdx % colors.length; } - buckets.set(p.patternType, bucket); + buckets.set(p.patternGroup, bucket); } let res = header(); @@ -131,11 +131,11 @@ PatternGraphDot.generate = function(patternGraph) { foo: for (const edge of g.edges()) { const fromTo = patternGraph.nodes2patterns([edge.v, edge.w]); for (const pattern of fromTo) { - if (pattern.isPseudoPattern || !pattern.patternType) { + if (pattern.isPseudoPattern || !pattern.patternGroup) { continue foo; } } - const thisColor = colorMap.get(fromTo[0].patternType); + const thisColor = colorMap.get(fromTo[0].patternGroup); res.push(addEdge(fromTo[0], fromTo[1], thisColor)); } diff --git a/packages/core/src/lib/pattern_registry.js b/packages/core/src/lib/pattern_registry.js index 95145234c..041cb109e 100644 --- a/packages/core/src/lib/pattern_registry.js +++ b/packages/core/src/lib/pattern_registry.js @@ -4,7 +4,7 @@ * Allows lookups for patterns via a central registry. * @constructor */ -const PatternRegistry = function() { +const PatternRegistry = function () { this.key2pattern = new Map(); /** For lookups by {@link Pattern#partialKey} */ @@ -12,15 +12,15 @@ const PatternRegistry = function() { }; PatternRegistry.prototype = { - allPatterns: function() { + allPatterns: function () { return Array.from(this.key2pattern.values()); }, - has: function(name) { + has: function (name) { return this.key2pattern.has(name); }, - get: function(name) { + get: function (name) { return this.key2pattern.get(name); }, @@ -28,18 +28,18 @@ PatternRegistry.prototype = { * Adds the given pattern to the registry. If a pattern with the same key exists, it is replaced. * @param pattern {Pattern|*} */ - put: function(pattern) { + put: function (pattern) { const name = PatternRegistry.partialName(pattern); this.partials.set(name, pattern); const key = PatternRegistry.patternKey(pattern); this.key2pattern.set(key, pattern); }, - remove: function(name) { + remove: function (name) { this.key2pattern.delete(name); }, - getPartial: function(partialName) { + getPartial: function (partialName) { /* Code in here has been moved from getPartial() to prepare for some refactoring. There are a few advantages to this method: @@ -83,7 +83,7 @@ PatternRegistry.prototype = { }, }; -PatternRegistry.patternKey = function(pattern) { +PatternRegistry.patternKey = function (pattern) { return pattern.relPath; }; @@ -93,7 +93,7 @@ PatternRegistry.patternKey = function(pattern) { * @param pattern {Pattern} * @return {string} */ -PatternRegistry.partialName = function(pattern) { +PatternRegistry.partialName = function (pattern) { return pattern.patternPartial; }; diff --git a/packages/core/src/lib/patternlab.js b/packages/core/src/lib/patternlab.js index 2b8cc3d43..405da4fc9 100644 --- a/packages/core/src/lib/patternlab.js +++ b/packages/core/src/lib/patternlab.js @@ -47,13 +47,14 @@ module.exports = class PatternLab { // Load up engines please this.engines = patternEngines; this.engines.loadAllEngines(config); + this.isBusy = false; // // INITIALIZE EMPTY GLOBAL DATA STRUCTURES // this.data = {}; this.patterns = []; - this.subtypePatterns = {}; + this.subgroupPatterns = {}; this.partials = {}; // Cache the package.json in RAM @@ -64,6 +65,9 @@ module.exports = class PatternLab { // Make ye olde event emitter this.events = new PatternLabEventEmitter(); + this.hooks = {}; + this.hooks[events.PATTERNLAB_PATTERN_WRITE_END] = []; + // Make a place for the pattern graph to sit this.graph = null; @@ -107,9 +111,7 @@ module.exports = class PatternLab { if (typeof patternlab.config.paths.source.patternlabFiles === 'string') { logger.warning(''); logger.warning( - `Configuration key [paths.source.patternlabFiles] inside patternlab-config.json was found as the string '${ - patternlab.config.paths.source.patternlabFiles - }'` + `Configuration key [paths.source.patternlabFiles] inside patternlab-config.json was found as the string '${patternlab.config.paths.source.patternlabFiles}'` ); logger.warning( 'Since Pattern Lab Node Core 3.0.0 this key is an object. Suggest you update this key following this issue: https://github.com/pattern-lab/patternlab-node/issues/683.' @@ -213,10 +215,10 @@ module.exports = class PatternLab { } writePatternFiles(headHTML, pattern, footerHTML, outputBasePath) { - const nullFormatter = str => str; - const defaultFormatter = codeString => + const nullFormatter = (str) => str; + const defaultFormatter = (codeString) => cleanHtml(codeString, { indent_size: 2 }); - const makePath = type => + const makePath = (type) => path.join( this.config.paths.public.patterns, pattern.getPatternLink(this, type) @@ -256,7 +258,7 @@ module.exports = class PatternLab { ); //write the compiled template to the public patterns directory - outputFiles.forEach(outFile => + outputFiles.forEach((outFile) => fs.outputFileSync( path.join(process.cwd(), outputBasePath, outFile.path), outFile.content @@ -272,22 +274,22 @@ module.exports = class PatternLab { */ registerLogger(logLevel) { if (logLevel === undefined) { - logger.log.on('info', msg => console.info(msg)); - logger.log.on('warning', msg => console.info(msg)); - logger.log.on('error', msg => console.info(msg)); + logger.log.on('info', (msg) => console.info(msg)); + logger.log.on('warning', (msg) => console.info(msg)); + logger.log.on('error', (msg) => console.info(msg)); } else { if (logLevel === 'quiet') { return; } switch (logLevel) { case 'debug': - logger.log.on('debug', msg => console.info(msg)); + logger.log.on('debug', (msg) => console.info(msg)); case 'info': - logger.log.on('info', msg => console.info(msg)); + logger.log.on('info', (msg) => console.info(msg)); case 'warning': - logger.log.on('warning', msg => console.info(msg)); + logger.log.on('warning', (msg) => console.info(msg)); case 'error': - logger.log.on('error', msg => console.info(msg)); + logger.log.on('error', (msg) => console.info(msg)); } } } @@ -305,7 +307,12 @@ module.exports = class PatternLab { // dive once to perform iterative populating of patternlab object processAllPatternsIterative(patterns_dir) { const self = this; - const promiseAllPatternFiles = new Promise(function(resolve) { + + // before updating the patterns has to be reset, otherwise + // deleted pattern would still be present in the patterns array + this.patterns = []; + + const promiseAllPatternFiles = new Promise(function (resolve) { dive( patterns_dir, (err, file) => { @@ -331,11 +338,11 @@ module.exports = class PatternLab { }); return promiseAllPatternFiles.then(() => { return Promise.all( - this.patterns.map(pattern => { + this.patterns.map((pattern) => { return processIterative(pattern, self); }) ).then(() => { - // patterns sorted by name so the patterntype and patternsubtype is adhered to for menu building + // patterns sorted by name so the patternGroup and patternSubgroup is adhered to for menu building this.patterns.sort((pattern1, pattern2) => pattern1.name.localeCompare(pattern2.name) ); @@ -346,7 +353,7 @@ module.exports = class PatternLab { processAllPatternsRecursive(patterns_dir) { const self = this; - const promiseAllPatternFiles = new Promise(function(resolve) { + const promiseAllPatternFiles = new Promise(function (resolve) { dive( patterns_dir, (err, file) => { diff --git a/packages/core/src/lib/plugin_manager.js b/packages/core/src/lib/plugin_manager.js index a3a37ab58..f79307beb 100644 --- a/packages/core/src/lib/plugin_manager.js +++ b/packages/core/src/lib/plugin_manager.js @@ -1,65 +1,39 @@ 'use strict'; -const plugin_manager = function() { - const path = require('path'); - const findModules = require('./findModules'); - - const _ = require('lodash'); - +const plugin_manager = function () { const logger = require('./log'); - const pluginMatcher = /^plugin-(.*)$/; - - /** - * Loads a plugin - * - * @param modulePath {string} the path to the plugin - * @return {object} the loaded plugin - */ - function loadPlugin(modulePath) { - return require(modulePath); - } - - /** - * Given a path: return the plugin name if the path points to a valid plugin - * module directory, or false if it doesn't. - * @param filePath - * @returns Plugin name if exists or FALSE - */ - function isPlugin(filePath) { - const baseName = path.basename(filePath); - const pluginMatch = baseName.match(pluginMatcher); - - if (pluginMatch) { - return pluginMatch[1]; - } - return false; - } - /** * Looks for installed plugins, loads them, and invokes them * @param {object} patternlab */ function initializePlugins(patternlab) { - const nodeModulesPath = path.join(process.cwd(), 'node_modules'); - const foundPlugins = findModules(nodeModulesPath, plugin_manager.is_plugin); - foundPlugins.forEach(plugin => { - logger.info(`Found plugin: plugin-${plugin.name}`); + const foundPlugins = Object.keys(patternlab.config.plugins || {}); + foundPlugins.forEach((plugin) => { + logger.info(`Found plugin: ${plugin}`); logger.info(`Attempting to load and initialize plugin.`); - const pluginModule = plugin_manager.load_plugin(plugin.modulePath); + const pluginModule = require(plugin); pluginModule(patternlab); }); } + async function raiseEvent(patternlab, eventName, args) { + patternlab.events.emit(eventName, args); + await (async function () { + const hookHandlers = (patternlab.hooks[eventName] || []).map((h) => + h(args) + ); + + await Promise.all(hookHandlers); + })(); + } + return { - intialize_plugins: patternlab => { + intialize_plugins: (patternlab) => { initializePlugins(patternlab); }, - load_plugin: modulePath => { - return loadPlugin(modulePath); - }, - is_plugin: filePath => { - return isPlugin(filePath); + raiseEvent: async (patternlab, eventName, ...args) => { + await raiseEvent(patternlab, eventName, args); }, }; }; diff --git a/packages/core/src/lib/processIterative.js b/packages/core/src/lib/processIterative.js index 1c65c85ca..8f57f7dff 100644 --- a/packages/core/src/lib/processIterative.js +++ b/packages/core/src/lib/processIterative.js @@ -5,15 +5,12 @@ const pph = require('./pseudopattern_hunter'); // This is now solely for analysis; loading of the pattern file is // above, in loadPatternIterative() -module.exports = function(pattern, patternlab) { +module.exports = function (pattern, patternlab) { //look for a pseudo pattern by checking if there is a file //containing same name, with ~ in it, ending in .json return pph .find_pseudopatterns(pattern, patternlab) .then(() => { - //find any stylemodifiers that may be in the current pattern - pattern.stylePartials = pattern.findPartialsWithStyleModifiers(); - //find any pattern parameters that may be in the current pattern pattern.parameteredPartials = pattern.findPartialsWithPatternParameters(); return Promise.resolve(pattern); diff --git a/packages/core/src/lib/processMetaPattern.js b/packages/core/src/lib/processMetaPattern.js index 66ca99586..dea8fbe70 100644 --- a/packages/core/src/lib/processMetaPattern.js +++ b/packages/core/src/lib/processMetaPattern.js @@ -9,7 +9,7 @@ const logger = require('./log'); //this may be mocked in unit tests, so let it be overridden let fs = require('fs-extra'); // eslint-disable-line -module.exports = function(fileName, metaType, patternlab) { +module.exports = function (fileName, metaType, patternlab) { const metaPath = path.resolve(patternlab.config.paths.source.meta, fileName); const metaPattern = new Pattern(metaPath, null, patternlab); metaPattern.template = fs.readFileSync(metaPath, 'utf8'); @@ -19,11 +19,9 @@ module.exports = function(fileName, metaType, patternlab) { .then(() => { patternlab[metaType] = metaPattern; }) - .catch(reason => { + .catch((reason) => { logger.warning( - `Could not find the user-editable template ${fileName}, currently configured to be at ${ - patternlab.config.paths.source.meta - }. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.` + `Could not find the user-editable template ${fileName}, currently configured to be at ${patternlab.config.paths.source.meta}. Your configured path may be incorrect (check paths.source.meta in your config file), the file may have been deleted, or it may have been left in the wrong place during a migration or update.` ); logger.warning(reason); }); diff --git a/packages/core/src/lib/processRecursive.js b/packages/core/src/lib/processRecursive.js index 97c4ac560..3c541c85c 100644 --- a/packages/core/src/lib/processRecursive.js +++ b/packages/core/src/lib/processRecursive.js @@ -4,7 +4,7 @@ const logger = require('./log'); const decompose = require('./decompose'); const getPartial = require('./get'); -module.exports = function(file, patternlab) { +module.exports = function (file, patternlab) { //find current pattern in patternlab object using file as a partial const currentPattern = getPartial(file, patternlab, false); @@ -19,7 +19,7 @@ module.exports = function(file, patternlab) { } //call our helper method to actually unravel the pattern with any partials - return decompose(currentPattern, patternlab).catch(reason => { + return decompose(currentPattern, patternlab).catch((reason) => { console.log(reason); logger.error(reason); }); diff --git a/packages/core/src/lib/pseudopattern_hunter.js b/packages/core/src/lib/pseudopattern_hunter.js index c57379405..28d4f3e1a 100644 --- a/packages/core/src/lib/pseudopattern_hunter.js +++ b/packages/core/src/lib/pseudopattern_hunter.js @@ -13,10 +13,11 @@ const readDocumentation = require('./readDocumentation'); const lineage_hunter = new lh(); const changes_hunter = new ch(); const yaml = require('js-yaml'); +const dataMerger = require('./dataMerger'); -const pseudopattern_hunter = function() {}; +const pseudopattern_hunter = function () {}; -pseudopattern_hunter.prototype.find_pseudopatterns = function( +pseudopattern_hunter.prototype.find_pseudopatterns = function ( currentPattern, patternlab ) { @@ -49,32 +50,27 @@ pseudopattern_hunter.prototype.find_pseudopatterns = function( paths.source.patterns, pseudoPatterns[i] ); - variantFileData = yaml.safeLoad( + variantFileData = yaml.load( fs.readFileSync(variantFileFullPath, 'utf8') ); } catch (err) { - logger.warning( - `There was an error parsing pseudopattern JSON for ${ - currentPattern.relPath - }` + logger.error( + `There was an error parsing pseudopattern JSON for ${currentPattern.relPath}` ); - logger.warning(err); + logger.error(err); } //extend any existing data with variant data - variantFileData = _.merge( - {}, + variantFileData = dataMerger( currentPattern.jsonFileData, - variantFileData + variantFileData, + patternlab.config ); const variantName = pseudoPatterns[i] .substring(pseudoPatterns[i].indexOf('~') + 1) .split('.')[0]; - const variantExtension = pseudoPatterns[i] - .split('.') - .slice(-1) - .pop(); + const variantExtension = pseudoPatterns[i].split('.').slice(-1).pop(); const variantFilePath = path.join( currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.' + variantExtension @@ -90,7 +86,6 @@ pseudopattern_hunter.prototype.find_pseudopatterns = function( extendedTemplate: currentPattern.extendedTemplate, isPseudoPattern: true, basePattern: currentPattern, - stylePartials: currentPattern.stylePartials, parameteredPartials: currentPattern.parameteredPartials, // Only regular patterns are discovered during iterative walks @@ -102,13 +97,15 @@ pseudopattern_hunter.prototype.find_pseudopatterns = function( }, patternlab ); + patternVariant.order = _.clone(currentPattern.order); + patternVariant.hidden = _.clone(currentPattern.hidden); changes_hunter.checkBuildState(patternVariant, patternlab); patternlab.graph.add(patternVariant); patternlab.graph.link(patternVariant, currentPattern); //process the companion markdown file if it exists - readDocumentation(patternVariant, patternlab); + readDocumentation(patternVariant, patternlab, true); //find pattern lineage lineage_hunter.find_lineage(patternVariant, patternlab); diff --git a/packages/core/src/lib/readDocumentation.js b/packages/core/src/lib/readDocumentation.js index d22c6fa88..1159a0347 100644 --- a/packages/core/src/lib/readDocumentation.js +++ b/packages/core/src/lib/readDocumentation.js @@ -1,7 +1,8 @@ 'use strict'; -const path = require('path'); const _ = require('lodash'); +const path = require('path'); +const fs = require('fs-extra'); const ch = require('./changes_hunter'); const logger = require('./log'); @@ -10,14 +11,15 @@ const mp = require('./markdown_parser'); const changes_hunter = new ch(); const markdown_parser = new mp(); -let fs = require('fs-extra'); //eslint-disable-line prefer-const +const FILE_EXTENSION = '.md'; +const GROUP_DOC_PREFIX = '_'; -module.exports = function(pattern, patternlab) { +module.exports = function (pattern, patternlab, isVariant) { try { const markdownFileName = path.resolve( patternlab.config.paths.source.patterns, pattern.subdir, - pattern.fileName + '.md' + pattern.fileName + FILE_EXTENSION ); changes_hunter.checkLastModified(pattern, markdownFileName); @@ -37,9 +39,9 @@ module.exports = function(pattern, patternlab) { pattern.patternState = markdownObject.state; } if (markdownObject.order) { - pattern.order = markdownObject.order; + pattern[isVariant ? 'variantOrder' : 'order'] = markdownObject.order; } - if (markdownObject.hidden) { + if (markdownObject.hasOwnProperty('hidden')) { pattern.hidden = markdownObject.hidden; } if (markdownObject.excludeFromStyleguide) { @@ -54,6 +56,14 @@ module.exports = function(pattern, patternlab) { if (markdownObject.links) { pattern.links = markdownObject.links; } + + if ( + markdownObject.hasOwnProperty('deeplyNested') && + markdownObject.deeplyNested + ) { + // Reset to pattern without own pattern-directory + pattern.promoteFromDirectoryToFlatPattern(patternlab); + } } else { logger.warning(`error processing markdown for ${pattern.patternPartial}`); } @@ -63,12 +73,83 @@ module.exports = function(pattern, patternlab) { } catch (err) { // do nothing when file not found if (err.code !== 'ENOENT') { - logger.warning( - `'there was an error setting pattern keys after markdown parsing of the companion file for pattern ${ - pattern.patternPartial - }` + logger.error( + `There was an error setting pattern keys after markdown parsing of the companion file for pattern ${pattern.patternPartial}${FILE_EXTENSION}` + ); + logger.error(err); + } + } + + // Read Documentation for Pattern-Group + // Use this approach, since pattern lab is a pattern driven software + if (pattern.patternGroup) { + const groupRelPath = pattern.relPath.split(path.sep); + try { + const markdownFileNameGroup = path.resolve( + patternlab.config.paths.source.patterns, + groupRelPath[0] || pattern.subdir, + GROUP_DOC_PREFIX + pattern.patternGroup + FILE_EXTENSION + ); + const markdownFileContentsGroup = fs.readFileSync( + markdownFileNameGroup, + 'utf8' + ); + const markdownObjectGroup = markdown_parser.parse( + markdownFileContentsGroup + ); + + if (!_.isEmpty(markdownObjectGroup)) { + pattern.patternGroupData = markdownObjectGroup; + } + } catch (err) { + // do nothing when file not found + if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') { + logger.warning( + `There was an error setting pattern group data after markdown parsing for ${path.join( + patternlab.config.paths.source.patterns, + groupRelPath[0] || pattern.subdir, + GROUP_DOC_PREFIX + pattern.patternGroup + FILE_EXTENSION + )}` + ); + logger.warning(err); + } + } + } + + // Read Documentation for Pattern-Subgroup + if (pattern.patternSubgroup) { + const subgroupRelPath = pattern.relPath.split(path.sep); + try { + const markdownFileNameSubgroup = path.resolve( + patternlab.config.paths.source.patterns, + subgroupRelPath[0], + subgroupRelPath[1], + GROUP_DOC_PREFIX + pattern.patternSubgroup + FILE_EXTENSION ); - logger.warning(err); + const markdownFileContentsSubgroup = fs.readFileSync( + markdownFileNameSubgroup, + 'utf8' + ); + const markdownObjectSubgroup = markdown_parser.parse( + markdownFileContentsSubgroup + ); + + if (!_.isEmpty(markdownObjectSubgroup)) { + pattern.patternSubgroupData = markdownObjectSubgroup; + } + } catch (err) { + // do nothing when file not found + if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') { + logger.warning( + `There was an error setting pattern subgroup data after markdown parsing for ${path.join( + patternlab.config.paths.source.patterns, + subgroupRelPath[0], + subgroupRelPath[1], + GROUP_DOC_PREFIX + pattern.patternSubgroup + FILE_EXTENSION + )}` + ); + logger.warning(err); + } } } }; diff --git a/packages/core/src/lib/render.js b/packages/core/src/lib/render.js index 3ba1f2589..b73d5369f 100644 --- a/packages/core/src/lib/render.js +++ b/packages/core/src/lib/render.js @@ -2,7 +2,7 @@ const logger = require('./log'); -module.exports = function(pattern, data, partials) { +module.exports = function (pattern, data, partials) { logger.debug( `render: ${ pattern.patternPartial !== '-.' diff --git a/packages/core/src/lib/replaceParameter.js b/packages/core/src/lib/replaceParameter.js index 7b0cd6734..b045b58b2 100644 --- a/packages/core/src/lib/replaceParameter.js +++ b/packages/core/src/lib/replaceParameter.js @@ -2,7 +2,7 @@ const logger = require('./log'); -module.exports = function(template, prop, data) { +module.exports = function (template, prop, data) { let t = template; const valueRE = new RegExp(`{{{?\\s*[${prop}]+\\s*}?}}`); diff --git a/packages/core/src/lib/resolver.js b/packages/core/src/lib/resolver.js new file mode 100644 index 000000000..d70961413 --- /dev/null +++ b/packages/core/src/lib/resolver.js @@ -0,0 +1,53 @@ +'use strict'; + +const path = require('path'); + +/** + * @func resolvePackageLocations + * Resolves all possible package locations + */ +const resolvePackageLocations = () => { + let lookupPath = path.resolve(process.env.projectDir); + const paths = [lookupPath]; + while (path.dirname(lookupPath) !== lookupPath) { + lookupPath = path.join(lookupPath, '../'); + paths.push(lookupPath); + } + return paths; +}; + +/** + * @func resolveFileInPackage + * Resolves a file inside a package + */ +const resolveFileInPackage = (packageName, ...pathElements) => { + if (process.env.projectDir) { + return require.resolve(path.join(packageName, ...pathElements), { + paths: resolvePackageLocations(), + }); + } else { + return require.resolve(path.join(packageName, ...pathElements)); + } +}; + +/** + * @func resolvePackageFolder + * Resolves the location of a package on disc + */ +const resolvePackageFolder = (packageName) => { + return path.dirname(resolveFileInPackage(packageName, 'package.json')); +}; + +/** + * @func resolveDirInPackage + * Resolves a file inside a package + */ +const resolveDirInPackage = (packageName, ...pathElements) => { + return path.join(resolvePackageFolder(packageName), ...pathElements); +}; + +module.exports = { + resolveFileInPackage, + resolveDirInPackage, + resolvePackageFolder, +}; diff --git a/packages/core/src/lib/server.js b/packages/core/src/lib/server.js index 7b5a9cecd..58bef01a4 100644 --- a/packages/core/src/lib/server.js +++ b/packages/core/src/lib/server.js @@ -6,7 +6,7 @@ const liveServer = require('@pattern-lab/live-server'); const events = require('./events'); const logger = require('./log'); -const server = patternlab => { +const server = (patternlab) => { const _module = { serve: () => { let serverReady = false; @@ -20,7 +20,7 @@ const server = patternlab => { port: 3000, }; - const servers = Object.keys(patternlab.uikits).map(kit => { + const servers = Object.keys(patternlab.uikits).map((kit) => { const uikit = patternlab.uikits[kit]; defaults.root = path.resolve( path.join( @@ -36,6 +36,30 @@ const server = patternlab => { patternlab.config.paths.public.root ) ); + defaults.assets = [ + path.resolve( + path.join( + process.cwd(), + patternlab.config.paths.source.js, + '**', + '*.js' // prevent preprocessors like typescript from reloading + ) + ), + path.resolve( + path.join(process.cwd(), patternlab.config.paths.source.images) + ), + path.resolve( + path.join(process.cwd(), patternlab.config.paths.source.fonts) + ), + path.resolve( + path.join( + process.cwd(), + patternlab.config.paths.source.css, + '**', + '*.css' // prevent preprocessors from reloading + ) + ), + ]; // allow for overrides should they exist inside patternlab-config.json const liveServerConfig = Object.assign( @@ -63,9 +87,9 @@ const server = patternlab => { setTimeout(() => { try { liveServer.start(liveServerConfig); - resolveMsg = `Pattern Lab is being served from http://127.0.0.1:${ - liveServerConfig.port - }`; + resolveMsg = `Pattern Lab is being served from ${ + liveServerConfig.https ? 'https' : 'http' + }://127.0.0.1:${liveServerConfig.port}`; logger.info(resolveMsg); } catch (e) { const err = `Pattern Lab serve failed to start: ${e}`; @@ -82,7 +106,7 @@ const server = patternlab => { return Promise.all(servers); }, - reload: data => { + reload: (data) => { const _data = data || { file: '', action: '', diff --git a/packages/core/src/lib/starterkit_manager.js b/packages/core/src/lib/starterkit_manager.js index c00b33bbe..737aadd9a 100644 --- a/packages/core/src/lib/starterkit_manager.js +++ b/packages/core/src/lib/starterkit_manager.js @@ -1,6 +1,6 @@ 'use strict'; -const starterkit_manager = function(config) { +const starterkit_manager = function (config) { const path = require('path'); const fetch = require('node-fetch'); const fs = require('fs-extra'); @@ -29,7 +29,7 @@ const starterkit_manager = function(config) { kitDirStats = fs.statSync(kitPath); } catch (ex) { logger.warning( - `${starterkitName} not found, use npm to install it first.` + `${starterkitName} not found, use npm or another package manager to install it first.` ); logger.warning(`${starterkitName} not loaded.`); return; @@ -38,16 +38,12 @@ const starterkit_manager = function(config) { if (kitPathDirExists) { if (clean) { logger.info( - `Deleting contents of ${ - paths.source.root - } prior to starterkit load.` + `Deleting contents of ${paths.source.root} prior to starterkit load.` ); fs.emptyDirSync(paths.source.root); } else { logger.info( - `Overwriting contents of ${ - paths.source.root - } during starterkit load.` + `Overwriting contents of ${paths.source.root} during starterkit load.` ); } @@ -82,7 +78,7 @@ const starterkit_manager = function(config) { }, } ) - .then(function(res) { + .then(function (res) { const contentType = res.headers.get('content-type'); if (contentType && contentType.indexOf('application/json') === -1) { throw new TypeError( @@ -91,15 +87,15 @@ const starterkit_manager = function(config) { } return res.json(); }) - .then(function(json) { + .then(function (json) { if (!json.items || !Array.isArray(json.items)) { return false; } - return json.items.map(function(repo) { + return json.items.map(function (repo) { return { name: repo.name, url: repo.html_url }; }); }) - .catch(function(err) { + .catch(function (err) { logger.error(err); return false; }); @@ -115,27 +111,29 @@ const starterkit_manager = function(config) { //TODO review for deletion or convert callers to use findModules() function detectStarterKits() { const node_modules_path = path.join(process.cwd(), 'node_modules'); - const npm_modules = fs.readdirSync(node_modules_path).filter(function(dir) { - const module_path = path.join(process.cwd(), 'node_modules', dir); - return ( - fs.statSync(module_path).isDirectory() && - dir.indexOf('starterkit-') === 0 - ); - }); + const npm_modules = fs + .readdirSync(node_modules_path) + .filter(function (dir) { + const module_path = path.join(process.cwd(), 'node_modules', dir); + return ( + fs.statSync(module_path).isDirectory() && + dir.indexOf('starterkit-') === 0 + ); + }); return npm_modules; } return { - load_starterkit: function(starterkitName, clean) { + load_starterkit: function (starterkitName, clean) { loadStarterKit(starterkitName, clean); }, - list_starterkits: function() { + list_starterkits: function () { return listStarterkits(); }, - pack_starterkit: function() { + pack_starterkit: function () { packStarterkit(); }, - detect_starterkits: function() { + detect_starterkits: function () { return detectStarterKits(); }, }; diff --git a/packages/core/src/lib/style_modifier_hunter.js b/packages/core/src/lib/style_modifier_hunter.js deleted file mode 100644 index 13a7ff2d1..000000000 --- a/packages/core/src/lib/style_modifier_hunter.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -const logger = require('./log'); - -const style_modifier_hunter = function() { - /** - * Modifies a patterns partial with any styleModifiers found on the supplied partial - * - * @param pattern {object} the pattern to extend - * @param partial {string} partial containing styleModifiers - * @param patternlab {object} the patternlab instance - */ - function consumestylemodifier(pattern, partial, patternlab) { - //extract the classname from the stylemodifier which comes in the format of :className - let styleModifier = partial.match(/:([\w\-_|])+/g) - ? partial.match(/:([\w\-_|])+/g)[0].slice(1) - : null; - - if (styleModifier) { - //replace the special character pipe | used to separate multiple classes with a space - styleModifier = styleModifier.replace(/\|/g, ' '); - - logger.debug( - `Found partial styleModifier within pattern ${pattern.patternPartial}` - ); - - //replace the stylemodifier placeholder with the class name - pattern.extendedTemplate = pattern.extendedTemplate.replace( - /{{[ ]?styleModifier[ ]?}}/i, - styleModifier - ); - - //update the extendedTemplate in the partials object in case this pattern is consumed later - patternlab.partials[pattern.patternPartial] = pattern.extendedTemplate; - } - } - - return { - consume_style_modifier: function(pattern, partial, patternlab) { - consumestylemodifier(pattern, partial, patternlab); - }, - }; -}; - -module.exports = style_modifier_hunter; diff --git a/packages/core/src/lib/ui_builder.js b/packages/core/src/lib/ui_builder.js index 96229e08c..8b3d7de3a 100644 --- a/packages/core/src/lib/ui_builder.js +++ b/packages/core/src/lib/ui_builder.js @@ -3,18 +3,17 @@ const path = require('path'); const _ = require('lodash'); -const of = require('./object_factory'); -const Pattern = of.Pattern; +const Pattern = require('./object_factory').Pattern; const logger = require('./log'); const uikitExcludePattern = require('./uikitExcludePattern'); -//these are mocked in unit tests, so let them be overridden +// these are mocked in unit tests, so let them be overridden let render = require('./render'); //eslint-disable-line prefer-const let fs = require('fs-extra'); //eslint-disable-line prefer-const let buildFooter = require('./buildFooter'); //eslint-disable-line prefer-const let exportData = require('./exportData'); //eslint-disable-line prefer-const -const ui_builder = function() { +const ui_builder = function () { /** * Registers the pattern to the patternPaths object for the appropriate patternGroup and basename * patternGroup + patternBaseName are what comprise the patternPartial (atoms-colors) @@ -26,7 +25,7 @@ const ui_builder = function() { patternlab.patternPaths[pattern.patternGroup] = {}; } - //only add real patterns + // only add real patterns if (pattern.isPattern && !pattern.isDocPattern) { patternlab.patternPaths[pattern.patternGroup][pattern.patternBaseName] = pattern.name; @@ -34,7 +33,7 @@ const ui_builder = function() { } /** - * Registers the pattern with the viewAllPaths object for the appropriate patternGroup and patternSubGroup + * Registers the pattern with the viewAllPaths object for the appropriate patternGroup and patternSubgroup * @param patternlab - global data store * @param pattern - the pattern to add */ @@ -44,20 +43,18 @@ const ui_builder = function() { } if ( - !patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubGroup] + !patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubgroup] && + pattern.patternSubgroup ) { + // note these retain any number prefixes if present, because these paths match the filesystem patternlab.viewAllPaths[pattern.patternGroup][ - pattern.patternSubGroup - ] = {}; + pattern.patternSubgroup + ] = `${pattern.patternGroup}-${pattern.patternSubgroup}`; } - //note these retain any number prefixes if present, because these paths match the filesystem - patternlab.viewAllPaths[pattern.patternGroup][pattern.patternSubGroup] = - pattern.patternType + '-' + pattern.patternSubType; - - //add all if it does not exist yet + // add all if it does not exist yet if (!patternlab.viewAllPaths[pattern.patternGroup].all) { - patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternType; + patternlab.viewAllPaths[pattern.patternGroup].all = pattern.patternGroup; } } @@ -75,63 +72,57 @@ const ui_builder = function() { isOmitted = uikitExcludePattern(pattern, uikit); if (isOmitted) { logger.info( - `Omitting ${ - pattern.patternPartial - } from styleguide patterns because its pattern state or tag is excluded within ${ - uikit.name - }.` + `Omitting ${pattern.patternPartial} from styleguide patterns because its pattern state or tag is excluded within ${uikit.name}.` ); return true; } - // skip underscore-prefixed files - isOmitted = pattern.isPattern && pattern.fileName.charAt(0) === '_'; + // skip marked as hidden patterns + isOmitted = + (pattern.isPattern && pattern.hidden) || + // TODO: Remove next line when removing support & deprecation waring for underscore prefix hiding + (pattern.isPattern && pattern.fileName.charAt(0) === '_'); if (isOmitted) { logger.info( - `Omitting ${ - pattern.patternPartial - } from styleguide patterns because it has an underscore suffix.` + `Omitting ${pattern.patternPartial} from styleguide patterns because it is marked as hidden within it's documentation.` ); return true; } - //this is meant to be a homepage that is not present anywhere else + // this is meant to be a homepage that is not present anywhere else isOmitted = pattern.patternPartial === patternlab.config.defaultPattern; if (isOmitted) { logger.info( - `Omitting ${ - pattern.patternPartial - } from styleguide patterns because it is defined as a defaultPattern.` + `Omitting ${pattern.patternPartial} from styleguide patterns because it is defined as a defaultPattern.` ); patternlab.defaultPattern = pattern; return true; } - //this pattern is contained with a directory prefixed with an underscore (a handy way to hide whole directories from the nav + // this pattern is contained with a directory documented as hidden (a handy way to hide whole directories from the nav isOmitted = + (pattern.patternGroupData && pattern.patternGroupData.hidden) || + (pattern.patternSubgroupData && pattern.patternSubgroupData.hidden) || + // TODO: Remove next two lines when removing support & deprecation waring for underscore prefix hiding pattern.relPath.charAt(0) === '_' || pattern.relPath.indexOf(path.sep + '_') > -1; if (isOmitted) { logger.info( - `Omitting ${ - pattern.patternPartial - } from styleguide patterns because its contained within an underscored directory.` + `Omitting ${pattern.patternPartial} from styleguide patterns because its contained within an hidden directory.` ); return true; } - //this pattern is a head or foot pattern + // this pattern is a head or foot pattern isOmitted = pattern.isMetaPattern; if (isOmitted) { logger.info( - `Omitting ${ - pattern.patternPartial - } from styleguide patterns because its a meta pattern.` + `Omitting ${pattern.patternPartial} from styleguide patterns because its a meta pattern.` ); return true; } - //yay, let's include this on the front end + // yay, let's include this on the front end return isOmitted; } @@ -139,203 +130,196 @@ const ui_builder = function() { * For the given pattern, find or construct the view-all pattern block for the group * @param pattern - the pattern to derive our documentation pattern from * @param patternlab - global data store - * @param isSubtypePattern - whether or not this is a subtypePattern or a typePattern (typePatterns not supported yet) + * @param isSubgroupPattern - whether or not this is a subgroupPattern or a typePattern (groupedPatterns not supported yet) * @returns the found or created pattern object */ - function injectDocumentationBlock(pattern, patternlab, isSubtypePattern) { - //first see if loadPattern processed one already - let docPattern = - patternlab.subtypePatterns[ - pattern.patternGroup + - (isSubtypePattern ? '-' + pattern.patternSubGroup : '') - ]; - if (docPattern) { - docPattern.isDocPattern = true; - docPattern.order = -Number.MAX_SAFE_INTEGER; - return docPattern; - } - - //if not, create one now - docPattern = new Pattern.createEmpty( + function injectDocumentationBlock(pattern, patternlab, isSubgroupPattern) { + return new Pattern.createEmpty( { name: pattern.flatPatternPath, - patternName: isSubtypePattern - ? pattern.patternSubGroup - : pattern.patternGroup, - patternDesc: '', - patternPartial: - 'viewall-' + - pattern.patternGroup + - (isSubtypePattern ? '-' + pattern.patternSubGroup : ''), - patternSectionSubtype: isSubtypePattern, - patternLink: pattern.flatPatternPath + path.sep + 'index.html', + patternName: _.startCase( + isSubgroupPattern ? pattern.patternSubgroup : pattern.patternGroup + ), + patternDesc: isSubgroupPattern + ? pattern.patternSubgroupData.markdown + : pattern.patternGroupData.markdown, + patternPartial: `viewall-${pattern.patternGroup}-${ + isSubgroupPattern ? pattern.patternSubgroup : 'all' + }`, + patternSectionSubgroup: true, + patternLink: path.join( + isSubgroupPattern ? pattern.flatPatternPath : pattern.patternGroup, + 'index.html' + ), isPattern: false, engine: null, flatPatternPath: pattern.flatPatternPath, isDocPattern: true, - order: -Number.MAX_SAFE_INTEGER, + order: Number.MIN_SAFE_INTEGER, }, patternlab ); - return docPattern; } /** - * Registers flat patterns with the patternTypes object + * Sorts the given patterns in the way they are ment to be sorted + * @param {array} patterns which should be sorted + * @returns a sorted array of patterns + */ + function getSortedPatterns(patterns) { + return _.sortBy(patterns, ['order', 'variantOrder', 'name']); + } + + /** + * Registers flat patterns with the patternGroups object * This is a new menu group like atoms * @param patternlab - global data store * @param pattern - the pattern to register */ - function addPatternType(patternlab, pattern) { - patternlab.patternTypes.push({ - patternTypeLC: pattern.patternGroup.toLowerCase(), - patternTypeUC: - pattern.patternGroup.charAt(0).toUpperCase() + - pattern.patternGroup.slice(1), - patternType: pattern.patternType, - patternTypeDash: pattern.patternGroup, //todo verify - patternTypeItems: [], + function addPatternGroup(patternlab, pattern) { + patternlab.patternGroups.push({ + patternGroupLC: _.kebabCase(pattern.patternGroup), + patternGroupUC: _.startCase(pattern.patternGroup), + patternGroup: pattern.patternGroup, + patternGroupDash: pattern.patternGroup, //todo verify + patternGroupItems: [], + order: + pattern.patternGroupData && pattern.patternGroupData.order + ? Number(pattern.patternGroupData.order) + : 0, }); + + patternlab.patternGroups = _.sortBy( + patternlab.patternGroups, + 'order', + 'patternGroup' + ); } /** - * Return the patternType object for the given pattern. Exits application if not found. + * Return the patternGroup object for the given pattern. Exits application if not found. * @param patternlab - global data store * @param pattern - the pattern to derive the pattern Type from * @returns the found pattern type object */ - function getPatternType(patternlab, pattern) { - const patternType = _.find(patternlab.patternTypes, [ - 'patternType', - pattern.patternType, + function getPatternGroup(patternlab, pattern) { + const patternGroup = _.find(patternlab.patternGroups, [ + 'patternGroup', + pattern.patternGroup, ]); - if (!patternType) { + if (!patternGroup) { logger.error( - `Could not find patternType ${ - pattern.patternType - }. This is a critical error.` + `Could not find patternGroup ${pattern.patternGroup}. This is a critical error.` ); } - return patternType; + return patternGroup; } /** - * Return the patternSubType object for the given pattern. Exits application if not found. + * Return the patternSubgroup object for the given pattern. Exits application if not found. * @param patternlab - global data store - * @param pattern - the pattern to derive the pattern subType from - * @returns the found patternSubType object + * @param pattern - the pattern to derive the pattern subgroup from + * @returns the found patternSubgroup object */ - function getPatternSubType(patternlab, pattern) { - const patternType = getPatternType(patternlab, pattern); - const patternSubType = _.find(patternType.patternTypeItems, [ - 'patternSubtype', - pattern.patternSubType, + function getPatternSubgroup(patternlab, pattern) { + const patternGroup = getPatternGroup(patternlab, pattern); + const patternSubgroup = _.find(patternGroup.patternGroupItems, [ + 'patternSubgroup', + pattern.patternSubgroup, ]); - if (!patternSubType) { + if (!patternSubgroup) { logger.error( - `Could not find patternType ${pattern.patternType}-${ - pattern.patternType - }. This is a critical error.` + `Could not find patternGroup ${pattern.patternGroup}-${pattern.patternGroup}. This is a critical error.` ); } - return patternSubType; + return patternSubgroup; } /** - * Registers the pattern with the appropriate patternType.patternTypeItems object + * Registers the pattern with the appropriate patternGroup.patternGroupItems object * This is a new menu group like atoms/global * @param patternlab - global data store * @param pattern - the pattern to register */ - function addPatternSubType(patternlab, pattern) { - const newSubType = { - patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), - patternSubtypeUC: - pattern.patternSubGroup.charAt(0).toUpperCase() + - pattern.patternSubGroup.slice(1), - patternSubtype: pattern.patternSubType, - patternSubtypeDash: pattern.patternSubGroup, //todo verify - patternSubtypeItems: [], - }; - const patternType = getPatternType(patternlab, pattern); - const insertIndex = _.sortedIndexBy( - patternType.patternTypeItems, - newSubType, - 'patternSubtype' + function addPatternSubgroup(patternlab, pattern) { + const patternGroup = getPatternGroup(patternlab, pattern); + + patternGroup.patternGroupItems.push({ + patternSubgroupLC: _.kebabCase(pattern.patternSubgroup), + patternSubgroupUC: _.startCase(pattern.patternSubgroup), + patternSubgroup: pattern.patternSubgroup, + patternSubgroupDash: pattern.patternSubgroup, //todo verify + patternSubgroupItems: [], + order: + pattern.patternSubgroupData && pattern.patternSubgroupData.order + ? Number(pattern.patternSubgroupData.order) + : 0, + }); + + patternGroup.patternGroupItems = _.sortBy( + patternGroup.patternGroupItems, + 'order', + 'patternSubgroup' ); - patternType.patternTypeItems.splice(insertIndex, 0, newSubType); } /** - * Creates a patternSubTypeItem object from a pattern + * Creates a patternSubgroupItem object from a pattern * This is a menu item you click on - * @param pattern - the pattern to derive the subtypeitem from - * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternSrcPath: string, patternPath: string}} + * @param pattern - the pattern to derive the subgroupitem from + * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternPath: string}} */ - function createPatternSubTypeItem(pattern) { - let patternPath = ''; - if (pattern.isFlatPattern) { - patternPath = - pattern.flatPatternPath + - '-' + - pattern.fileName + - '/' + - pattern.flatPatternPath + - '-' + - pattern.fileName + - '.html'; - } else { - patternPath = - pattern.flatPatternPath + '/' + pattern.flatPatternPath + '.html'; - } - + function createPatternSubgroupItem(pattern) { return { patternPartial: pattern.patternPartial, patternName: pattern.patternName, patternState: pattern.patternState, - patternSrcPath: encodeURI(pattern.subdir + '/' + pattern.fileName), - patternPath: patternPath, - order: pattern.order, + patternPath: pattern.patternLink, + name: pattern.name, + isDocPattern: false, + order: Number(pattern.order) || 0, // Failsafe is someone entered a string + variantOrder: Number(pattern.variantOrder) || 0, // Failsafe is someone entered a string }; } /** - * Registers the pattern with the appropriate patternType.patternSubType.patternSubtypeItems array + * Registers the pattern with the appropriate patternGroup.patternSubgroup.patternSubgroupItems array * These are the actual menu items you click on * @param patternlab - global data store - * @param pattern - the pattern to derive the subtypeitem from + * @param pattern - the pattern to derive the subgroupitem from * @param createViewAllVariant - whether or not to create the special view all item */ - function addPatternSubTypeItem( + function addPatternSubgroupItem( patternlab, pattern, - createSubtypeViewAllVarient + createSubgroupViewAllVariant ) { - let newSubTypeItem; + let newSubgroupItem; - if (createSubtypeViewAllVarient) { - newSubTypeItem = { + if (createSubgroupViewAllVariant) { + newSubgroupItem = { patternPartial: - 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup, - patternName: 'View All', + 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubgroup, + patternName: `View All`, patternPath: encodeURI(pattern.flatPatternPath + '/index.html'), - patternType: pattern.patternType, - patternSubtype: pattern.patternSubtype, - order: 0, + patternGroup: pattern.patternGroup, + patternSubgroup: pattern.patternSubgroup, + name: pattern.flatPatternPath, + isDocPattern: true, + order: Number.MAX_SAFE_INTEGER, }; } else { - newSubTypeItem = createPatternSubTypeItem(pattern); + newSubgroupItem = createPatternSubgroupItem(pattern); } - const patternSubType = getPatternSubType(patternlab, pattern); - patternSubType.patternSubtypeItems.push(newSubTypeItem); - patternSubType.patternSubtypeItems = _.sortBy( - patternSubType.patternSubtypeItems, - ['order', 'name'] + const patternSubgroup = getPatternSubgroup(patternlab, pattern); + patternSubgroup.patternSubgroupItems.push(newSubgroupItem); + patternSubgroup.patternSubgroupItems = getSortedPatterns( + patternSubgroup.patternSubgroupItems ); } @@ -345,113 +329,42 @@ const ui_builder = function() { * @param pattern - the pattern to add */ function addPatternItem(patternlab, pattern, isViewAllVariant) { - const patternType = getPatternType(patternlab, pattern); - if (!patternType) { + const patternGroup = getPatternGroup(patternlab, pattern); + if (!patternGroup) { logger.error( - `Could not find patternType ${ - pattern.patternType - }. This is a critical error.` + `Could not find patternGroup ${pattern.patternGroup}. This is a critical error.` ); } - if (!patternType.patternItems) { - patternType.patternItems = []; - } - + patternGroup.patternItems = patternGroup.patternItems || []; if (isViewAllVariant) { - if (!pattern.isFlatPattern) { - //todo: it'd be nice if we could get this into createPatternSubTypeItem someday - patternType.patternItems.push({ - patternPartial: 'viewall-' + pattern.patternGroup + '-all', - patternName: 'View All', - patternPath: encodeURI(pattern.patternType + '/index.html'), - order: -Number.MAX_SAFE_INTEGER, - }); - } + patternGroup.patternItems.push({ + patternPartial: `viewall-${pattern.patternGroup}-all`, + patternName: `View all ${_.startCase(pattern.patternGroup)}`, + patternPath: encodeURI(pattern.patternGroup + '/index.html'), + name: pattern.patternGroup, + isDocPattern: true, + order: Number.MAX_SAFE_INTEGER, // Or pattern.groupData.order + }); } else { - patternType.patternItems.push(createPatternSubTypeItem(pattern)); + patternGroup.patternItems.push(createPatternSubgroupItem(pattern)); } - patternType.patternItems = _.sortBy(patternType.patternItems, [ - 'order', - 'name', - ]); - } - - // function getPatternItems(patternlab, patternType) { - // var patternType = _.find(patternlab.patternTypes, ['patternTypeLC', patternType]); - // if (patternType) { - // return patternType.patternItems; - // } - // return []; - // } - - /** - * Sorts patterns based on order property found within pattern markdown, falling back on name. - * @param patternsArray - patterns to sort - * @returns sorted patterns - */ - function sortPatterns(patternsArray) { - return patternsArray.sort(function(a, b) { - let aOrder = parseInt(a.order, 10); - const bOrder = parseInt(b.order, 10); - - if (aOrder === NaN) { - aOrder = Number.MAX_SAFE_INTEGER; - } - - if (bOrder === NaN) { - aOrder = Number.MAX_SAFE_INTEGER; - } - - //alwasy return a docPattern first - if (a.isDocPattern && !b.isDocPattern) { - return -1; - } - - if (!a.isDocPattern && b.isDocPattern) { - return 1; - } - - //use old alphabetical ordering if we have nothing else to use - //pattern.order will be Number.MAX_SAFE_INTEGER if never defined by markdown, or markdown parsing fails - if ( - aOrder === Number.MAX_SAFE_INTEGER && - bOrder === Number.MAX_SAFE_INTEGER - ) { - if (a.name > b.name) { - return 1; - } - if (a.name < b.name) { - return -1; - } - } - - //if we get this far, we can sort safely - if (aOrder && bOrder) { - if (aOrder > bOrder) { - return 1; - } - if (aOrder < bOrder) { - return -1; - } - } - return 0; - }); + patternGroup.patternItems = getSortedPatterns(patternGroup.patternItems); } /** * Returns an object representing how the front end styleguide and navigation is structured * @param patternlab - global data store * @param uikit - the current uikit being built - * @returns ptterns grouped by type -> subtype like atoms -> global -> pattern, pattern, pattern + * @returns patterns grouped by type -> subgroup like atoms -> global -> pattern, pattern, pattern */ function groupPatterns(patternlab, uikit) { const groupedPatterns = { patternGroups: {}, }; - _.forEach(patternlab.patterns, function(pattern) { - //ignore patterns we can omit from rendering directly + _.forEach(patternlab.patterns, function (pattern) { + // ignore patterns we can omit from rendering directly pattern.omitFromStyleguide = isPatternExcluded( pattern, patternlab, @@ -463,43 +376,45 @@ const ui_builder = function() { if (!groupedPatterns.patternGroups[pattern.patternGroup]) { groupedPatterns.patternGroups[pattern.patternGroup] = {}; - pattern.isSubtypePattern = false; - addPatternType(patternlab, pattern); - - //todo: Pattern Type View All and Documentation - //groupedPatterns.patternGroups[pattern.patternGroup]['viewall-' + pattern.patternGroup] = injectDocumentationBlock(pattern, patternlab, false); - addPatternItem(patternlab, pattern, true); + pattern.isSubgroupPattern = false; + addPatternGroup(patternlab, pattern); + if ( + !pattern.isFlatPattern || + patternlab.config.renderFlatPatternsOnViewAllPages + ) { + addPatternItem(patternlab, pattern, true); + } + addToViewAllPaths(patternlab, pattern); } - //continue building navigation for nested patterns - if (pattern.patternGroup !== pattern.patternSubGroup) { + // continue building navigation for nested patterns + if (!pattern.isFlatPattern) { if ( !groupedPatterns.patternGroups[pattern.patternGroup][ - pattern.patternSubGroup + pattern.patternSubgroup ] ) { - addPatternSubType(patternlab, pattern); + addPatternSubgroup(patternlab, pattern); - pattern.isSubtypePattern = !pattern.isPattern; + pattern.isSubgroupPattern = !pattern.isPattern; groupedPatterns.patternGroups[pattern.patternGroup][ - pattern.patternSubGroup + pattern.patternSubgroup ] = {}; groupedPatterns.patternGroups[pattern.patternGroup][ - pattern.patternSubGroup - ][ - 'viewall-' + pattern.patternGroup + '-' + pattern.patternSubGroup - ] = injectDocumentationBlock(pattern, patternlab, true); + pattern.patternSubgroup + ]['viewall-' + pattern.patternGroup + '-' + pattern.patternSubgroup] = + injectDocumentationBlock(pattern, patternlab, true); addToViewAllPaths(patternlab, pattern); - addPatternSubTypeItem(patternlab, pattern, true); + addPatternSubgroupItem(patternlab, pattern, true); } groupedPatterns.patternGroups[pattern.patternGroup][ - pattern.patternSubGroup + pattern.patternSubgroup ][pattern.patternBaseName] = pattern; addToPatternPaths(patternlab, pattern); - addPatternSubTypeItem(patternlab, pattern); + addPatternSubgroupItem(patternlab, pattern); } else { addPatternItem(patternlab, pattern); addToPatternPaths(patternlab, pattern); @@ -509,9 +424,27 @@ const ui_builder = function() { return groupedPatterns; } + /** + * Search all flat patterns of a specific pattern type + * + * @param {Patternlab} patternlab Current patternlab instance + * @param {string} patternGroup indicator which patterns to search for + */ + function getFlatPatternItems(patternlab, patternGroup) { + const patterns = _.filter( + patternlab.patterns, + (pattern) => + pattern.patternGroup === patternGroup && pattern.isFlatPattern + ); + if (patterns) { + return getSortedPatterns(patterns); + } + return []; + } + /** * Takes a set of patterns and builds a viewall HTML page for them - * Used by the type and subtype viewall sets + * Used by the type and subgroup viewall sets * @param patternlab - global data store * @param patterns - the set of patterns to build the viewall page for * @param patternPartial - a key used to identify the viewall page @@ -519,24 +452,63 @@ const ui_builder = function() { */ function buildViewAllHTML(patternlab, patterns, patternPartial, uikit) { return render( - Pattern.createEmpty({ extendedTemplate: uikit.viewAll }), + Pattern.createEmpty({ extendedTemplate: uikit.viewAll }, patternlab), { - //data + // data partials: patterns, patternPartial: 'viewall-' + patternPartial, cacheBuster: patternlab.cacheBuster, }, { - //templates + // templates patternSection: uikit.patternSection, - patternSectionSubtype: uikit.patternSectionSubType, + patternSectionSubgroup: uikit.patternSectionSubgroup, } - ).catch(reason => { + ).catch((reason) => { console.log(reason); logger.error('Error building buildViewAllHTML'); }); } + /** + * Sorts the pattern groups for the view all page as they are meant to be sorted. + * Therefore the function searches for the subgroup in the patternGroupItems and retrieves its sorting. + * @param patternGroup The pattern group object with it's subgroups + * @param patternGroupName the pattern group name e.g. atoms + * @param patternlab - global data store + * @returns a sorted list of pattern groups + */ + function getSortedPatternSubgroups( + patternGroup, + patternGroupName, + patternlab + ) { + return _.sortBy(_.values(patternGroup), [ + (pSubgroup) => { + const group = patternlab.patternGroups.find( + (g) => g.patternGroup === patternGroupName + ); + + if (group) { + const sg = group.patternGroupItems.find((item) => { + const firstPattern = _.first( + _.values(pSubgroup).filter((p) => p.patternBaseName !== '.') + ); + return ( + item && + firstPattern && + firstPattern.patternSubgroup === item.patternSubgroup + ); + }); + + return sg ? sg.order : 0; + } else { + return 0; + } + }, + ]); + } + /** * Constructs viewall pages for each set of grouped patterns * @param mainPageHeadHtml - the already built main page HTML @@ -552,255 +524,302 @@ const ui_builder = function() { ) { const paths = patternlab.config.paths; let patterns = []; - let writeViewAllFile = true; - - //loop through the grouped styleguide patterns, building at each level - const allPatternTypePromises = _.map( - styleguidePatterns.patternGroups, - (patternGroup, patternType) => { - let typePatterns = []; - let styleguideTypePatterns = []; - const styleGuideExcludes = - patternlab.config.styleGuideExcludes || - patternlab.config.styleguideExcludes; - const subTypePromises = _.map( - _.values(patternGroup), - (patternSubtypes, patternSubtype, originalPatternGroup) => { + + // loop through the grouped styleguide patterns, building at each level + const allPatternGroupPromises = _.map( + patternlab.patternGroups, + (patternGroup) => { + const patternGroupName = patternGroup.patternGroup; + const group = styleguidePatterns.patternGroups[patternGroupName]; + let groupedPatterns = []; + let styleguideGroupedPatterns = []; + const styleGuideExcludes = patternlab.config.styleGuideExcludes || []; + + /** + * View all pages for subgroups + */ + const subgroupPromises = _.map( + getSortedPatternSubgroups(group, patternGroupName, patternlab), + (patternSubgroups, patternSubgroup, originalPatternGroup) => { let p; - const samplePattern = _.find(patternSubtypes, st => { - return !st.patternPartial.startsWith('viewall-'); - }); + const samplePattern = _.find( + patternSubgroups, + (st) => !st.patternPartial.startsWith('viewall-') + ); const patternName = Object.keys( - _.values(originalPatternGroup)[patternSubtype] + _.values(originalPatternGroup)[patternSubgroup] )[1]; const patternPartial = - patternType + '-' + samplePattern.patternSubType; + patternGroupName + '-' + samplePattern.patternSubgroup; - //do not create a viewall page for flat patterns - if (patternType === patternName) { - writeViewAllFile = false; + // do not create a viewall page for flat patterns + if (patternGroupName === patternName) { logger.debug( - `skipping ${patternType} as flat patterns do not have view all pages` + `skipping ${patternGroupName} as flat patterns do not have view all pages` ); return Promise.resolve(); } - //render the footer needed for the viewall template + // render the footer needed for the viewall template return buildFooter(patternlab, `viewall-${patternPartial}`, uikit) - .then(footerHTML => { - //render the viewall template by finding these smallest subtype-grouped patterns - const subtypePatterns = sortPatterns(_.values(patternSubtypes)); + .then((footerHTML) => { + // render the viewall template by finding these smallest subgroup-grouped patterns + const subgroupPatterns = getSortedPatterns( + _.values(patternSubgroups) + ); - //determine if we should write at this time by checking if these are flat patterns or grouped patterns - p = _.find(subtypePatterns, function(pat) { + // determine if we should write at this time by checking if these are flat patterns or grouped patterns + p = _.find(subgroupPatterns, function (pat) { return pat.isDocPattern; }); - //determine if we should omit this subpatterntype completely from the viewall page - const omitPatternType = + // determine if we should omit this subpatternGroup completely from the viewall page + const omitPatternGroup = styleGuideExcludes && styleGuideExcludes.length && - _.some(styleGuideExcludes, function(exclude) { - return exclude === patternType + '/' + patternName; - }); - if (omitPatternType) { + _.some( + styleGuideExcludes, + (exclude) => + exclude === `${patternGroupName}/${patternName}` + ); + if (omitPatternGroup) { logger.debug( - `Omitting ${patternType}/${patternName} from building a viewall page because its patternSubGroup is specified in styleguideExcludes.` + `Omitting ${patternGroupName}/${patternName} from building a viewall page because its patternSubgroup is specified in styleguideExcludes.` ); } else { - styleguideTypePatterns = styleguideTypePatterns.concat( - subtypePatterns - ); + styleguideGroupedPatterns = + styleguideGroupedPatterns.concat(subgroupPatterns); } - typePatterns = typePatterns.concat(subtypePatterns); + groupedPatterns = groupedPatterns.concat(subgroupPatterns); - //render the viewall template for the subtype + // render the viewall template for the subgroup return buildViewAllHTML( patternlab, - subtypePatterns, + subgroupPatterns, patternPartial, uikit ) - .then(viewAllHTML => { + .then((viewAllHTML) => { return fs.outputFile( path.join( process.cwd(), uikit.outputDir, - paths.public.patterns + - p.flatPatternPath + - '/index.html' + path.join( + `${paths.public.patterns}${p.flatPatternPath}`, + 'index.html' + ) ), mainPageHeadHtml + viewAllHTML + footerHTML ); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('Error building ViewAllHTML'); }); }) - .then(() => { - //do not create a viewall page for flat patterns - if (!writeViewAllFile || !p) { + .catch((reason) => { + console.log(reason); + logger.error('Error building footer HTML'); + }); + } + ); + + /** + * View all pages for groups + */ + return Promise.all(subgroupPromises) + .then(() => { + // render the footer needed for the viewall template + return buildFooter( + patternlab, + `viewall-${patternGroupName}-all`, + uikit + ) + .then((footerHTML) => { + const sortedFlatPatterns = getFlatPatternItems( + patternlab, + patternGroupName + ); + + if (patternlab.config.renderFlatPatternsOnViewAllPages) { + // Check if this is a flat pattern group + groupedPatterns = sortedFlatPatterns.concat(groupedPatterns); + } + + // get the appropriate patternGroup + const anyPatternOfType = _.find( + groupedPatterns, + function (pat) { + return pat.patternGroup && pat.patternGroup !== ''; + } + ); + + if (!anyPatternOfType || !groupedPatterns.length) { logger.debug( - `skipping ${patternType} as flat patterns do not have view all pages` + `skipping ${patternGroupName} as flat patterns do not have view all pages` ); - return Promise.resolve(); + return Promise.resolve([]); } - //render the footer needed for the viewall template - return buildFooter( + // render the viewall template for the type + return buildViewAllHTML( patternlab, - 'viewall-' + patternType + '-all', + groupedPatterns, + patternGroupName, uikit ) - .then(footerHTML => { - //add any flat patterns - //todo this isn't quite working yet - //typePatterns = typePatterns.concat(getPatternItems(patternlab, patternType)); - - //get the appropriate patternType - const anyPatternOfType = _.find(typePatterns, function( - pat - ) { - return pat.patternType && pat.patternType !== ''; - }); - - if (!anyPatternOfType) { + .then((viewAllHTML) => { + fs.outputFileSync( + path.join( + process.cwd(), + uikit.outputDir, + path.join( + `${paths.public.patterns}${patternGroupName}`, + 'index.html' + ) + ), + mainPageHeadHtml + viewAllHTML + footerHTML + ); + + // determine if we should omit this patternGroup completely from the viewall page + const omitPatternGroup = + styleGuideExcludes && + styleGuideExcludes.length && + _.some(styleGuideExcludes, function (exclude) { + return exclude === patternGroupName; + }); + if (omitPatternGroup) { logger.debug( - `skipping ${patternType} as flat patterns do not have view all pages` + `Omitting ${patternGroupName} from building a viewall page because its patternGroup is specified in styleguideExcludes.` ); - return Promise.resolve(); + } else { + if (patternlab.config.renderFlatPatternsOnViewAllPages) { + patterns = sortedFlatPatterns; + patterns = patterns.concat(styleguideGroupedPatterns); + } else { + patterns = styleguideGroupedPatterns; + } } - - //render the viewall template for the type - return buildViewAllHTML( - patternlab, - typePatterns, - patternType, - uikit - ) - .then(viewAllHTML => { - fs.outputFileSync( - path.join( - process.cwd(), - uikit.outputDir, - paths.public.patterns + - anyPatternOfType.patternType + - '/index.html' - ), - mainPageHeadHtml + viewAllHTML + footerHTML - ); - - //determine if we should omit this patterntype completely from the viewall page - const omitPatternType = - styleGuideExcludes && - styleGuideExcludes.length && - _.some(styleGuideExcludes, function(exclude) { - return exclude === patternType; - }); - if (omitPatternType) { - logger.debug( - `Omitting ${patternType} from building a viewall page because its patternGroup is specified in styleguideExcludes.` - ); - } else { - patterns = patterns.concat(styleguideTypePatterns); - } - return Promise.resolve(patterns); - }) - .catch(reason => { - console.log(reason); - logger.error('Error building ViewAllHTML'); - }); + return Promise.resolve(patterns); }) - .catch(reason => { + .catch((reason) => { console.log(reason); - logger.error('Error building footerHTML'); + logger.error('Error building ViewAllHTML'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); - logger.error('Error building footer HTML'); + logger.error('Error building footerHTML'); }); - } - ); - - return Promise.all(subTypePromises).catch(reason => { - console.log(reason); - logger.error('Error during buildViewAllPages'); - }); + }) + .catch((reason) => { + console.log(reason); + logger.error('Error during buildViewAllPages'); + }); } ); - return Promise.all(allPatternTypePromises).catch(reason => { - console.log(reason); - logger.error('Error during buildViewAllPages'); - }); + return Promise.all(allPatternGroupPromises) + .then((allPatterns) => + Promise.resolve(_.filter(allPatterns, (p) => p.length)) + ) + .catch((reason) => { + console.log(reason); + logger.error('Error during buildViewAllPages'); + }); } /** * Reset any global data we use between builds to guard against double adding things + * + * @param {Patternlab} patternlab Actual patternlab instance */ function resetUIBuilderState(patternlab) { patternlab.patternPaths = {}; patternlab.viewAllPaths = {}; - patternlab.patternTypes = []; + patternlab.patternGroups = []; + } + + /** + * Uniques all generated patterns and groups, also adds a group document pattern before + * each group. Used for generating view all page and all its pattern. + * + * @param {[Pattern[]]} allPatterns All generated patterns + * @param {Patternlab} patternlab Actual patternlab instance + */ + function uniqueAllPatterns(allPatterns, patternlab) { + return _.uniq( + _.flatMapDeep( + _.map(allPatterns, (patterns) => [ + injectDocumentationBlock( + _.find(patterns, (p) => !p.patternPartial.startsWith('viewall-')), + patternlab, + false + ), + ...patterns, + ]), + (pattern) => pattern + ) + ); } /** * The main entry point for ui_builder - * @param patternlab - global data store + * @param patternlabGlobal - global data store * @returns {Promise} a promise fulfilled when build is complete */ - function buildFrontend(patternlab) { - resetUIBuilderState(patternlab); + function buildFrontend(patternlabGlobal) { + const paths = patternlabGlobal.config.paths; - const paths = patternlab.config.paths; + const uikitPromises = _.map(patternlabGlobal.uikits, (uikit) => { + //we need to make sure the patternlab object gets manipulated per uikit + const patternlab = Object.assign({}, patternlabGlobal); - const uikitPromises = _.map(patternlab.uikits, uikit => { + resetUIBuilderState(patternlab); //determine which patterns should be included in the front-end rendering const styleguidePatterns = groupPatterns(patternlab, uikit); - return new Promise(resolve => { - //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header + return new Promise((resolve) => { + // set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header const headerPromise = render( - Pattern.createEmpty({ extendedTemplate: uikit.header }), + Pattern.createEmpty({ extendedTemplate: uikit.header }, patternlab), { cacheBuster: patternlab.cacheBuster, } ) - .then(headerPartial => { + .then((headerPartial) => { const headFootData = patternlab.data; headFootData.patternLabHead = headerPartial; headFootData.cacheBuster = patternlab.cacheBuster; return render(patternlab.userHead, headFootData); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('error during header render()'); }); - //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer + // set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer const footerPromise = render( - Pattern.createEmpty({ extendedTemplate: uikit.footer }), + Pattern.createEmpty({ extendedTemplate: uikit.footer }, patternlab), { patternData: '{}', cacheBuster: patternlab.cacheBuster, } ) - .then(footerPartial => { + .then((footerPartial) => { const headFootData = patternlab.data; headFootData.patternLabFoot = footerPartial; return render(patternlab.userFoot, headFootData); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('error during footer render()'); }); return Promise.all([headerPromise, footerPromise]).then( - headFootPromiseResults => { - //build the viewall pages + (headFootPromiseResults) => { + // build the viewall pages return buildViewAllPages( headFootPromiseResults[0], @@ -808,34 +827,36 @@ const ui_builder = function() { styleguidePatterns, uikit ) - .then(allPatterns => { - //todo track down why we need to make this unique in the first place - const uniquePatterns = _.uniq( - _.flatMapDeep(allPatterns, pattern => { - return pattern; - }) + .then((allPatterns) => { + // todo track down why we need to make this unique in the first place + const uniquePatterns = uniqueAllPatterns( + allPatterns, + patternlab ); - //add the defaultPattern if we found one + // add the defaultPattern if we found one if (patternlab.defaultPattern) { uniquePatterns.push(patternlab.defaultPattern); addToPatternPaths(patternlab, patternlab.defaultPattern); } - //build the main styleguide page + // build the main styleguide page return render( - Pattern.createEmpty({ - extendedTemplate: uikit.viewAll, - }), + Pattern.createEmpty( + { + extendedTemplate: uikit.viewAll, + }, + patternlab + ), { partials: uniquePatterns, }, { patternSection: uikit.patternSection, - patternSectionSubtype: uikit.patternSectionSubType, + patternSectionSubgroup: uikit.patternSectionSubgroup, } ) - .then(styleguideHtml => { + .then((styleguideHtml) => { fs.outputFileSync( path.resolve( path.join( @@ -852,7 +873,7 @@ const ui_builder = function() { logger.info('Built Pattern Lab front end'); - //move the index file from its asset location into public root + // move the index file from its asset location into public root let patternlabSiteHtml; try { patternlabSiteHtml = fs.readFileSync( @@ -867,9 +888,7 @@ const ui_builder = function() { ); } catch (err) { logger.error( - `Could not load one or more styleguidekit assets from ${ - paths.source.styleguide - }` + `Could not load one or more styleguidekit assets from ${paths.source.styleguide}` ); } fs.outputFileSync( @@ -885,15 +904,15 @@ const ui_builder = function() { ); //write out patternlab.data object to be read by the client - exportData(patternlab); + exportData(patternlab, uikit); resolve(); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('error during buildFrontend()'); }); }) - .catch(reason => { + .catch((reason) => { console.log(reason); logger.error('error during buildViewAllPages()'); }); @@ -905,31 +924,12 @@ const ui_builder = function() { } return { - buildFrontend: function(patternlab) { - return buildFrontend(patternlab); - }, - isPatternExcluded: function(pattern, patternlab, uikit) { - return isPatternExcluded(pattern, patternlab, uikit); - }, - groupPatterns: function(patternlab, uikit) { - return groupPatterns(patternlab, uikit); - }, - resetUIBuilderState: function(patternlab) { - resetUIBuilderState(patternlab); - }, - buildViewAllPages: function( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ) { - return buildViewAllPages( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ); - }, + buildFrontend: buildFrontend, + isPatternExcluded: isPatternExcluded, + groupPatterns: groupPatterns, + resetUIBuilderState: resetUIBuilderState, + uniqueAllPatterns: uniqueAllPatterns, + buildViewAllPages: buildViewAllPages, }; }; diff --git a/packages/core/src/lib/uikitExcludePattern.js b/packages/core/src/lib/uikitExcludePattern.js index 61cddcb57..22aa3eece 100644 --- a/packages/core/src/lib/uikitExcludePattern.js +++ b/packages/core/src/lib/uikitExcludePattern.js @@ -1,7 +1,14 @@ 'use strict'; +const _ = require('lodash'); + const uikitExcludePattern = (pattern, uikit) => { const state = pattern.patternState; - return uikit.excludedPatternStates.includes(state); + const tags = _.isArray(pattern.tags) ? pattern.tags : [pattern.tags]; + + return ( + _.includes(uikit.excludedPatternStates, state) || + _.intersection(uikit.excludedTags, tags).length > 0 + ); }; module.exports = uikitExcludePattern; diff --git a/packages/core/src/lib/watchAssets.js b/packages/core/src/lib/watchAssets.js index f087b8a28..6f07626e7 100644 --- a/packages/core/src/lib/watchAssets.js +++ b/packages/core/src/lib/watchAssets.js @@ -10,7 +10,7 @@ let copyFile = require('./copyFile'); // eslint-disable-line prefer-const function onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions) { const subPath = p.replace(assetBase, ''); - _.each(patternlab.uikits, uikit => { + _.each(patternlab.uikits, (uikit) => { const destination = path.resolve( basePath, uikit.outputDir, @@ -57,10 +57,10 @@ const watchAssets = ( //watch for changes and copy assetWatcher - .on('add', p => { + .on('add', (p) => { onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions); }) - .on('change', p => { + .on('change', (p) => { onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions); }); diff --git a/packages/core/src/lib/watchPatternLabFiles.js b/packages/core/src/lib/watchPatternLabFiles.js index 7a1c390c2..c2eb681ab 100644 --- a/packages/core/src/lib/watchPatternLabFiles.js +++ b/packages/core/src/lib/watchPatternLabFiles.js @@ -4,6 +4,8 @@ const path = require('path'); const logger = require('./log'); const events = require('./events'); +const pm = require('./plugin_manager'); +const pluginMananger = new pm(); let chokidar = require('chokidar'); // eslint-disable-line prefer-const @@ -18,12 +20,12 @@ const watchPatternLabFiles = ( assetDirectories.source.data, assetDirectories.source.meta, ]; - const globalPaths = globalSources.map(globalSource => - path.join(basePath, globalSource, '*') + const globalPaths = globalSources.map((globalSource) => + path.join(path.resolve(basePath, globalSource), '*') ); - _.each(globalPaths, globalPath => { - logger.debug(`Pattern Lab is watching ${globalPath} for changes`); + _.each(globalPaths, (globalPath) => { + logger.debug(`Pattern Lab is watching ${globalPath} for changes!`); if (patternlab.watchers[globalPath]) { patternlab.watchers[globalPath].close(); @@ -41,20 +43,32 @@ const watchPatternLabFiles = ( //watch for changes and rebuild globalWatcher - .on('addDir', p => { - patternlab.events.emit(events.PATTERNLAB_GLOBAL_CHANGE, { - file: p, - }); + .on('addDir', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_GLOBAL_CHANGE, + { + file: p, + } + ); }) - .on('add', p => { - patternlab.events.emit(events.PATTERNLAB_GLOBAL_CHANGE, { - file: p, - }); + .on('add', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_GLOBAL_CHANGE, + { + file: p, + } + ); }) - .on('change', p => { - patternlab.events.emit(events.PATTERNLAB_GLOBAL_CHANGE, { - file: p, - }); + .on('change', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_GLOBAL_CHANGE, + { + file: p, + } + ); }); patternlab.watchers[globalPath] = globalWatcher; @@ -64,15 +78,16 @@ const watchPatternLabFiles = ( const baseFileExtensions = ['.json', '.yml', '.yaml', '.md']; const patternWatches = baseFileExtensions .concat(patternlab.engines.getSupportedFileExtensions()) - .map(dotExtension => + .map((dotExtension) => path.join( - basePath, - assetDirectories.source.patterns, + path.resolve(basePath, assetDirectories.source.patterns), `/**/*${dotExtension}` ) ); - _.each(patternWatches, patternWatchPath => { - logger.debug(`Pattern Lab is watching ${patternWatchPath} for changes`); + _.each(patternWatches, (patternWatchPath) => { + logger.debug( + `Pattern Lab is watching ${patternWatchPath} for changes - local!` + ); if (patternlab.watchers[patternWatchPath]) { patternlab.watchers[patternWatchPath].close(); @@ -90,29 +105,62 @@ const watchPatternLabFiles = ( //watch for changes and rebuild patternWatcher - .on('addDir', p => { - patternlab.events.emit(events.PATTERNLAB_PATTERN_CHANGE, { - file: p, - }); + .on('addDir', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_CHANGE, + { + file: p, + } + ); + }) + .on('add', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_CHANGE, + { + file: p, + } + ); }) - .on('add', p => { - patternlab.events.emit(events.PATTERNLAB_PATTERN_CHANGE, { - file: p, - }); + .on('change', async (p) => { + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_CHANGE, + { + file: p, + } + ); }) - .on('change', p => { - patternlab.events.emit(events.PATTERNLAB_PATTERN_CHANGE, { - file: p, - }); + // the watcher does not react on unlink and unlinkDir + // events, so patterns are never removed + .on('unlink', async (p) => { + patternlab.graph.sync(); + patternlab.graph.upgradeVersion(); + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_CHANGE, + { + file: p, + } + ); + }) + .on('unlinkDir', async (p) => { + patternlab.graph.sync(); + patternlab.graph.upgradeVersion(); + await pluginMananger.raiseEvent( + patternlab, + events.PATTERNLAB_PATTERN_CHANGE, + { + file: p, + } + ); }); - patternlab.watchers[patternWatchPath] = patternWatcher; }); logger.info( - `Pattern Lab is watching for changes to files under ${ - assetDirectories.source.root - }` + `Pattern Lab is watching for changes to files under ${assetDirectories.source.root}` ); return Promise.resolve(); }; diff --git a/packages/core/test/addPattern_tests.js b/packages/core/test/addPattern_tests.js index 0957e43e0..cf495cccb 100644 --- a/packages/core/test/addPattern_tests.js +++ b/packages/core/test/addPattern_tests.js @@ -10,11 +10,11 @@ const patterns_dir = './test/files/_patterns'; tap.test( 'addPattern - adds pattern extended template to patternlab partial object', - function(test) { + function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); - var pattern = new Pattern('00-test/01-bar.mustache'); + var pattern = new Pattern('test/bar.mustache'); pattern.extendedTemplate = 'barExtended'; pattern.template = 'bar'; @@ -22,20 +22,20 @@ tap.test( addPattern(pattern, patternlab); //assert - test.equals(patternlab.patterns.length, 1); - test.equals(patternlab.partials['test-bar'] !== undefined, true); - test.equals(patternlab.partials['test-bar'], 'barExtended'); + test.equal(patternlab.patterns.length, 1); + test.equal(patternlab.partials['test-bar'] !== undefined, true); + test.equal(patternlab.partials['test-bar'], 'barExtended'); test.end(); } ); tap.test( 'addPattern - adds pattern template to patternlab partial object if extendedtemplate does not exist yet', - function(test) { + function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); - var pattern = new Pattern('00-test/01-bar.mustache'); + var pattern = new Pattern('test/bar.mustache'); pattern.extendedTemplate = undefined; pattern.template = 'bar'; @@ -43,9 +43,9 @@ tap.test( addPattern(pattern, patternlab); //assert - test.equals(patternlab.patterns.length, 1); - test.equals(patternlab.partials['test-bar'] !== undefined, true); - test.equals(patternlab.partials['test-bar'], 'bar'); + test.equal(patternlab.patterns.length, 1); + test.equal(patternlab.partials['test-bar'] !== undefined, true); + test.equal(patternlab.partials['test-bar'], 'bar'); test.end(); } ); diff --git a/packages/core/test/annotation_exporter_tests.js b/packages/core/test/annotation_exporter_tests.js index 68c7b2f48..9fe95a1f6 100644 --- a/packages/core/test/annotation_exporter_tests.js +++ b/packages/core/test/annotation_exporter_tests.js @@ -20,35 +20,35 @@ function createFakePatternLab(anPath, customProps) { } var patternlab = createFakePatternLab(anPath); -var ae = require('../src/lib/annotation_exporter')(patternlab); +var ae = require('../src/lib/annotationExporter')(patternlab); -tap.test('converts old JS annotations into new format', function(test) { +tap.test('converts old JS annotations into new format', function (test) { //arrange //act - var annotations = ae.gatherJS(); + var annotations = ae.gatherJSON(); //assert - test.equals(annotations.length, 2); - test.equals(annotations[1].el, '.logo'); - test.equals(annotations[1].title, 'Logo'); - test.equals( + test.equal(annotations.length, 2); + test.equal(annotations[1].el, '.logo'); + test.equal(annotations[1].title, 'Logo'); + test.equal( annotations[1].comment, - 'The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don\'t support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

' + 'The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don\'t support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

' ); test.end(); }); -tap.test('converts new markdown annotations into an array', function(test) { +tap.test('converts new markdown annotations into an array', function (test) { //arrange //act var annotations = ae.gatherMD(); //assert - test.equals(annotations.length, 3); - test.equals(annotations[1].el, '.logo'); - test.equals(annotations[1].title, 'Logo'); - test.equals( + test.equal(annotations.length, 3); + test.equal(annotations[1].el, '.logo'); + test.equal(annotations[1].title, 'Logo'); + test.equal( annotations[1].comment.replace(/\r?\n|\r/gm, ''), '

The logo image is an SVG file.

' ); @@ -56,17 +56,17 @@ tap.test('converts new markdown annotations into an array', function(test) { test.end(); }); -tap.test('merges both annotation methods into one array', function(test) { +tap.test('merges both annotation methods into one array', function (test) { //arrange //act var annotations = ae.gather(); //assert - test.equals(annotations.length, 3); - test.equals(annotations[2].el, '#nav'); - test.equals(annotations[2].title, 'Navigation'); - test.equals( + test.equal(annotations.length, 3); + test.equal(annotations[2].el, '#nav'); + test.equal(annotations[2].title, 'Navigation'); + test.equal( annotations[2].comment.replace(/\r?\n|\r/gm, ''), '

Navigation for adaptive web experiences can be tricky. Refer to these repsonsive patterns when evaluating solutions.

' ); @@ -74,12 +74,12 @@ tap.test('merges both annotation methods into one array', function(test) { test.end(); }); -tap.test('when there are 0 annotation files', function(test) { +tap.test('when there are 0 annotation files', function (test) { var emptyAnPath = './test/files/empty/'; var patternlab2 = createFakePatternLab(emptyAnPath); - var ae2 = require('../src/lib/annotation_exporter')(patternlab2); + var ae2 = require('../src/lib/annotationExporter')(patternlab2); var annotations = ae2.gather(); - test.equals(annotations.length, 0); + test.equal(annotations.length, 0); test.end(); }); diff --git a/packages/core/test/buildListItems_tests.js b/packages/core/test/buildListItems_tests.js index 757c8f1aa..720e4a604 100644 --- a/packages/core/test/buildListItems_tests.js +++ b/packages/core/test/buildListItems_tests.js @@ -7,7 +7,7 @@ const listItems = require('./files/_data/listitems.json'); const buildlistItems = rewire('../src/lib/buildListItems'); const _Mock = { - shuffle: function(list) { + shuffle: function (list) { return list; }, }; @@ -19,9 +19,9 @@ buildlistItems.__set__({ tap.test( 'buildlistItems transforms container of listItems with one value', - test => { + (test) => { // do this to avoid the shuffling for now - const container = Object.assign({}, { listitems: { '1': listItems['1'] } }); + const container = Object.assign({}, { listitems: { 1: listItems['1'] } }); buildlistItems(container); test.same(container.listitems, { 'listItems-one': [ @@ -38,7 +38,7 @@ tap.test( tap.test( 'buildlistItems transforms container of listItems with three values', - test => { + (test) => { // do this to avoid the shuffling for now const container = { listitems: listItems }; buildlistItems(container); diff --git a/packages/core/test/changes_hunter_tests.js b/packages/core/test/changes_hunter_tests.js index 68b6c054d..a9050af0a 100644 --- a/packages/core/test/changes_hunter_tests.js +++ b/packages/core/test/changes_hunter_tests.js @@ -6,7 +6,7 @@ const rewire = require('rewire'); const ch = rewire('../src/lib/changes_hunter'); const fsMock = { - statSync: function() { + statSync: function () { return { mtime: { getTime: () => { @@ -27,41 +27,41 @@ ch.__set__({ const changes_hunter = new ch(); -tap.test('checkLastModified - sets lastModified to fileTime ', function(test) { +tap.test('checkLastModified - sets lastModified to fileTime ', function (test) { //arrange const mockPattern = { lastModified: 0 }; //act changes_hunter.checkLastModified(mockPattern, {}); //assert - test.equals(mockPattern.lastModified, 100); + test.equal(mockPattern.lastModified, 100); test.end(); }); tap.test( 'checkLastModified - does not alter pattern if file not found', - function(test) { + function (test) { //arrange const mockPattern = { lastModified: 1010 }; //act changes_hunter.checkLastModified(mockPattern, null); //assert - test.equals(mockPattern.lastModified, 1010); + test.equal(mockPattern.lastModified, 1010); test.end(); } ); tap.test( 'checkLastModified - uses pattern.lastModified if greater than file time', - function(test) { + function (test) { //arrange const mockPattern = { lastModified: 101 }; //act changes_hunter.checkLastModified(mockPattern, {}); //assert - test.equals(mockPattern.lastModified, 101); + test.equal(mockPattern.lastModified, 101); test.end(); } ); diff --git a/packages/core/test/copier_tests.js b/packages/core/test/copier_tests.js index 388300a01..b7e57af3d 100644 --- a/packages/core/test/copier_tests.js +++ b/packages/core/test/copier_tests.js @@ -52,7 +52,7 @@ function createFakePatternLab(customProps) { tap.test( 'transformConfigPaths takes configuration.paths() and maps to a better key store', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({}); @@ -60,10 +60,10 @@ tap.test( var result = copier.transformConfigPaths(patternlab.config.paths); //assert - test.equals(result.img.source, './test/img'); - test.equals(result.img.public, './test/output/img'); - test.equals(result.css.source, './test/css'); - test.equals(result.css.public, './test/output/css'); + test.equal(result.img.source, './test/img'); + test.equal(result.img.public, './test/output/img'); + test.equal(result.css.source, './test/css'); + test.equal(result.css.public, './test/output/css'); test.end(); } ); diff --git a/packages/core/test/data_loader_tests.js b/packages/core/test/data_loader_tests.js index 9eaa8864b..2eae23311 100644 --- a/packages/core/test/data_loader_tests.js +++ b/packages/core/test/data_loader_tests.js @@ -2,12 +2,12 @@ const tap = require('tap'); -tap.test('loadDataFromFile - Load ', function(test) { +tap.test('loadDataFromFile - Load ', function (test) { const fs = require('fs-extra'), dataLoader = require('../src/lib/data_loader')(), data_dir = `${__dirname}/files/_data/`; let data = dataLoader.loadDataFromFile(data_dir + 'foo', fs); - test.equals(data.foo, 'bar'); + test.equal(data.foo, 'bar'); test.end(); }); diff --git a/packages/core/test/engine_handlebars_tests.js b/packages/core/test/engine_handlebars_tests.js index d268c1c63..8e5d3c34e 100644 --- a/packages/core/test/engine_handlebars_tests.js +++ b/packages/core/test/engine_handlebars_tests.js @@ -24,7 +24,7 @@ engineLoader.loadAllEngines(config); // don't run these tests unless handlebars is installed if (!engineLoader.handlebars) { - tap.test('Handlebars engine not installed, skipping tests.', function(test) { + tap.test('Handlebars engine not installed, skipping tests.', function (test) { test.end(); }); return; @@ -61,9 +61,9 @@ function testFindPartials(test, partialTests) { // setup current pattern from what we would have during execution // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html + // https://patternlab.io/docs/including-patterns/ var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.hbs', // relative path now + 'molecules/testing/test-mol.hbs', // relative path now null, // data { template: partialTests.join(), @@ -74,27 +74,27 @@ function testFindPartials(test, partialTests) { var results = currentPattern.findPartials(); // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); + test.equal(results.length, partialTests.length); + partialTests.forEach(function (testString, index) { + test.equal(results[index], testString); }); test.end(); } -tap.test('hello world handlebars pattern renders', function(test) { +tap.test('hello world handlebars pattern renders', function (test) { test.plan(1); - var patternPath = path.join('00-atoms', '00-global', '00-helloworld.hbs'); + var patternPath = path.join('atoms', 'global', 'helloworld.hbs'); // do all the normal processing of the pattern var patternlab = new fakePatternLab(); var helloWorldPattern = loadPattern(patternPath, patternlab); - processIterative(helloWorldPattern, patternlab).then(helloWorldPattern => { + processIterative(helloWorldPattern, patternlab).then((helloWorldPattern) => { processRecursive(patternPath, patternlab).then(() => { - helloWorldPattern.render().then(results => { - test.equals(results, 'Hello world!' + eol); + helloWorldPattern.render().then((results) => { + test.equal(results, 'Hello world!' + eol); test.end(); }); }); @@ -103,16 +103,12 @@ tap.test('hello world handlebars pattern renders', function(test) { tap.test( 'hello worlds handlebars pattern can see the atoms-helloworld partial and renders it twice', - function(test) { + function (test) { test.plan(1); // pattern paths - var pattern1Path = path.join('00-atoms', '00-global', '00-helloworld.hbs'); - var pattern2Path = path.join( - '00-molecules', - '00-global', - '00-helloworlds.hbs' - ); + var pattern1Path = path.join('atoms', 'global', 'helloworld.hbs'); + var pattern2Path = path.join('molecules', 'global', 'helloworlds.hbs'); // set up environment var patternlab = new fakePatternLab(); // environment @@ -128,8 +124,8 @@ tap.test( processRecursive(pattern1Path, patternlab).then(() => { processRecursive(pattern2Path, patternlab).then(() => { // test - pattern2.render().then(results => { - test.equals( + pattern2.render().then((results) => { + test.equal( results, 'Hello world!' + eol + ' and Hello world!' + eol + eol ); @@ -141,15 +137,11 @@ tap.test( } ); -tap.test('handlebars partials can render JSON values', function(test) { +tap.test('handlebars partials can render JSON values', function (test) { test.plan(1); // pattern paths - var pattern1Path = path.join( - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' - ); + var pattern1Path = path.join('atoms', 'global', 'helloworld-withdata.hbs'); // set up environment var patternlab = new fakePatternLab(); // environment @@ -160,8 +152,8 @@ tap.test('handlebars partials can render JSON values', function(test) { processIterative(helloWorldWithData, patternlab).then(() => { processRecursive(pattern1Path, patternlab).then(() => { // test - helloWorldWithData.render().then(results => { - test.equals( + helloWorldWithData.render().then((results) => { + test.equal( results, 'Hello world!' + eol + @@ -176,19 +168,15 @@ tap.test('handlebars partials can render JSON values', function(test) { tap.test( 'handlebars partials use the JSON environment from the calling pattern and can accept passed parameters', - function(test) { + function (test) { test.plan(1); // pattern paths - var atomPath = path.join( - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' - ); + var atomPath = path.join('atoms', 'global', 'helloworld-withdata.hbs'); var molPath = path.join( - '00-molecules', - '00-global', - '00-call-atom-with-molecule-data.hbs' + 'molecules', + 'global', + 'call-atom-with-molecule-data.hbs' ); // set up environment @@ -204,9 +192,9 @@ tap.test( processRecursive(atomPath, patternlab), processRecursive(molPath, patternlab), ]).then(() => { - mol.render().then(results => { + mol.render().then((results) => { // test - test.equals( + test.equal( results, '

Call with default JSON environment:

' + eol + @@ -229,7 +217,7 @@ tap.test( } ); -tap.only('find_pattern_partials finds partials', function(test) { +tap.only('find_pattern_partials finds partials', function (test) { testFindPartials(test, [ '{{> molecules-comment-header}}', '{{> molecules-comment-header}}', @@ -239,20 +227,20 @@ tap.only('find_pattern_partials finds partials', function(test) { ]); }); -tap.test('find_pattern_partials finds verbose partials', function(test) { +tap.test('find_pattern_partials finds verbose partials', function (test) { testFindPartials(test, [ - '{{> 01-molecules/06-components/03-comment-header.hbs }}', - "{{> 01-molecules/06-components/02-single-comment.hbs(description: 'A life is like a garden. Perfect moments can be had, but not preserved, except in memory.') }}", + '{{> molecules/components/comment-header.hbs }}', + "{{> molecules/components/single-comment.hbs(description: 'A life is like a garden. Perfect moments can be had, but not preserved, except in memory.') }}", '{{> molecules-single-comment:foo }}', "{{>atoms-error(message: 'That's no moon...')}}", "{{> atoms-error(message: 'That's no moon...') }}", - '{{> 00-atoms/00-global/06-test }}', + '{{> atoms/global/test }}', ]); }); tap.test( 'find_pattern_partials finds simple partials with parameters', - function(test) { + function (test) { testFindPartials(test, [ "{{> molecules-single-comment(description: 'A life isn't like a garden. Perfect moments can be had, but not preserved, except in memory.') }}", '{{> molecules-single-comment(description:"A life is like a "garden". Perfect moments can be had, but not preserved, except in memory.") }}', @@ -260,16 +248,9 @@ tap.test( } ); -tap.test( - 'find_pattern_partials finds simple partials with style modifiers', - function(test) { - testFindPartials(test, ['{{> molecules-single-comment:foo }}']); - } -); - tap.test( 'find_pattern_partials finds partials with handlebars parameters', - function(test) { + function (test) { testFindPartials(test, [ '{{> atoms-title title="bravo" headingLevel="2" headingSize="bravo" position="left"}}', '{{> atoms-title title="bravo"' + @@ -289,15 +270,16 @@ tap.test( } ); -tap.test('find_pattern_partials finds handlebars block partials', function( - test -) { - testFindPartials(test, ['{{#> myPartial }}']); -}); +tap.test( + 'find_pattern_partials finds handlebars block partials', + function (test) { + testFindPartials(test, ['{{#> myPartial }}']); + } +); tap.only( 'hidden handlebars patterns can be called by their nice names', - function(test) { + function (test) { //arrange const testPatternsPath = path.resolve( __dirname, @@ -306,15 +288,11 @@ tap.only( ); const pl = util.fakePatternLab(testPatternsPath); - var hiddenPatternPath = path.join( - '00-atoms', - '00-global', - '_00-hidden.hbs' - ); + var hiddenPatternPath = path.join('atoms', 'global', '_hidden.hbs'); var testPatternPath = path.join( - '00-molecules', - '00-global', - '00-hidden-pattern-tester.hbs' + 'molecules', + 'global', + 'hidden-pattern-tester.hbs' ); var hiddenPattern = loadPattern(hiddenPatternPath, pl); @@ -326,9 +304,9 @@ tap.only( processRecursive(hiddenPatternPath, pl), processRecursive(testPatternPath, pl), ]).then(() => { - testPattern.render().then(results => { + testPattern.render().then((results) => { //act - test.equals( + test.equal( util.sanitized(results), util.sanitized("Here's the hidden atom: [I'm the hidden atom\n]\n") ); @@ -340,14 +318,10 @@ tap.only( tap.test( '@partial-block template should render without throwing (@geoffp repo issue #3)', - function(test) { + function (test) { test.plan(1); - var patternPath = path.join( - '00-atoms', - '00-global', - '10-at-partial-block.hbs' - ); + var patternPath = path.join('atoms', 'global', 'at-partial-block.hbs'); // do all the normal processing of the pattern var patternlab = new fakePatternLab(); @@ -355,7 +329,7 @@ tap.test( processIterative(atPartialBlockPattern, patternlab).then(() => { processRecursive(patternPath, patternlab).then(() => { - atPartialBlockPattern.render().then(results => { + atPartialBlockPattern.render().then((results) => { var expectedResults = '{{> @partial-block }}' + eol + 'It worked!' + eol; test.equal(results, expectedResults); @@ -367,19 +341,15 @@ tap.test( tap.test( 'A template calling a @partial-block template should render correctly', - function(test) { + function (test) { test.plan(1); // pattern paths - var pattern1Path = path.join( - '00-atoms', - '00-global', - '10-at-partial-block.hbs' - ); + var pattern1Path = path.join('atoms', 'global', 'at-partial-block.hbs'); var pattern2Path = path.join( - '00-molecules', - '00-global', - '10-call-at-partial-block.hbs' + 'molecules', + 'global', + 'call-at-partial-block.hbs' ); // set up environment @@ -395,10 +365,10 @@ tap.test( processRecursive(pattern1Path, patternlab), processRecursive(pattern2Path, patternlab), ]).then(() => { - callAtPartialBlockPattern.render().then(results => { + callAtPartialBlockPattern.render().then((results) => { // test var expectedResults = 'Hello World!' + eol + 'It worked!' + eol; - test.equals(results, expectedResults); + test.equal(results, expectedResults); }); }); } diff --git a/packages/core/test/engine_liquid_tests.js b/packages/core/test/engine_liquid_tests.js index 9036dbca1..7aefb6e03 100644 --- a/packages/core/test/engine_liquid_tests.js +++ b/packages/core/test/engine_liquid_tests.js @@ -12,7 +12,7 @@ var eol = require('os').EOL; // don't run these tests unless liquid is installed var engineLoader = require('../src/lib/pattern_engines'); if (!engineLoader.liquid) { - tap.test('Liquid engine not installed, skipping tests.', function(test) { + tap.test('Liquid engine not installed, skipping tests.', function (test) { test.end(); }); return; @@ -49,9 +49,9 @@ function testFindPartials(test, partialTests) { // setup current pattern from what we would have during execution // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html + // https://patternlab.io/docs/including-patterns/ var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.liquid', // relative path now + 'molecules/testing/test-mol.liquid', // relative path now null, // data { template: partialTests.join(), @@ -62,18 +62,18 @@ function testFindPartials(test, partialTests) { var results = currentPattern.findPartials(); // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); + test.equal(results.length, partialTests.length); + partialTests.forEach(function (testString, index) { + test.equal(results[index], testString); }); test.end(); } -tap.test('button liquid pattern renders', function(test) { +tap.test('button liquid pattern renders', function (test) { test.plan(1); - var patternPath = path.join('00-atoms', '00-general', '08-button.liquid'); + var patternPath = path.join('atoms', 'general', 'button.liquid'); var expectedValue = '\n\n\n\n\n
\n \n\n \n\nButton\n\n\n
\n\n \n \n\n

Oh, hello world!

\n
\n
\n'; + '\n\n\n\n\n
\n \n\n \n\nButton\n\n\n
\n\n \n \n\n

Oh, hello world!

\n
\n
\n'; // set up environment var patternlab = new fakePatternLab(); // environment @@ -153,7 +145,7 @@ tap.test( // test // this pattern is too long - so just remove line endings on both sides and compare output - test.equals( + test.equal( mediaObjectPattern.render().replace(/\r?\n|\r/gm, ''), expectedValue.replace(/\r?\n|\r/gm, '') ); @@ -161,55 +153,57 @@ tap.test( } ); -tap.test('liquid partials can render JSON values', { skip: true }, function( - test -) { - test.plan(1); +tap.test( + 'liquid partials can render JSON values', + { skip: true }, + function (test) { + test.plan(1); - // pattern paths - var pattern1Path = path.resolve( - testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' - ); + // pattern paths + var pattern1Path = path.resolve( + testPatternsPath, + 'atoms', + 'global', + 'helloworld-withdata.hbs' + ); - // set up environment - var patternlab = new fakePatternLab(); // environment + // set up environment + var patternlab = new fakePatternLab(); // environment - // do all the normal processing of the pattern - var helloWorldWithData = assembler.process_pattern_iterative( - pattern1Path, - patternlab - ); - assembler.process_pattern_recursive(pattern1Path, patternlab); + // do all the normal processing of the pattern + var helloWorldWithData = assembler.process_pattern_iterative( + pattern1Path, + patternlab + ); + assembler.process_pattern_recursive(pattern1Path, patternlab); - // test - test.equals( - helloWorldWithData.render(), - 'Hello world!\nYeah, we got the subtitle from the JSON.\n' - ); - test.end(); -}); + // test + test.equal( + helloWorldWithData.render(), + 'Hello world!\nYeah, we got the subtitle from the JSON.\n' + ); + test.end(); + } +); tap.test( 'liquid partials use the JSON environment from the calling pattern and can accept passed parameters', { skip: true }, - function(test) { + function (test) { test.plan(1); // pattern paths var atomPath = path.resolve( testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' + 'atoms', + 'global', + 'helloworld-withdata.hbs' ); var molPath = path.resolve( testPatternsPath, - '00-molecules', - '00-global', - '00-call-atom-with-molecule-data.hbs' + 'molecules', + 'global', + 'call-atom-with-molecule-data.hbs' ); // set up environment @@ -222,7 +216,7 @@ tap.test( assembler.process_pattern_recursive(molPath, patternlab); // test - test.equals( + test.equal( mol.render(), '

Call with default JSON environment:

\nThis is Hello world!\nfrom the default JSON.\n\n\n

Call with passed parameter:

\nHowever, this is Hello world!\nfrom a totally different blob.\n\n' ); @@ -230,7 +224,7 @@ tap.test( } ); -tap.test('find_pattern_partials finds partials', function(test) { +tap.test('find_pattern_partials finds partials', function (test) { testFindPartials(test, [ '{% include "atoms-image" %}', "{% include 'atoms-image' %}", @@ -241,16 +235,16 @@ tap.test('find_pattern_partials finds partials', function(test) { ]); }); -tap.test('find_pattern_partials finds verbose partials', function(test) { +tap.test('find_pattern_partials finds verbose partials', function (test) { testFindPartials(test, [ - "{% include '01-molecules/06-components/03-comment-header.liquid' %}", - "{% include '00-atoms/00-global/06-test' %}", + "{% include 'molecules/components/comment-header.liquid' %}", + "{% include 'atoms/global/test' %}", ]); }); tap.test( 'find_pattern_partials finds partials with liquid parameters', - function(test) { + function (test) { testFindPartials(test, [ "{% include 'molecules-template' with {'foo': 'bar'} %}", "{% include 'molecules-template' with vars %}", diff --git a/packages/core/test/engine_mustache_tests.js b/packages/core/test/engine_mustache_tests.js index 8f0241d24..dd5e3fb19 100644 --- a/packages/core/test/engine_mustache_tests.js +++ b/packages/core/test/engine_mustache_tests.js @@ -13,7 +13,7 @@ var config = require('./util/patternlab-config.json'); var engineLoader = require('../src/lib/pattern_engines'); engineLoader.loadAllEngines(config); if (!engineLoader.mustache) { - tap.test('Mustache engine not installed, skipping tests.', function(test) { + tap.test('Mustache engine not installed, skipping tests.', function (test) { test.end(); }); return; @@ -50,9 +50,9 @@ function testFindPartials(test, partialTests) { // setup current pattern from what we would have during execution // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html + // https://patternlab.io/docs/including-patterns/ var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.mustache', // relative path now + 'molecules/testing/test-mol.mustache', // relative path now null, // data { template: partialTests.join(eol), @@ -63,35 +63,9 @@ function testFindPartials(test, partialTests) { var results = currentPattern.findPartials(); // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); - }); - - test.end(); -} - -function testFindPartialsWithStyleModifiers(test, partialTests) { - test.plan(partialTests.length + 1); - - // setup current pattern from what we would have during execution - // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html - var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.mustache', // relative path now - null, // data - { - template: partialTests.join(eol), - } - ); - - // act - var results = currentPattern.findPartialsWithStyleModifiers(); - - // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); + test.equal(results.length, partialTests.length); + partialTests.forEach(function (testString, index) { + test.equal(results[index], testString); }); test.end(); @@ -102,9 +76,9 @@ function testFindPartialsWithPatternParameters(test, partialTests) { // setup current pattern from what we would have during execution // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html + // https://patternlab.io/docs/including-patterns/ var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.mustache', // relative path now + 'molecules/testing/test-mol.mustache', // relative path now null, // data { template: partialTests.join(eol), @@ -115,21 +89,21 @@ function testFindPartialsWithPatternParameters(test, partialTests) { var results = currentPattern.findPartialsWithPatternParameters(); // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); + test.equal(results.length, partialTests.length); + partialTests.forEach(function (testString, index) { + test.equal(results[index], testString); }); test.end(); } -tap.test('find_pattern_partials finds one simple partial', function(test) { +tap.test('find_pattern_partials finds one simple partial', function (test) { testFindPartials(test, ['{{> molecules-comment-header}}']); }); tap.test( 'find_pattern_partials finds simple partials under stressed circumstances', - function(test) { + function (test) { testFindPartials(test, [ '{{>molecules-comment-header}}', '{{> ' + eol + ' molecules-comment-header' + eol + '}}', @@ -138,86 +112,38 @@ tap.test( } ); -tap.test('find_pattern_partials finds one simple verbose partial', function( - test -) { - testFindPartials(test, ['{{> 00-atoms/00-global/06-test }}']); -}); - -tap.test('find_pattern_partials finds partials with parameters', function( - test -) { - testFindPartials(test, [ - '{{> molecules-single-comment(description: true) }}', - '{{> molecules-single-comment(description: 42) }}', - "{{> molecules-single-comment(description: '42') }}", - '{{> molecules-single-comment(description: "42") }}', - "{{> molecules-single-comment(description: 'test', anotherThing: 'retest') }}", - '{{> molecules-single-comment(description: false, anotherThing: "retest") }}', - '{{> molecules-single-comment(description:"A life is like a "garden". Perfect moments can be had, but not preserved, except in memory.") }}', - ]); -}); +tap.test( + 'find_pattern_partials finds one simple verbose partial', + function (test) { + testFindPartials(test, ['{{> atoms/global/test }}']); + } +); tap.test( - 'find_pattern_partials finds simple partials with style modifiers', - function(test) { + 'find_pattern_partials finds partials with parameters', + function (test) { testFindPartials(test, [ - '{{> molecules-single-comment:foo }}', - '{{> molecules-single-comment:foo|bar }}', + '{{> molecules-single-comment(description: true) }}', + '{{> molecules-single-comment(description: 42) }}', + "{{> molecules-single-comment(description: '42') }}", + '{{> molecules-single-comment(description: "42") }}', + "{{> molecules-single-comment(description: 'test', anotherThing: 'retest') }}", + '{{> molecules-single-comment(description: false, anotherThing: "retest") }}', + '{{> molecules-single-comment(description:"A life is like a "garden". Perfect moments can be had, but not preserved, except in memory.") }}', ]); } ); -tap.test('find_pattern_partials finds mixed partials', function(test) { +tap.test('find_pattern_partials finds mixed partials', function (test) { testFindPartials(test, [ '{{> molecules-single-comment:foo(description: "test", anotherThing: true) }}', '{{> molecules-single-comment:foo|bar(description: true) }}', ]); }); -tap.test( - 'find_pattern_partials finds one simple partial with styleModifier', - function(test) { - testFindPartialsWithStyleModifiers(test, [ - '{{> molecules-comment-header:test}}', - ]); - } -); - -tap.test( - 'find_pattern_partials finds partial with many styleModifiers', - function(test) { - testFindPartialsWithStyleModifiers(test, [ - '{{> molecules-comment-header:test|test2|test3}}', - ]); - } -); - -tap.test( - 'find_pattern_partials finds partials with differing styleModifiers', - function(test) { - testFindPartialsWithStyleModifiers(test, [ - '{{> molecules-comment-header:test|test2|test3}}', - '{{> molecules-comment-header:foo-1}}', - '{{> molecules-comment-header:bar_1}}', - ]); - } -); - -tap.test( - 'find_pattern_partials finds partials with styleModifiers when parameters present', - function(test) { - testFindPartialsWithStyleModifiers(test, [ - '{{> molecules-comment-header:test|test2|test3(description: true)}}', - "{{> molecules-comment-header:foo-1(description: 'foo')}}", - "{{> molecules-comment-header:bar_1(descrition: 'bar', anotherThing: 10102010) }}", - ]); - } -); - tap.test( 'find_pattern_partials_with_parameters finds one simple partial with parameters', - function(test) { + function (test) { testFindPartialsWithPatternParameters(test, [ "{{> molecules-comment-header(description: 'test')}}", ]); @@ -226,7 +152,7 @@ tap.test( tap.test( 'find_pattern_partials_with_parameters finds partials with parameters', - function(test) { + function (test) { testFindPartialsWithPatternParameters(test, [ '{{> molecules-single-comment(description: true) }}', '{{> molecules-single-comment(description: 42) }}', @@ -238,14 +164,3 @@ tap.test( ]); } ); - -tap.test( - 'find_pattern_partials finds partials with parameters when styleModifiers present', - function(test) { - testFindPartialsWithPatternParameters(test, [ - '{{> molecules-comment-header:test|test2|test3(description: true)}}', - "{{> molecules-comment-header:foo-1(description: 'foo')}}", - "{{> molecules-comment-header:bar_1(descrition: 'bar', anotherThing: 10102010) }}", - ]); - } -); diff --git a/packages/core/test/engine_react_tests.js b/packages/core/test/engine_react_tests.js index 2d271bb9b..8e34d5338 100644 --- a/packages/core/test/engine_react_tests.js +++ b/packages/core/test/engine_react_tests.js @@ -15,33 +15,33 @@ engineLoader.loadAllEngines(config); // don't run these tests unless the react engine is installed if (!engineLoader.react) { - tap.test('React engine not installed, skipping tests.', test => { + tap.test('React engine not installed, skipping tests.', (test) => { test.end(); }); } else { const fpl = testUtils.fakePatternLab(testPatternsPath); - tap.test('Load the hello world pattern and verify contents', test => { + tap.test('Load the hello world pattern and verify contents', (test) => { const patternPath = path.join( testPatternsPath, - '00-atoms/00-general/HelloWorld.jsx' + 'atoms/general/HelloWorld.jsx' ); const patternContent = fs.readFileSync(patternPath, { encoding: 'utf8' }); const pattern = loadPattern(patternPath, fpl); - test.equals(pattern.template, patternContent); + test.equal(pattern.template, patternContent); test.end(); }); - tap.test('Load the hello world pattern and verify output', test => { + tap.test('Load the hello world pattern and verify output', (test) => { const patternPath = path.join( testPatternsPath, - '00-atoms/00-general/HelloWorld.jsx' + 'atoms/general/HelloWorld.jsx' ); const pattern = loadPattern(patternPath, fpl); - return pattern.render().then(output => { - test.equals(output, '
Hello world!
\n'); + return pattern.render().then((output) => { + test.equal(output, '
Hello world!
\n'); }); }); } diff --git a/packages/core/test/engine_twig_tests.js b/packages/core/test/engine_twig_tests.js index 33a49bbe9..d631a4020 100644 --- a/packages/core/test/engine_twig_tests.js +++ b/packages/core/test/engine_twig_tests.js @@ -12,7 +12,7 @@ var eol = require('os').EOL; // don't run these tests unless twig is installed var engineLoader = require('../src/lib/pattern_engines'); if (!engineLoader.twig) { - tap.test('Twig engine not installed, skipping tests.', function(test) { + tap.test('Twig engine not installed, skipping tests.', function (test) { test.end(); }); return; @@ -49,9 +49,9 @@ function testFindPartials(test, partialTests) { // setup current pattern from what we would have during execution // docs on partial syntax are here: - // http://patternlab.io/docs/pattern-including.html + // https://patternlab.io/docs/including-patterns/ var currentPattern = Pattern.create( - '01-molecules/00-testing/00-test-mol.twig', // relative path now + 'molecules/testing/test-mol.twig', // relative path now null, // data { template: partialTests.join(), @@ -62,18 +62,18 @@ function testFindPartials(test, partialTests) { var results = currentPattern.findPartials(); // assert - test.equals(results.length, partialTests.length); - partialTests.forEach(function(testString, index) { - test.equals(results[index], testString); + test.equal(results.length, partialTests.length); + partialTests.forEach(function (testString, index) { + test.equal(results[index], testString); }); test.end(); } -tap.test('button twig pattern renders', function(test) { +tap.test('button twig pattern renders', function (test) { test.plan(1); - var patternPath = path.join('00-atoms', '00-general', '08-button.twig'); + var patternPath = path.join('atoms', 'general', 'button.twig'); var expectedValue = '\n\n\n\n\n
\n \n\n \n\nButton\n\n\n
\n\n \n \n\n

Oh, hello world!

\n
\n
\n'; + '\n\n\n\n\n
\n \n\n \n\nButton\n\n\n
\n\n \n \n\n

Oh, hello world!

\n
\n
\n'; // set up environment var patternlab = new fakePatternLab(); // environment @@ -149,7 +145,7 @@ tap.test( // test // this pattern is too long - so just remove line endings on both sides and compare output - test.equals( + test.equal( mediaObjectPattern.render().replace(/\r?\n|\r/gm, ''), expectedValue.replace(/\r?\n|\r/gm, '') ); @@ -157,55 +153,57 @@ tap.test( } ); -tap.test('twig partials can render JSON values', { skip: true }, function( - test -) { - test.plan(1); +tap.test( + 'twig partials can render JSON values', + { skip: true }, + function (test) { + test.plan(1); - // pattern paths - var pattern1Path = path.resolve( - testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' - ); + // pattern paths + var pattern1Path = path.resolve( + testPatternsPath, + 'atoms', + 'global', + 'helloworld-withdata.hbs' + ); - // set up environment - var patternlab = new fakePatternLab(); // environment + // set up environment + var patternlab = new fakePatternLab(); // environment - // do all the normal processing of the pattern - var helloWorldWithData = assembler.process_pattern_iterative( - pattern1Path, - patternlab - ); - assembler.process_pattern_recursive(pattern1Path, patternlab); + // do all the normal processing of the pattern + var helloWorldWithData = assembler.process_pattern_iterative( + pattern1Path, + patternlab + ); + assembler.process_pattern_recursive(pattern1Path, patternlab); - // test - test.equals( - helloWorldWithData.render(), - 'Hello world!\nYeah, we got the subtitle from the JSON.\n' - ); - test.end(); -}); + // test + test.equal( + helloWorldWithData.render(), + 'Hello world!\nYeah, we got the subtitle from the JSON.\n' + ); + test.end(); + } +); tap.test( 'twig partials use the JSON environment from the calling pattern and can accept passed parameters', { skip: true }, - function(test) { + function (test) { test.plan(1); // pattern paths var atomPath = path.resolve( testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld-withdata.hbs' + 'atoms', + 'global', + 'helloworld-withdata.hbs' ); var molPath = path.resolve( testPatternsPath, - '00-molecules', - '00-global', - '00-call-atom-with-molecule-data.hbs' + 'molecules', + 'global', + 'call-atom-with-molecule-data.hbs' ); // set up environment @@ -218,7 +216,7 @@ tap.test( assembler.process_pattern_recursive(molPath, patternlab); // test - test.equals( + test.equal( mol.render(), '

Call with default JSON environment:

\nThis is Hello world!\nfrom the default JSON.\n\n\n

Call with passed parameter:

\nHowever, this is Hello world!\nfrom a totally different blob.\n\n' ); @@ -226,7 +224,7 @@ tap.test( } ); -tap.test('find_pattern_partials finds partials', function(test) { +tap.test('find_pattern_partials finds partials', function (test) { testFindPartials(test, [ '{% include "atoms-image" %}', "{% include 'atoms-image' %}", @@ -237,20 +235,21 @@ tap.test('find_pattern_partials finds partials', function(test) { ]); }); -tap.test('find_pattern_partials finds verbose partials', function(test) { +tap.test('find_pattern_partials finds verbose partials', function (test) { testFindPartials(test, [ - "{% include '01-molecules/06-components/03-comment-header.twig' %}", - "{% include '00-atoms/00-global/06-test' %}", + "{% include 'molecules/components/comment-header.twig' %}", + "{% include 'atoms/global/test' %}", ]); }); -tap.test('find_pattern_partials finds partials with twig parameters', function( - test -) { - testFindPartials(test, [ - "{% include 'molecules-template' with {'foo': 'bar'} %}", - "{% include 'molecules-template' with vars %}", - "{% include 'molecules-template.twig' with {'foo': 'bar'} only %}", - "{% include 'organisms-sidebar' ignore missing with {'foo': 'bar'} %}", - ]); -}); +tap.test( + 'find_pattern_partials finds partials with twig parameters', + function (test) { + testFindPartials(test, [ + "{% include 'molecules-template' with {'foo': 'bar'} %}", + "{% include 'molecules-template' with vars %}", + "{% include 'molecules-template.twig' with {'foo': 'bar'} only %}", + "{% include 'organisms-sidebar' ignore missing with {'foo': 'bar'} %}", + ]); + } +); diff --git a/packages/core/test/engine_underscore_tests.js b/packages/core/test/engine_underscore_tests.js index fbdbb5617..a944e830b 100644 --- a/packages/core/test/engine_underscore_tests.js +++ b/packages/core/test/engine_underscore_tests.js @@ -14,7 +14,7 @@ var eol = require('os').EOL; // don't run tests unless underscore is installed var engineLoader = require('../src/lib/pattern_engines'); if (!engineLoader.underscore) { - tap.test('Underscore engine not installed, skipping tests', function(test) { + tap.test('Underscore engine not installed, skipping tests', function (test) { test.end(); }); return; @@ -45,14 +45,14 @@ function fakePatternLab() { return fpl; } -tap.test('hello world underscore pattern renders', function(test) { +tap.test('hello world underscore pattern renders', function (test) { test.plan(1); var patternPath = path.resolve( testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld.html' + 'atoms', + 'global', + 'helloworld.html' ); // do all the normal processing of the pattern @@ -65,19 +65,19 @@ tap.test('hello world underscore pattern renders', function(test) { .then(() => { assembler.process_pattern_recursive(patternPath, patternlab); - test.equals(helloWorldPattern.render(), 'Hello world!' + eol); + test.equal(helloWorldPattern.render(), 'Hello world!' + eol); }); }); -tap.test('underscore partials can render JSON values', function(test) { +tap.test('underscore partials can render JSON values', function (test) { test.plan(1); // pattern paths var pattern1Path = path.resolve( testPatternsPath, - '00-atoms', - '00-global', - '00-helloworld-withdata.html' + 'atoms', + 'global', + 'helloworld-withdata.html' ); // set up environment @@ -91,7 +91,7 @@ tap.test('underscore partials can render JSON values', function(test) { assembler.process_pattern_recursive(pattern1Path, patternlab); // test - test.equals( + test.equal( helloWorldWithData.render(), 'Hello world!' + eol + 'Yeah, we got the subtitle from the JSON.' + eol ); @@ -100,7 +100,7 @@ tap.test('underscore partials can render JSON values', function(test) { tap.test( 'findPartial return the ID of the partial, given a whole partial call', - function(test) { + function (test) { var engineLoader = require('../src/lib/pattern_engines'); var underscoreEngine = engineLoader.underscore; @@ -108,7 +108,7 @@ tap.test( // do all the normal processing of the pattern // test - test.equals( + test.equal( underscoreEngine.findPartial( "<%= _.renderNamedPartial('molecules-details', obj) %>" ), @@ -120,7 +120,7 @@ tap.test( tap.test( 'hidden underscore patterns can be called by their nice names', - function(test) { + function (test) { const util = require('./util/test_utils.js'); //arrange @@ -131,15 +131,11 @@ tap.test( ); const pl = util.fakePatternLab(testPatternsPath); - var hiddenPatternPath = path.join( - '00-atoms', - '00-global', - '_00-hidden.html' - ); + var hiddenPatternPath = path.join('atoms', 'global', '_hidden.html'); var testPatternPath = path.join( - '00-molecules', - '00-global', - '00-hidden-pattern-tester.html' + 'molecules', + 'global', + 'hidden-pattern-tester.html' ); var hiddenPattern = loadPattern(hiddenPatternPath, pl); @@ -153,7 +149,7 @@ tap.test( pattern_assembler.process_pattern_recursive(testPatternPath, pl); //act - test.equals( + test.equal( util.sanitized(testPattern.render()), util.sanitized("Here's the hidden atom: [I'm the hidden atom\n]\n") ); diff --git a/packages/core/test/exportData_tests.js b/packages/core/test/exportData_tests.js index 93cd9573d..2443dde76 100644 --- a/packages/core/test/exportData_tests.js +++ b/packages/core/test/exportData_tests.js @@ -10,7 +10,7 @@ const util = require('./util/test_utils.js'); const testPatternsPath = path.resolve(__dirname, 'files', '_patterns'); const fsMock = { - outputFileSync: function(path, content) { + outputFileSync: function (path, content) { /* INTENTIONAL NOOP */ }, }; @@ -20,49 +20,78 @@ exportData.__set__({ fs: fsMock, }); -const patternlab = util.fakePatternLab(testPatternsPath); -const result = exportData(patternlab); +const uikitFoo = { + name: 'uikit-foo', + enabled: true, + outputDir: 'foo', + excludedPatternStates: ['legacy'], + excludedTags: ['baz'], +}; + +tap.test('exportData exports config', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); -tap.test('exportData exports config', function(test) { - test.equals(result.indexOf('config') > -1, true); - test.equals(result.indexOf('paths') > -1, true); - test.equals(result.indexOf('theme') > -1, true); + test.equal(result.indexOf('config') > -1, true); + test.equal(result.indexOf('paths') > -1, true); + test.equal(result.indexOf('theme') > -1, true); test.end(); }); -tap.test('exportData exports ishControls', function(test) { - test.equals(result.indexOf('ishControlsHide') > -1, true); +tap.test('exportData exports ishControls', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('ishControlsHide') > -1, true); test.end(); }); -tap.test('exportData exports navItems', function(test) { - test.equals(result.indexOf('patternTypes') > -1, true); +tap.test('exportData exports navItems', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('patternGroups') > -1, true); test.end(); }); -tap.test('exportData exports patternPaths', function(test) { - test.equals(result.indexOf('patternPaths') > -1, true); +tap.test('exportData exports patternPaths', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('patternPaths') > -1, true); test.end(); }); -tap.test('exportData exports viewAllPaths', function(test) { - test.equals(result.indexOf('viewAllPaths') > -1, true); +tap.test('exportData exports viewAllPaths', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('viewAllPaths') > -1, true); test.end(); }); -tap.test('exportData exports plugins', function(test) { - test.equals(result.indexOf('plugins') > -1, true); +tap.test('exportData exports plugins', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('plugins') > -1, true); test.end(); }); -tap.test('exportData exports defaultShowPatternInfo', function(test) { - test.equals(result.indexOf('defaultShowPatternInfo') > -1, true); - test.equals(result.indexOf('"defaultShowPatternInfo":false') > -1, true); +tap.test('exportData exports defaultShowPatternInfo', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('defaultShowPatternInfo') > -1, true); + test.equal(result.indexOf('"defaultShowPatternInfo":false') > -1, true); test.end(); }); -tap.test('exportData exports defaultPattern', function(test) { - test.equals(result.indexOf('defaultPattern') > -1, true); - test.equals(result.indexOf('"defaultPattern":"all"') > -1, true); +tap.test('exportData exports defaultPattern', function (test) { + const patternlab = util.fakePatternLab(testPatternsPath); + const result = exportData(patternlab, uikitFoo); + + test.equal(result.indexOf('defaultPattern') > -1, true); + test.equal(result.indexOf('"defaultPattern":"all"') > -1, true); test.end(); }); diff --git a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld-withdata.hbs b/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld-withdata.hbs deleted file mode 100644 index 3cfaf83c0..000000000 --- a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld-withdata.hbs +++ /dev/null @@ -1,2 +0,0 @@ -Hello world! -{{ subtitle }} diff --git a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/_00-hidden.hbs b/packages/core/test/files/_handlebars-test-patterns/atoms/global/_hidden.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/_00-hidden.hbs rename to packages/core/test/files/_handlebars-test-patterns/atoms/global/_hidden.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/10-at-partial-block.hbs b/packages/core/test/files/_handlebars-test-patterns/atoms/global/at-partial-block.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/10-at-partial-block.hbs rename to packages/core/test/files/_handlebars-test-patterns/atoms/global/at-partial-block.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld-withdata.hbs b/packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld-withdata.hbs new file mode 100644 index 000000000..30c6ff45a --- /dev/null +++ b/packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld-withdata.hbs @@ -0,0 +1,2 @@ +Hello world! +{{subtitle}} diff --git a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld-withdata.json b/packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld-withdata.json similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld-withdata.json rename to packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld-withdata.json diff --git a/packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld.hbs b/packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-atoms/00-global/00-helloworld.hbs rename to packages/core/test/files/_handlebars-test-patterns/atoms/global/helloworld.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/10-call-at-partial-block.hbs b/packages/core/test/files/_handlebars-test-patterns/molecules/global/call-at-partial-block.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/10-call-at-partial-block.hbs rename to packages/core/test/files/_handlebars-test-patterns/molecules/global/call-at-partial-block.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.hbs b/packages/core/test/files/_handlebars-test-patterns/molecules/global/call-atom-with-molecule-data.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.hbs rename to packages/core/test/files/_handlebars-test-patterns/molecules/global/call-atom-with-molecule-data.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.json b/packages/core/test/files/_handlebars-test-patterns/molecules/global/call-atom-with-molecule-data.json similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.json rename to packages/core/test/files/_handlebars-test-patterns/molecules/global/call-atom-with-molecule-data.json diff --git a/packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-helloworlds.hbs b/packages/core/test/files/_handlebars-test-patterns/molecules/global/helloworlds.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-helloworlds.hbs rename to packages/core/test/files/_handlebars-test-patterns/molecules/global/helloworlds.hbs diff --git a/packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-hidden-pattern-tester.hbs b/packages/core/test/files/_handlebars-test-patterns/molecules/global/hidden-pattern-tester.hbs similarity index 100% rename from packages/core/test/files/_handlebars-test-patterns/00-molecules/00-global/00-hidden-pattern-tester.hbs rename to packages/core/test/files/_handlebars-test-patterns/molecules/global/hidden-pattern-tester.hbs diff --git a/packages/core/test/files/_liquid_test-patterns/00-atoms/00-general/09-image.liquid b/packages/core/test/files/_liquid_test-patterns/00-atoms/00-general/09-image.liquid deleted file mode 100644 index 01c4af9f8..000000000 --- a/packages/core/test/files/_liquid_test-patterns/00-atoms/00-general/09-image.liquid +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/packages/core/test/files/_liquid_test-patterns/00-atoms/00-general/08-button.liquid b/packages/core/test/files/_liquid_test-patterns/atoms/general/button.liquid similarity index 100% rename from packages/core/test/files/_liquid_test-patterns/00-atoms/00-general/08-button.liquid rename to packages/core/test/files/_liquid_test-patterns/atoms/general/button.liquid diff --git a/packages/core/test/files/_liquid_test-patterns/atoms/general/image.liquid b/packages/core/test/files/_liquid_test-patterns/atoms/general/image.liquid new file mode 100644 index 000000000..320401c8e --- /dev/null +++ b/packages/core/test/files/_liquid_test-patterns/atoms/general/image.liquid @@ -0,0 +1,5 @@ + diff --git a/packages/core/test/files/_liquid_test-patterns/00-molecules/00-general/00-media-object.liquid b/packages/core/test/files/_liquid_test-patterns/molecules/general/media-object.liquid similarity index 100% rename from packages/core/test/files/_liquid_test-patterns/00-molecules/00-general/00-media-object.liquid rename to packages/core/test/files/_liquid_test-patterns/molecules/general/media-object.liquid diff --git a/packages/core/test/files/_meta/_01-foot.hbs b/packages/core/test/files/_meta/_foot.hbs similarity index 100% rename from packages/core/test/files/_meta/_01-foot.hbs rename to packages/core/test/files/_meta/_foot.hbs diff --git a/packages/core/test/files/_meta/_01-foot.html b/packages/core/test/files/_meta/_foot.html similarity index 100% rename from packages/core/test/files/_meta/_01-foot.html rename to packages/core/test/files/_meta/_foot.html diff --git a/packages/development-edition-engine-handlebars/source/_meta/_01-foot.hbs b/packages/core/test/files/_meta/_foot.mustache similarity index 100% rename from packages/development-edition-engine-handlebars/source/_meta/_01-foot.hbs rename to packages/core/test/files/_meta/_foot.mustache diff --git a/packages/core/test/files/_meta/_00-head.hbs b/packages/core/test/files/_meta/_head.hbs similarity index 94% rename from packages/core/test/files/_meta/_00-head.hbs rename to packages/core/test/files/_meta/_head.hbs index b1f5c1ce0..d2b1ea726 100644 --- a/packages/core/test/files/_meta/_00-head.hbs +++ b/packages/core/test/files/_meta/_head.hbs @@ -2,7 +2,7 @@ {{ title }} - + diff --git a/packages/development-edition-engine-react/source/_meta/_00-head.hbs b/packages/core/test/files/_meta/_head.html similarity index 55% rename from packages/development-edition-engine-react/source/_meta/_00-head.hbs rename to packages/core/test/files/_meta/_head.html index cf826617a..56d9a2432 100644 --- a/packages/development-edition-engine-react/source/_meta/_00-head.hbs +++ b/packages/core/test/files/_meta/_head.html @@ -1,16 +1,23 @@ - - - - {{ title }} - - - - - - - - {{{ patternLabHead }}} - - - - + + + + {{ title }} + + + + + + + + {{{ patternLabHead }}} + + + diff --git a/packages/edition-node-gulp/source/_meta/_00-head.mustache b/packages/core/test/files/_meta/_head.mustache similarity index 94% rename from packages/edition-node-gulp/source/_meta/_00-head.mustache rename to packages/core/test/files/_meta/_head.mustache index 0001e7628..14a98f369 100644 --- a/packages/edition-node-gulp/source/_meta/_00-head.mustache +++ b/packages/core/test/files/_meta/_head.mustache @@ -2,7 +2,7 @@ {{ title }} - + diff --git a/packages/core/test/files/_patterns/00-test/03-styled-atom.mustache b/packages/core/test/files/_patterns/00-test/03-styled-atom.mustache deleted file mode 100644 index b736c06aa..000000000 --- a/packages/core/test/files/_patterns/00-test/03-styled-atom.mustache +++ /dev/null @@ -1,3 +0,0 @@ - - {{message}} - diff --git a/packages/core/test/files/_patterns/00-test/nav.json b/packages/core/test/files/_patterns/00-test/nav.json deleted file mode 100644 index 32a6c0952..000000000 --- a/packages/core/test/files/_patterns/00-test/nav.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "brad" : { - "url" : "link.twitter-brad" - }, - "dave" : { - "url" : "link.twitter-dave" - }, - "brian" : { - "url" : "link.twitter-brian" - } -} diff --git a/packages/core/test/files/_patterns/00-test/paramMiddle.mustache b/packages/core/test/files/_patterns/00-test/paramMiddle.mustache deleted file mode 100644 index 31169fb7e..000000000 --- a/packages/core/test/files/_patterns/00-test/paramMiddle.mustache +++ /dev/null @@ -1,3 +0,0 @@ -
- {{> test-link }} -
diff --git a/packages/core/test/files/_patterns/00-test/paramParent.mustache b/packages/core/test/files/_patterns/00-test/paramParent.mustache deleted file mode 100644 index bf4e84562..000000000 --- a/packages/core/test/files/_patterns/00-test/paramParent.mustache +++ /dev/null @@ -1 +0,0 @@ -{{> test-paramMiddle(styleModifier: "foo") }} diff --git a/packages/core/test/files/_patterns/00-test/sticky-comment-verbose.mustache b/packages/core/test/files/_patterns/00-test/sticky-comment-verbose.mustache deleted file mode 100644 index 55b21011d..000000000 --- a/packages/core/test/files/_patterns/00-test/sticky-comment-verbose.mustache +++ /dev/null @@ -1 +0,0 @@ -{{> 00-test/comment(description: 'A life is like a garden. Perfect moments can be had, but not preserved, except in memory.') }} diff --git a/packages/core/test/files/_patterns/orderTest/_orderTest.md b/packages/core/test/files/_patterns/orderTest/_orderTest.md new file mode 100644 index 000000000..c71e03c11 --- /dev/null +++ b/packages/core/test/files/_patterns/orderTest/_orderTest.md @@ -0,0 +1,3 @@ +--- +order: 1 +--- \ No newline at end of file diff --git a/packages/core/test/files/_meta/_00-head.mustache b/packages/core/test/files/_patterns/orderTest/a/a-test.mustache similarity index 100% rename from packages/core/test/files/_meta/_00-head.mustache rename to packages/core/test/files/_patterns/orderTest/a/a-test.mustache diff --git a/packages/core/test/files/_patterns/orderTest/b/_b.md b/packages/core/test/files/_patterns/orderTest/b/_b.md new file mode 100644 index 000000000..7017cea54 --- /dev/null +++ b/packages/core/test/files/_patterns/orderTest/b/_b.md @@ -0,0 +1,3 @@ +--- +order: 2 +--- \ No newline at end of file diff --git a/packages/core/test/files/_meta/_01-foot.mustache b/packages/core/test/files/_patterns/orderTest/b/b-test.mustache similarity index 100% rename from packages/core/test/files/_meta/_01-foot.mustache rename to packages/core/test/files/_patterns/orderTest/b/b-test.mustache diff --git a/packages/core/test/files/_patterns/orderTest/c/_c.md b/packages/core/test/files/_patterns/orderTest/c/_c.md new file mode 100644 index 000000000..4c2122185 --- /dev/null +++ b/packages/core/test/files/_patterns/orderTest/c/_c.md @@ -0,0 +1,3 @@ +--- +order: -1 +--- \ No newline at end of file diff --git a/packages/core/test/files/partials/patternSectionSubtype.mustache b/packages/core/test/files/_patterns/orderTest/c/c-test.mustache similarity index 100% rename from packages/core/test/files/partials/patternSectionSubtype.mustache rename to packages/core/test/files/_patterns/orderTest/c/c-test.mustache diff --git a/packages/core/test/files/_patterns/orderTest/c/subfolder/subfolder.mustache b/packages/core/test/files/_patterns/orderTest/c/subfolder/subfolder.mustache new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/test/files/_patterns/orderTest/orderTest.md b/packages/core/test/files/_patterns/orderTest/orderTest.md new file mode 100644 index 000000000..c71e03c11 --- /dev/null +++ b/packages/core/test/files/_patterns/orderTest/orderTest.md @@ -0,0 +1,3 @@ +--- +order: 1 +--- \ No newline at end of file diff --git a/packages/core/test/files/_patterns/00-test/_00-hidden-pattern.mustache b/packages/core/test/files/_patterns/test/_hidden-pattern.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/_00-hidden-pattern.mustache rename to packages/core/test/files/_patterns/test/_hidden-pattern.mustache diff --git a/packages/core/test/files/_patterns/00-test/_ignored-pattern.mustache b/packages/core/test/files/_patterns/test/_ignored-pattern.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/_ignored-pattern.mustache rename to packages/core/test/files/_patterns/test/_ignored-pattern.mustache diff --git a/packages/core/test/files/_patterns/00-test/539-a.mustache b/packages/core/test/files/_patterns/test/a.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/539-a.mustache rename to packages/core/test/files/_patterns/test/a.mustache diff --git a/packages/core/test/files/_patterns/00-test/12-another-styled-atom.mustache b/packages/core/test/files/_patterns/test/another-styled-atom.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/12-another-styled-atom.mustache rename to packages/core/test/files/_patterns/test/another-styled-atom.mustache diff --git a/packages/core/test/files/_patterns/00-test/539-b.mustache b/packages/core/test/files/_patterns/test/b.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/539-b.mustache rename to packages/core/test/files/_patterns/test/b.mustache diff --git a/packages/core/test/files/_patterns/00-test/01-bar.md b/packages/core/test/files/_patterns/test/bar.md similarity index 100% rename from packages/core/test/files/_patterns/00-test/01-bar.md rename to packages/core/test/files/_patterns/test/bar.md diff --git a/packages/core/test/files/_patterns/00-test/01-bar.mustache b/packages/core/test/files/_patterns/test/bar.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/01-bar.mustache rename to packages/core/test/files/_patterns/test/bar.mustache diff --git a/packages/core/test/files/_patterns/00-test/02-baz.md b/packages/core/test/files/_patterns/test/baz.md similarity index 100% rename from packages/core/test/files/_patterns/00-test/02-baz.md rename to packages/core/test/files/_patterns/test/baz.md diff --git a/packages/core/test/files/_patterns/00-test/02-baz.mustache b/packages/core/test/files/_patterns/test/baz.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/02-baz.mustache rename to packages/core/test/files/_patterns/test/baz.mustache diff --git a/packages/core/test/files/_patterns/00-test/11-bookend-listitem.mustache b/packages/core/test/files/_patterns/test/bookend-listitem.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/11-bookend-listitem.mustache rename to packages/core/test/files/_patterns/test/bookend-listitem.mustache diff --git a/packages/core/test/files/_patterns/00-test/08-bookend-params.mustache b/packages/core/test/files/_patterns/test/bookend-params.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/08-bookend-params.mustache rename to packages/core/test/files/_patterns/test/bookend-params.mustache diff --git a/packages/core/test/files/_patterns/00-test/09-bookend.mustache b/packages/core/test/files/_patterns/test/bookend.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/09-bookend.mustache rename to packages/core/test/files/_patterns/test/bookend.mustache diff --git a/packages/core/test/files/_patterns/00-test/539-c.mustache b/packages/core/test/files/_patterns/test/c.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/539-c.mustache rename to packages/core/test/files/_patterns/test/c.mustache diff --git a/packages/core/test/files/_patterns/00-test/comment-tag.mustache b/packages/core/test/files/_patterns/test/comment-tag.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/comment-tag.mustache rename to packages/core/test/files/_patterns/test/comment-tag.mustache diff --git a/packages/core/test/files/_patterns/00-test/comment.mustache b/packages/core/test/files/_patterns/test/comment.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/comment.mustache rename to packages/core/test/files/_patterns/test/comment.mustache diff --git a/packages/core/test/files/_patterns/00-test/00-foo.md b/packages/core/test/files/_patterns/test/foo.md similarity index 100% rename from packages/core/test/files/_patterns/00-test/00-foo.md rename to packages/core/test/files/_patterns/test/foo.md diff --git a/packages/core/test/files/_patterns/00-test/00-foo.mustache b/packages/core/test/files/_patterns/test/foo.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/00-foo.mustache rename to packages/core/test/files/_patterns/test/foo.mustache diff --git a/packages/core/test/files/_patterns/00-test/04-group.mustache b/packages/core/test/files/_patterns/test/group.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/04-group.mustache rename to packages/core/test/files/_patterns/test/group.mustache diff --git a/packages/core/test/files/_patterns/00-test/05-group2.mustache b/packages/core/test/files/_patterns/test/group2.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/05-group2.mustache rename to packages/core/test/files/_patterns/test/group2.mustache diff --git a/packages/core/test/files/_patterns/00-test/15-hidden-pattern-tester.mustache b/packages/core/test/files/_patterns/test/hidden-pattern-tester.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/15-hidden-pattern-tester.mustache rename to packages/core/test/files/_patterns/test/hidden-pattern-tester.mustache diff --git a/packages/core/test/files/_patterns/00-test/14-inception.mustache b/packages/core/test/files/_patterns/test/inception.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/14-inception.mustache rename to packages/core/test/files/_patterns/test/inception.mustache diff --git a/packages/core/test/files/_patterns/00-test/link.mustache b/packages/core/test/files/_patterns/test/link.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/link.mustache rename to packages/core/test/files/_patterns/test/link.mustache diff --git a/packages/core/test/files/_patterns/00-test/linkInParameter.mustache b/packages/core/test/files/_patterns/test/linkInParameter.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/linkInParameter.mustache rename to packages/core/test/files/_patterns/test/linkInParameter.mustache diff --git a/packages/core/test/files/_patterns/00-test/685-list.mustache b/packages/core/test/files/_patterns/test/list.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/685-list.mustache rename to packages/core/test/files/_patterns/test/list.mustache diff --git a/packages/core/test/files/_patterns/00-test/listWithListItems.listitems.json b/packages/core/test/files/_patterns/test/listWithListItems.listitems.json similarity index 100% rename from packages/core/test/files/_patterns/00-test/listWithListItems.listitems.json rename to packages/core/test/files/_patterns/test/listWithListItems.listitems.json diff --git a/packages/core/test/files/_patterns/00-test/listWithListItems.mustache b/packages/core/test/files/_patterns/test/listWithListItems.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/listWithListItems.mustache rename to packages/core/test/files/_patterns/test/listWithListItems.mustache diff --git a/packages/core/test/files/_patterns/00-test/listWithPartial.mustache b/packages/core/test/files/_patterns/test/listWithPartial.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/listWithPartial.mustache rename to packages/core/test/files/_patterns/test/listWithPartial.mustache diff --git a/packages/core/test/files/_patterns/00-test/13-listitem.mustache b/packages/core/test/files/_patterns/test/listitem.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/13-listitem.mustache rename to packages/core/test/files/_patterns/test/listitem.mustache diff --git a/packages/core/test/files/_patterns/00-test/mirror.mustache b/packages/core/test/files/_patterns/test/mirror.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/mirror.mustache rename to packages/core/test/files/_patterns/test/mirror.mustache diff --git a/packages/core/test/files/_patterns/00-test/07-mixed-params.mustache b/packages/core/test/files/_patterns/test/mixed-params.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/07-mixed-params.mustache rename to packages/core/test/files/_patterns/test/mixed-params.mustache diff --git a/packages/core/test/files/_patterns/00-test/06-mixed.mustache b/packages/core/test/files/_patterns/test/mixed.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/06-mixed.mustache rename to packages/core/test/files/_patterns/test/mixed.mustache diff --git a/packages/core/test/files/_patterns/00-test/10-multiple-classes-numeric.mustache b/packages/core/test/files/_patterns/test/multiple-classes-numeric.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/10-multiple-classes-numeric.mustache rename to packages/core/test/files/_patterns/test/multiple-classes-numeric.mustache diff --git a/packages/core/test/files/_patterns/test/nav.json b/packages/core/test/files/_patterns/test/nav.json new file mode 100644 index 000000000..8d47a2491 --- /dev/null +++ b/packages/core/test/files/_patterns/test/nav.json @@ -0,0 +1,29 @@ +{ + "brad": { + "url": "link.twitter-brad" + }, + "dave": { + "url": "link.twitter-dave" + }, + "brian": { + "url": "link.twitter-brian" + }, + "someone": { + "url": "link.twitter-someone" + }, + "someone2": { + "url": "link.facebook-someone2" + }, + "viewall-twitter": { + "url": "link.viewall-twitter-all" + }, + "viewall-twitter-people": { + "url": "link.viewall-twitter-people" + }, + "viewall-facebook": { + "url": "link.viewall-facebook-all" + }, + "viewall-facebook-people": { + "url": "link.viewall-facebook-people" + } +} \ No newline at end of file diff --git a/packages/core/test/files/_patterns/00-test/nav.mustache b/packages/core/test/files/_patterns/test/nav.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/nav.mustache rename to packages/core/test/files/_patterns/test/nav.mustache diff --git a/packages/core/test/files/_patterns/test/paramMiddle.mustache b/packages/core/test/files/_patterns/test/paramMiddle.mustache new file mode 100644 index 000000000..b69912370 --- /dev/null +++ b/packages/core/test/files/_patterns/test/paramMiddle.mustache @@ -0,0 +1,3 @@ +
+ {{> test-link }} +
diff --git a/packages/core/test/files/_patterns/00-test/paramParent.json b/packages/core/test/files/_patterns/test/paramParent.json similarity index 100% rename from packages/core/test/files/_patterns/00-test/paramParent.json rename to packages/core/test/files/_patterns/test/paramParent.json diff --git a/packages/core/test/files/_patterns/test/paramParent.mustache b/packages/core/test/files/_patterns/test/paramParent.mustache new file mode 100644 index 000000000..5ae3cb466 --- /dev/null +++ b/packages/core/test/files/_patterns/test/paramParent.mustache @@ -0,0 +1 @@ +{{> test-paramMiddle(additionalClasses: "foo") }} diff --git a/packages/core/test/files/_patterns/00-test/parameterTags.mustache b/packages/core/test/files/_patterns/test/parameterTags.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/parameterTags.mustache rename to packages/core/test/files/_patterns/test/parameterTags.mustache diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json new file mode 100644 index 000000000..1cb2a1d93 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.json @@ -0,0 +1,3 @@ +{ + "theme-class": "json-theme-class" +} diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache new file mode 100644 index 000000000..5716ca598 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-json.mustache @@ -0,0 +1 @@ +bar diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md new file mode 100644 index 000000000..358c8a525 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.md @@ -0,0 +1,3 @@ +--- +theme-class: markdown-theme-class +--- diff --git a/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache new file mode 100644 index 000000000..5716ca598 --- /dev/null +++ b/packages/core/test/files/_patterns/test/pattern-wrap-class-markdown.mustache @@ -0,0 +1 @@ +bar diff --git a/packages/core/test/files/_patterns/00-test/474-pseudomodifier.mustache b/packages/core/test/files/_patterns/test/pseudomodifier.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/474-pseudomodifier.mustache rename to packages/core/test/files/_patterns/test/pseudomodifier.mustache diff --git a/packages/core/test/files/_patterns/00-test/474-pseudomodifier~test.json b/packages/core/test/files/_patterns/test/pseudomodifier~test.json similarity index 100% rename from packages/core/test/files/_patterns/00-test/474-pseudomodifier~test.json rename to packages/core/test/files/_patterns/test/pseudomodifier~test.json diff --git a/packages/core/test/files/_patterns/00-test/553-repeatedListItems.mustache b/packages/core/test/files/_patterns/test/repeatedListItems.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/553-repeatedListItems.mustache rename to packages/core/test/files/_patterns/test/repeatedListItems.mustache diff --git a/packages/core/test/files/_patterns/test/sticky-comment-verbose.mustache b/packages/core/test/files/_patterns/test/sticky-comment-verbose.mustache new file mode 100644 index 000000000..168b757d9 --- /dev/null +++ b/packages/core/test/files/_patterns/test/sticky-comment-verbose.mustache @@ -0,0 +1 @@ +{{> test/comment(description: 'A life is like a garden. Perfect moments can be had, but not preserved, except in memory.') }} diff --git a/packages/core/test/files/_patterns/00-test/sticky-comment.mustache b/packages/core/test/files/_patterns/test/sticky-comment.mustache similarity index 100% rename from packages/core/test/files/_patterns/00-test/sticky-comment.mustache rename to packages/core/test/files/_patterns/test/sticky-comment.mustache diff --git a/packages/core/test/files/_patterns/00-test/03-styled-atom.json b/packages/core/test/files/_patterns/test/styled-atom.json similarity index 100% rename from packages/core/test/files/_patterns/00-test/03-styled-atom.json rename to packages/core/test/files/_patterns/test/styled-atom.json diff --git a/packages/core/test/files/_patterns/00-test/03-styled-atom.md b/packages/core/test/files/_patterns/test/styled-atom.md similarity index 100% rename from packages/core/test/files/_patterns/00-test/03-styled-atom.md rename to packages/core/test/files/_patterns/test/styled-atom.md diff --git a/packages/core/test/files/_patterns/test/styled-atom.mustache b/packages/core/test/files/_patterns/test/styled-atom.mustache new file mode 100644 index 000000000..e85d0fc26 --- /dev/null +++ b/packages/core/test/files/_patterns/test/styled-atom.mustache @@ -0,0 +1,3 @@ + + {{message}} + diff --git a/packages/core/test/files/_patterns/00-test/03-styled-atom~alt.json b/packages/core/test/files/_patterns/test/styled-atom~alt.json similarity index 100% rename from packages/core/test/files/_patterns/00-test/03-styled-atom~alt.json rename to packages/core/test/files/_patterns/test/styled-atom~alt.json diff --git a/packages/core/test/files/_patterns/test/variant-test.json b/packages/core/test/files/_patterns/test/variant-test.json new file mode 100644 index 000000000..9d371748a --- /dev/null +++ b/packages/core/test/files/_patterns/test/variant-test.json @@ -0,0 +1,9 @@ +{ + "a": 1, + "b": [2, 3], + "c": { + "d": [4, 5], + "e": 8, + "f": {"a": ["a"], "b": ["b"], "c": ["c"]} + } +} \ No newline at end of file diff --git a/packages/core/test/files/_patterns/test/variant-test.mustache b/packages/core/test/files/_patterns/test/variant-test.mustache new file mode 100644 index 000000000..fe4dd1f58 --- /dev/null +++ b/packages/core/test/files/_patterns/test/variant-test.mustache @@ -0,0 +1 @@ +{{a}} \ No newline at end of file diff --git a/packages/core/test/files/_patterns/test/variant-test~merge.json b/packages/core/test/files/_patterns/test/variant-test~merge.json new file mode 100644 index 000000000..c60d0974c --- /dev/null +++ b/packages/core/test/files/_patterns/test/variant-test~merge.json @@ -0,0 +1,8 @@ +{ + "a": 2, + "b": [8], + "c": { + "d": [6, 7], + "f": {"b": ["x"]} + } +} \ No newline at end of file diff --git a/packages/core/test/files/_react-test-patterns/00-atoms/00-general/HelloWorld.jsx b/packages/core/test/files/_react-test-patterns/atoms/general/HelloWorld.jsx similarity index 100% rename from packages/core/test/files/_react-test-patterns/00-atoms/00-general/HelloWorld.jsx rename to packages/core/test/files/_react-test-patterns/atoms/general/HelloWorld.jsx diff --git a/packages/core/test/files/_twig-test-patterns/00-atoms/00-general/09-image.twig b/packages/core/test/files/_twig-test-patterns/00-atoms/00-general/09-image.twig deleted file mode 100644 index 01c4af9f8..000000000 --- a/packages/core/test/files/_twig-test-patterns/00-atoms/00-general/09-image.twig +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/packages/core/test/files/_twig-test-patterns/00-atoms/00-general/08-button.twig b/packages/core/test/files/_twig-test-patterns/atoms/general/button.twig similarity index 100% rename from packages/core/test/files/_twig-test-patterns/00-atoms/00-general/08-button.twig rename to packages/core/test/files/_twig-test-patterns/atoms/general/button.twig diff --git a/packages/core/test/files/_twig-test-patterns/atoms/general/image.twig b/packages/core/test/files/_twig-test-patterns/atoms/general/image.twig new file mode 100644 index 000000000..320401c8e --- /dev/null +++ b/packages/core/test/files/_twig-test-patterns/atoms/general/image.twig @@ -0,0 +1,5 @@ + diff --git a/packages/core/test/files/_twig-test-patterns/00-molecules/00-general/00-media-object.twig b/packages/core/test/files/_twig-test-patterns/molecules/general/media-object.twig similarity index 100% rename from packages/core/test/files/_twig-test-patterns/00-molecules/00-general/00-media-object.twig rename to packages/core/test/files/_twig-test-patterns/molecules/general/media-object.twig diff --git a/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld-withdata.html b/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld-withdata.html deleted file mode 100644 index 32c1c7361..000000000 --- a/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld-withdata.html +++ /dev/null @@ -1,2 +0,0 @@ -Hello world! -<%= subtitle %> diff --git a/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-helloworlds.html b/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-helloworlds.html deleted file mode 100644 index a493205c3..000000000 --- a/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-helloworlds.html +++ /dev/null @@ -1 +0,0 @@ -<%= _.template(_partials['atoms-helloworld'])(_data) %> and <%= _.template(_partials['atoms-helloworld'])(_data) %> diff --git a/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/_00-hidden.html b/packages/core/test/files/_underscore-test-patterns/atoms/global/_hidden.html similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/_00-hidden.html rename to packages/core/test/files/_underscore-test-patterns/atoms/global/_hidden.html diff --git a/packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld-withdata.html b/packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld-withdata.html new file mode 100644 index 000000000..92e7cd0d0 --- /dev/null +++ b/packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld-withdata.html @@ -0,0 +1 @@ +Hello world! <%= subtitle %> diff --git a/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld-withdata.json b/packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld-withdata.json similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld-withdata.json rename to packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld-withdata.json diff --git a/packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld.html b/packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld.html similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-atoms/00-global/00-helloworld.html rename to packages/core/test/files/_underscore-test-patterns/atoms/global/helloworld.html diff --git a/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.html b/packages/core/test/files/_underscore-test-patterns/molecules/global/call-atom-with-molecule-data.html similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.html rename to packages/core/test/files/_underscore-test-patterns/molecules/global/call-atom-with-molecule-data.html diff --git a/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.json b/packages/core/test/files/_underscore-test-patterns/molecules/global/call-atom-with-molecule-data.json similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-call-atom-with-molecule-data.json rename to packages/core/test/files/_underscore-test-patterns/molecules/global/call-atom-with-molecule-data.json diff --git a/packages/core/test/files/_underscore-test-patterns/molecules/global/helloworlds.html b/packages/core/test/files/_underscore-test-patterns/molecules/global/helloworlds.html new file mode 100644 index 000000000..a7e774300 --- /dev/null +++ b/packages/core/test/files/_underscore-test-patterns/molecules/global/helloworlds.html @@ -0,0 +1,2 @@ +<%= _.template(_partials['atoms-helloworld'])(_data) %> and <%= +_.template(_partials['atoms-helloworld'])(_data) %> diff --git a/packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-hidden-pattern-tester.html b/packages/core/test/files/_underscore-test-patterns/molecules/global/hidden-pattern-tester.html similarity index 100% rename from packages/core/test/files/_underscore-test-patterns/00-molecules/00-global/00-hidden-pattern-tester.html rename to packages/core/test/files/_underscore-test-patterns/molecules/global/hidden-pattern-tester.html diff --git a/packages/core/test/files/annotations.js b/packages/core/test/files/annotations.js index 6bc8c1432..66a3475c4 100644 --- a/packages/core/test/files/annotations.js +++ b/packages/core/test/files/annotations.js @@ -8,7 +8,7 @@ var comments = { { "el": ".logo", "title": "Logo", - "comment": "The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don't support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

" + "comment": "The logo image is an SVG file, which ensures that the logo displays crisply even on high resolution displays. A PNG fallback is provided for browsers that don't support SVG images.

Further reading: Optimizing Web Experiences for High Resolution Screens

" } ] }; diff --git a/packages/core/test/files/partials/patternSectionSubgroup.mustache b/packages/core/test/files/partials/patternSectionSubgroup.mustache new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/test/get_tests.js b/packages/core/test/get_tests.js index 5e954182c..59be0fd20 100644 --- a/packages/core/test/get_tests.js +++ b/packages/core/test/get_tests.js @@ -7,29 +7,30 @@ const getPartial = require('../src/lib/get'); const patterns_dir = './test/files/_patterns'; -tap.test('getPartial - returns the fuzzy result when no others found', function( - test -) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - patternlab.patterns = []; +tap.test( + 'getPartial - returns the fuzzy result when no others found', + function (test) { + //arrange + const patternlab = util.fakePatternLab(patterns_dir); + patternlab.patterns = []; - patternlab.patterns.push({ - patternPartial: 'character-han-solo', - subdir: 'character', - fileName: 'han-solo', - verbosePartial: 'character/han-solo', - }); + patternlab.patterns.push({ + patternPartial: 'character-han-solo', + subdir: 'character', + fileName: 'han-solo', + verbosePartial: 'character/han-solo', + }); - //act - var result = getPartial('character-han', patternlab); + //act + var result = getPartial('character-han', patternlab); - //assert - test.equals(result, patternlab.patterns[0]); - test.end(); -}); + //assert + test.equal(result, patternlab.patterns[0]); + test.end(); + } +); -tap.test('getPartial - returns the verbose result if found', function(test) { +tap.test('getPartial - returns the verbose result if found', function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); patternlab.patterns = []; @@ -53,11 +54,11 @@ tap.test('getPartial - returns the verbose result if found', function(test) { var result = getPartial('molecules/primary-nav', patternlab); //assert - test.equals(result, patternlab.patterns[1]); + test.equal(result, patternlab.patterns[1]); test.end(); }); -tap.test('getPartial - returns the exact key if found', function(test) { +tap.test('getPartial - returns the exact key if found', function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); patternlab.patterns = []; @@ -79,6 +80,6 @@ tap.test('getPartial - returns the exact key if found', function(test) { var result = getPartial('molecules-primary-nav', patternlab); //assert - test.equals(result, patternlab.patterns[1]); + test.equal(result, patternlab.patterns[1]); test.end(); }); diff --git a/packages/core/test/index_tests.js b/packages/core/test/index_tests.js index d2e98895e..5cf82654e 100644 --- a/packages/core/test/index_tests.js +++ b/packages/core/test/index_tests.js @@ -15,33 +15,33 @@ process.env.PATTERNLAB_ENV = 'CI'; //set up a global mocks - we don't want to be writing/rendering any files right now -const copierMock = function() { +const copierMock = function () { return { - copyAndWatch: function() { + copyAndWatch: function () { return Promise.resolve(); }, }; }; -const uiBuilderMock = function() { +const uiBuilderMock = function () { return { - buildFrontend: function() { + buildFrontend: function () { return Promise.resolve(); }, }; }; const fsMock = { - outputFileSync: function(path, content) { + outputFileSync: function (path, content) { /* INTENTIONAL NOOP */ }, - readJSONSync: function(path, encoding) { + readJSONSync: function (path, encoding) { return fs.readJSONSync(path, encoding); }, - emptyDir: function(path) { + emptyDir: function (path) { return fs.emptyDir(path); }, - readFileSync: function(path, encoding) { + readFileSync: function (path, encoding) { return fs.readFileSync(path, encoding); }, }; @@ -57,29 +57,29 @@ entry.__set__({ copier: copierMock, }); -tap.test('version - should call patternlab.getVersion', test => { +tap.test('version - should call patternlab.getVersion', (test) => { //arrange const pl = new entry(testConfig); //act //assert - test.equals(pl.version(), packageInfo.version); + test.equal(pl.version(), packageInfo.version); test.end(); }); tap.test( 'getDefaultConfig - static method should return the default config object', - test => { + (test) => { const requestedConfig = entry.getDefaultConfig(); test.type(requestedConfig, 'object'); - test.equals(requestedConfig, defaultConfig); + test.equal(requestedConfig, defaultConfig); test.end(); } ); tap.test( 'getDefaultConfig - instance method should return the default config object', - test => { + (test) => { //arrange const pl = new entry(testConfig); @@ -87,12 +87,12 @@ tap.test( //assert const requestedConfig = pl.getDefaultConfig(); test.type(requestedConfig, 'object'); - test.equals(requestedConfig, defaultConfig); + test.equal(requestedConfig, defaultConfig); test.end(); } ); -tap.test('patternsonly a promise', test => { +tap.test('patternsonly a promise', (test) => { //arrange const revert = entry.__set__('buildPatterns', buildPatternsMock); const pl = new entry(testConfig); @@ -104,7 +104,7 @@ tap.test('patternsonly a promise', test => { }); }); -tap.test('patternsonly calls buildPatterns', test => { +tap.test('patternsonly calls buildPatterns', (test) => { //arrange const revert = entry.__set__( 'buildPatterns', @@ -113,7 +113,7 @@ tap.test('patternsonly calls buildPatterns', test => { test.ok(cleanPublic); test.type(patternlab, 'object'); test.type(data, 'object'); - test.equals(data.foo, 'bar'); + test.equal(data.foo, 'bar'); return Promise.resolve(); } ); @@ -128,9 +128,9 @@ tap.test('patternsonly calls buildPatterns', test => { }); }); -tap.test('serve calls serve', test => { +tap.test('serve calls serve', (test) => { //arrange - const revert = entry.__set__('serverModule', patternlab => { + const revert = entry.__set__('serverModule', (patternlab) => { return { serve: () => { test.ok(1); @@ -149,7 +149,7 @@ tap.test('serve calls serve', test => { }); }); -tap.test('buildPatterns suite', test => { +tap.test('buildPatterns suite', (test) => { //arrange const patternExporterMock = { @@ -158,19 +158,18 @@ tap.test('buildPatterns suite', test => { the contents of the patterns look like. This, coupled with a mocking of fs and the ui_builder, allow us to focus only on the order of events within build. */ - export_patterns: function(patternlab) { + export_patterns: function (patternlab) { tap.test( 'replace data link even when pattern parameter present', - function(test) { + function (test) { var pattern = get('test-paramParent', patternlab); - test.equals( + test.equal( util.sanitized(pattern.extendedTemplate), '', 'partial inclusion completes' ); - test.equals( - pattern.patternPartialCode.indexOf('00-test-00-foo.rendered.html') > - -1, + test.equal( + pattern.patternPartialCode.indexOf('test-foo.rendered.html') > -1, true, 'data link should be replaced properly' ); @@ -180,9 +179,9 @@ tap.test('buildPatterns suite', test => { tap.test( 'finds partials with their own parameters and renders them too', - function(test) { + function (test) { var pattern = get('test-c', patternlab); - test.equals( + test.equal( util.sanitized(pattern.patternPartialCode), util.sanitized(`c b @@ -196,9 +195,9 @@ tap.test('buildPatterns suite', test => { tap.test( 'finds and extends templates with mixed parameter and global data', - function(test) { + function (test) { var pattern = get('test-sticky-comment', patternlab); - test.equals( + test.equal( util.sanitized(pattern.patternPartialCode), util.sanitized( `

Bar

A life is like a garden. Perfect moments can be had, but not preserved, except in memory.

` @@ -208,21 +207,21 @@ tap.test('buildPatterns suite', test => { } ); - tap.test('expands links inside parameters', function(test) { + tap.test('expands links inside parameters', function (test) { var pattern = get('test-linkInParameter', patternlab); - test.equals( + test.equal( util.sanitized(pattern.patternPartialCode), util.sanitized( - `Cool Dude` + `Cool Dude` ) ); test.end(); }); - tap.test('uses global listItem property', test => { + tap.test('uses global listItem property', (test) => { var pattern = get('test-listWithPartial', patternlab); let assertionCount = 0; - ['dA', 'dB', 'dC'].forEach(d => { + ['dA', 'dB', 'dC'].forEach((d) => { if (pattern.patternPartialCode.indexOf(d) > -1) { assertionCount++; } @@ -233,7 +232,7 @@ tap.test('buildPatterns suite', test => { tap.test( 'overwrites listItem property if that property is in local .listitem.json', - test => { + (test) => { var pattern = get('test-listWithListItems', patternlab); test.ok(pattern.patternPartialCode.indexOf('tX') > -1); test.ok(pattern.patternPartialCode.indexOf('tY') > -1); @@ -245,7 +244,7 @@ tap.test('buildPatterns suite', test => { tap.test( 'uses global listItem property after merging local .listitem.json', - test => { + (test) => { var pattern = get('test-listWithListItems', patternlab); test.ok(pattern.patternPartialCode.indexOf('dA') > -1); test.ok(pattern.patternPartialCode.indexOf('dB') > -1); @@ -254,39 +253,11 @@ tap.test('buildPatterns suite', test => { } ); - tap.test( - 'correctly ignores bookended partials without a style modifier when the same partial has a style modifier between', - test => { - var pattern = get('test-bookend-listitem', patternlab); - test.equals( - util.sanitized(pattern.extendedTemplate), - util.sanitized(`
- {{#listItems-two}} - - {{message}} - - - - {{message}} - - - - {{message}} - - - {{/listItems-two}} -
- `) - ); - test.end(); - } - ); - tap.test( 'listItems keys (`one` through `twelve`) can be used more than once per pattern', - test => { + (test) => { var pattern = get('test-repeatedListItems', patternlab); - test.equals( + test.equal( util.sanitized(pattern.patternPartialCode), util.sanitized(`AAA BBB`) ); @@ -299,7 +270,7 @@ tap.test('buildPatterns suite', test => { // From issue #145 https://github.com/pattern-lab/patternlab-node/issues/145 // tap.test(' parses parameters containing html tags', function (test) { // var pattern = get('test-parameterTags', patternlab); - // test.equals(util.sanitized(pattern.patternPartialCode), util.sanitized(`

Single-quoted

Double-quoted

With attributes

`)); + // test.equal(util.sanitized(pattern.patternPartialCode), util.sanitized(`

Single-quoted

Double-quoted

With attributes

`)); // test.end(); // }); @@ -314,7 +285,7 @@ tap.test('buildPatterns suite', test => { testConfig.patternExportPatternPartials = ['test-paramParent']; const pl = new entry(testConfig); - test.equals(pl.events.eventNames().length, 0); + test.equal(pl.events.eventNames().length, 0); //act return pl @@ -326,12 +297,12 @@ tap.test('buildPatterns suite', test => { }, }) .then(() => { - test.equals( + test.equal( pl.events.eventNames().length, 2, 'should register two events' ); - test.equals(pl.events.listenerCount(events.PATTERNLAB_PATTERN_CHANGE), 1); - test.equals(pl.events.listenerCount(events.PATTERNLAB_GLOBAL_CHANGE), 1); + test.equal(pl.events.listenerCount(events.PATTERNLAB_PATTERN_CHANGE), 1); + test.equal(pl.events.listenerCount(events.PATTERNLAB_GLOBAL_CHANGE), 1); }); }); diff --git a/packages/core/test/lineage_hunter_tests.js b/packages/core/test/lineage_hunter_tests.js index b19157a28..31a40b764 100644 --- a/packages/core/test/lineage_hunter_tests.js +++ b/packages/core/test/lineage_hunter_tests.js @@ -22,7 +22,7 @@ const lineage_hunter = new lh(); // fake pattern creators function createFakeEmptyErrorPattern() { return new Pattern( - '01-molecules/01-toast/00-error.mustache', // relative path now + 'molecules/toast/error.mustache', // relative path now null // data ); } @@ -53,42 +53,41 @@ function createBasePatternLabObject() { pl.patterns = []; pl.partials = {}; pl.patternGroups = {}; - pl.subtypePatterns = {}; + pl.subgroupPatterns = {}; return pl; } -tap.test('find_lineage - finds lineage', function(test) { +tap.test('find_lineage - finds lineage', function (test) { //setup current pattern from what we would have during execution var currentPattern = new Pattern( - '02-organisms/00-global/00-header.mustache', // relative path now + 'organisms/global/header.mustache', // relative path now null // data ); extend(currentPattern, { template: '\r\n\r\n\r\n', patternPartialCode: - '\r\n\r\n\r\n', + '\r\n\r\n\r\n', }); var patternlab = { graph: new PatternGraph(null, 0), patterns: [ Pattern.createEmpty({ - name: '00-atoms-03-images-00-logo', - subdir: '00-atoms\\03-images', - filename: '00-logo.mustache', + name: 'atoms-images-logo', + subdir: 'atoms\\images', + filename: 'logo.mustache', data: null, template: '', patternPartialCode: '', patternBaseName: 'logo', - patternLink: - '00-atoms-03-images-00-logo/00-atoms-03-images-00-logo.html', + patternLink: 'atoms-images-logo/atoms-images-logo.html', patternGroup: 'atoms', - patternSubGroup: 'atoms\\03-images', - flatPatternPath: '00-atoms\\03-images', + patternSubgroup: 'atoms\\images', + flatPatternPath: 'atoms\\images', patternPartial: 'atoms-logo', patternState: '', lineage: [], @@ -97,9 +96,9 @@ tap.test('find_lineage - finds lineage', function(test) { lineageRIndex: [], }), Pattern.createEmpty({ - name: '01-molecules-05-navigation-00-primary-nav', - subdir: '01-molecules\\05-navigation', - filename: '00-primary-nav.mustache', + name: 'molecules-navigation-primary-nav', + subdir: 'molecules\\navigation', + filename: 'primary-nav.mustache', data: null, template: '\r\n', @@ -107,10 +106,10 @@ tap.test('find_lineage - finds lineage', function(test) { '\r\n', patternBaseName: 'primary-nav', patternLink: - '01-molecules-05-navigation-00-primary-nav/01-molecules-05-navigation-00-primary-nav.html', + 'molecules-navigation-primary-nav/molecules-navigation-primary-nav.html', patternGroup: 'molecules', - patternSubGroup: 'molecules\\05-navigation', - flatPatternPath: '01-molecules\\05-navigation', + patternSubgroup: 'molecules\\navigation', + flatPatternPath: 'molecules\\navigation', patternPartial: 'molecules-primary-nav', patternState: '', lineage: [], @@ -119,20 +118,19 @@ tap.test('find_lineage - finds lineage', function(test) { lineageRIndex: [], }), Pattern.createEmpty({ - name: '01-molecules-04-forms-00-search', - subdir: '01-molecules\\04-forms', - filename: '00-search.mustache', + name: 'molecules-forms-search', + subdir: 'molecules\\forms', + filename: 'search.mustache', data: null, template: - '
\r\n
\r\n\t Search\r\n\t \r\n\t \r\n\t \r\n
\r\n
', + '
\r\n
\r\n\t Search\r\n\t \r\n\t \r\n\t \r\n
\r\n
', patternPartialCode: - '
\r\n
\r\n\t Search\r\n\t \r\n\t \r\n\t \r\n
\r\n
', + '
\r\n
\r\n\t Search\r\n\t \r\n\t \r\n\t \r\n
\r\n
', patternBaseName: 'search', - patternLink: - '01-molecules-04-forms-00-search/01-molecules-04-forms-00-search.html', + patternLink: 'molecules-forms-search/molecules-forms-search.html', patternGroup: 'molecules', - patternSubGroup: 'molecules\\04-forms', - flatPatternPath: '01-molecules\\04-forms', + patternSubgroup: 'molecules\\forms', + flatPatternPath: 'molecules\\forms', patternPartial: 'molecules-search', patternState: '', lineage: [], @@ -150,7 +148,7 @@ tap.test('find_lineage - finds lineage', function(test) { }, }; // BAD: This "patches" the relative path which is unset when using "createEmpty" - patternlab.patterns.forEach(p => (p.relPath = p.patternLink)); + patternlab.patterns.forEach((p) => (p.relPath = p.patternLink)); lineage_hunter.find_lineage(currentPattern, patternlab); @@ -158,10 +156,10 @@ tap.test('find_lineage - finds lineage', function(test) { // Ensure compatibility for (let i of [currentPattern.lineageIndex, graphLineageIndex]) { - test.equals(i.length, 3); - test.equals(i[0], 'atoms-logo'); - test.equals(i[1], 'molecules-primary-nav'); - test.equals(i[2], 'molecules-search'); + test.equal(i.length, 3); + test.equal(i[0], 'atoms-logo'); + test.equal(i[1], 'molecules-primary-nav'); + test.equal(i[2], 'molecules-search'); } test.end(); @@ -169,7 +167,7 @@ tap.test('find_lineage - finds lineage', function(test) { tap.test( 'find_lineage - finds lineage with spaced pattern parameters', - function(test) { + function (test) { //setup current pattern from what we would have during execution var currentPattern = createFakeEmptyErrorPattern(); extend(currentPattern, { @@ -180,7 +178,7 @@ tap.test( var patternlab = { graph: new PatternGraph(null, 0), patterns: [ - Pattern.create('00-atoms/05-alerts/00-error.mustache', null, { + Pattern.create('atoms/alerts/error.mustache', null, { template: '

{{message}}

', extendedTemplate: '

{{message}}

', }), @@ -196,10 +194,10 @@ tap.test( lineage_hunter.find_lineage(currentPattern, patternlab); - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); - test.equals(patternlab.patterns[0].lineageRIndex.length, 1); - test.equals( + test.equal(currentPattern.lineageIndex.length, 1); + test.equal(currentPattern.lineageIndex[0], 'atoms-error'); + test.equal(patternlab.patterns[0].lineageRIndex.length, 1); + test.equal( patternlab.patterns[0].lineageR[0].lineagePattern, 'molecules-error' ); @@ -214,14 +212,14 @@ tap.test( ); var currentPatternLineageIndex = graph.lineageIndex(currentPattern); - test.equals(currentPatternLineageIndex.length, 1); - test.equals(currentPatternLineageIndex[0], 'atoms-error'); + test.equal(currentPatternLineageIndex.length, 1); + test.equal(currentPatternLineageIndex[0], 'atoms-error'); var patternlabPattern0_lineageRIndex = graph.lineageRIndex( patternlab.patterns[0] ); - test.equals(patternlabPattern0_lineageRIndex.length, 1); - test.equals(patternlabPattern0_lineageRIndex[0], 'molecules-error'); + test.equal(patternlabPattern0_lineageRIndex.length, 1); + test.equal(patternlabPattern0_lineageRIndex[0], 'molecules-error'); test.end(); } @@ -229,13 +227,13 @@ tap.test( tap.test( 'cascade_pattern_states promotes a lower pattern state up to the consumer', - function(test) { + function (test) { //arrange var pl = createBasePatternLabObject(); - var atomPattern = new of.Pattern('00-test/01-bar.mustache'); + var atomPattern = new of.Pattern('test/bar.mustache'); atomPattern.template = fs.readFileSync( - pl.config.paths.source.patterns + '00-test/01-bar.mustache', + pl.config.paths.source.patterns + 'test/bar.mustache', 'utf8' ); atomPattern.extendedTemplate = atomPattern.template; @@ -243,9 +241,9 @@ tap.test( addPattern(atomPattern, pl); - var consumerPattern = new of.Pattern('00-test/00-foo.mustache'); + var consumerPattern = new of.Pattern('test/foo.mustache'); consumerPattern.template = fs.readFileSync( - pl.config.paths.source.patterns + '00-test/00-foo.mustache', + pl.config.paths.source.patterns + 'test/foo.mustache', 'utf8' ); consumerPattern.extendedTemplate = consumerPattern.template; @@ -259,20 +257,20 @@ tap.test( //assert var consumerPatternReturned = getPartial('test-foo', pl); - test.equals(consumerPatternReturned.patternState, 'inreview'); + test.equal(consumerPatternReturned.patternState, 'inreview'); test.end(); } ); tap.test( 'cascade_pattern_states promotes a lower pattern state up to the consumers lineage', - function(test) { + function (test) { //arrange var pl = createBasePatternLabObject(); - var atomPattern = new of.Pattern('00-test/01-bar.mustache'); + var atomPattern = new of.Pattern('test/bar.mustache'); atomPattern.template = fs.readFileSync( - pl.config.paths.source.patterns + '00-test/01-bar.mustache', + pl.config.paths.source.patterns + 'test/bar.mustache', 'utf8' ); atomPattern.extendedTemplate = atomPattern.template; @@ -280,9 +278,9 @@ tap.test( addPattern(atomPattern, pl); - var consumerPattern = new of.Pattern('00-test/00-foo.mustache'); + var consumerPattern = new of.Pattern('test/foo.mustache'); consumerPattern.template = fs.readFileSync( - pl.config.paths.source.patterns + '00-test/00-foo.mustache', + pl.config.paths.source.patterns + 'test/foo.mustache', 'utf8' ); consumerPattern.extendedTemplate = consumerPattern.template; @@ -297,19 +295,19 @@ tap.test( //assert var consumerPatternReturned = getPartial('test-foo', pl); const lineage = pl.graph.lineage(consumerPatternReturned); - test.equals(lineage[0].lineageState, 'inreview'); + test.equal(lineage[0].lineageState, 'inreview'); test.end(); } ); tap.test( 'cascade_pattern_states sets the pattern state on any lineage patterns reverse lineage', - function(test) { + function (test) { //arrange var pl = createBasePatternLabObject(); - var atomPattern = loadPattern('00-test/01-bar.mustache', pl); - var consumerPattern = loadPattern('00-test/00-foo.mustache', pl); + var atomPattern = loadPattern('test/bar.mustache', pl); + var consumerPattern = loadPattern('test/foo.mustache', pl); lineage_hunter.find_lineage(consumerPattern, pl); @@ -319,7 +317,7 @@ tap.test( //assert var consumedPatternReturned = getPartial('test-bar', pl); let lineageR = pl.graph.lineageR(consumedPatternReturned); - test.equals(lineageR[0].lineageState, 'inreview'); + test.equal(lineageR[0].lineageState, 'inreview'); test.end(); } @@ -327,13 +325,13 @@ tap.test( tap.test( 'cascade_pattern_states promotes lower pattern state when consumer does not have its own state', - function(test) { + function (test) { //arrange var pl = createBasePatternLabObject(); - var atomPattern = new of.Pattern('00-test/01-bar.mustache'); + var atomPattern = new of.Pattern('test/bar.mustache'); atomPattern.template = fs.readFileSync( - path.resolve(pl.config.paths.source.patterns, '00-test/01-bar.mustache'), + path.resolve(pl.config.paths.source.patterns, 'test/bar.mustache'), 'utf8' ); atomPattern.extendedTemplate = atomPattern.template; @@ -341,9 +339,9 @@ tap.test( addPattern(atomPattern, pl); - var consumerPattern = new of.Pattern('00-test/00-foo.mustache'); + var consumerPattern = new of.Pattern('test/foo.mustache'); consumerPattern.template = fs.readFileSync( - path.resolve(pl.config.paths.source.patterns, '00-test/00-foo.mustache'), + path.resolve(pl.config.paths.source.patterns, 'test/foo.mustache'), 'utf8' ); consumerPattern.extendedTemplate = consumerPattern.template; @@ -356,16 +354,16 @@ tap.test( //assert var consumerPatternReturned = getPartial('test-foo', pl); - test.equals(consumerPatternReturned.lineage.length, 1); - test.equals(consumerPatternReturned.lineage[0].lineageState, 'inreview'); - test.equals(consumerPatternReturned.patternState, 'inreview'); + test.equal(consumerPatternReturned.lineage.length, 1); + test.equal(consumerPatternReturned.lineage[0].lineageState, 'inreview'); + test.equal(consumerPatternReturned.patternState, 'inreview'); test.end(); } ); tap.test( 'find_lineage - finds lineage with unspaced pattern parameters', - function(test) { + function (test) { //setup current pattern from what we would have during execution var currentPattern = createFakeEmptyErrorPattern(); extend(currentPattern, { @@ -377,18 +375,17 @@ tap.test( graph: PatternGraph.empty(), patterns: [ Pattern.createEmpty({ - name: '01-atoms-05-alerts-00-error', - subdir: '01-atoms\\05-alerts', - filename: '00-error.mustache', + name: 'atoms-alerts-error', + subdir: 'atoms\\alerts', + filename: 'error.mustache', data: null, template: '

{{message}}

', extendedTemplate: '

{{message}}

', patternBaseName: 'error', - patternLink: - '01-atoms-05-alerts-00-error/01-atoms-05-alerts-00-error.html', + patternLink: 'atoms-alerts-error/atoms-alerts-error.html', patternGroup: 'atoms', - patternSubGroup: 'atoms\\05-alerts', - flatPatternPath: '01-atoms\\05-alerts', + patternSubgroup: 'atoms\\alerts', + flatPatternPath: 'atoms\\alerts', patternPartial: 'atoms-error', patternState: '', lineage: [], @@ -408,228 +405,30 @@ tap.test( lineage_hunter.find_lineage(currentPattern, patternlab); - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); - test.equals(patternlab.patterns[0].lineageRIndex.length, 1); - test.equals( + test.equal(currentPattern.lineageIndex.length, 1); + test.equal(currentPattern.lineageIndex[0], 'atoms-error'); + test.equal(patternlab.patterns[0].lineageRIndex.length, 1); + test.equal( patternlab.patterns[0].lineageR[0].lineagePattern, 'molecules-error' ); - var currentPatternLineageIndex = patternlab.graph.lineageIndex( - currentPattern - ); - test.equals(currentPatternLineageIndex.length, 1); - test.equals(currentPatternLineageIndex[0], 'atoms-error'); + var currentPatternLineageIndex = + patternlab.graph.lineageIndex(currentPattern); + test.equal(currentPatternLineageIndex.length, 1); + test.equal(currentPatternLineageIndex[0], 'atoms-error'); var pattern0LineageRIndex = patternlab.graph.lineageRIndex( patternlab.patterns[0] ); - test.equals(pattern0LineageRIndex.length, 1); - test.equals(pattern0LineageRIndex[0], 'molecules-error'); - - test.end(); - } -); - -tap.test('find_lineage - finds lineage with spaced styleModifier', function( - test -) { - //setup current pattern from what we would have during execution - var currentPattern = Pattern.createEmpty({ - name: '01-molecules-01-toast-00-error', - subdir: '01-molecules\\01-toast', - filename: '00-error.mustache', - data: null, - template: '{{> atoms-error:foo }}', - extendedTemplate: '{{> atoms-error:foo }}', - patternBaseName: 'error', - patternLink: - '01-molecules-01-toast-00-error/01-molecules-01-toast-00-error.html', - patternGroup: 'molecules', - patternSubGroup: 'molecules\\01-toast', - flatPatternPath: '01-molecules\\01-toast', - patternPartial: 'molecules-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }); - var patternlab = { - graph: new PatternGraph(null, 0), - patterns: [ - Pattern.createEmpty({ - name: '01-atoms-05-alerts-00-error', - subdir: '01-atoms\\05-alerts', - filename: '00-error.mustache', - data: null, - template: '

{{message}}

', - extendedTemplate: '

{{message}}

', - patternBaseName: 'error', - patternLink: - '01-atoms-05-alerts-00-error/01-atoms-05-alerts-00-error.html', - patternGroup: 'atoms', - patternSubGroup: 'atoms\\05-alerts', - flatPatternPath: '01-atoms\\05-alerts', - patternPartial: 'atoms-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }), - ], - config: { - outputFileSuffixes: { - rendered: '.rendered', - rawTemplate: '', - markupOnly: '.markup-only', - }, - }, - }; - - lineage_hunter.find_lineage(currentPattern, patternlab); - - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); - - test.end(); -}); - -tap.test('find_lineage - finds lineage with unspaced styleModifier', function( - test -) { - //setup current pattern from what we would have during execution - var currentPattern = Pattern.createEmpty({ - name: '01-molecules-01-toast-00-error', - subdir: '01-molecules\\01-toast', - filename: '00-error.mustache', - data: null, - template: '{{> atoms-error:foo }}', - extendedTemplate: '{{>atoms-error:foo}}', - patternBaseName: 'error', - patternLink: - '01-molecules-01-toast-00-error/01-molecules-01-toast-00-error.html', - patternGroup: 'molecules', - patternSubGroup: 'molecules\\01-toast', - flatPatternPath: '01-molecules\\01-toast', - patternPartial: 'molecules-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }); - var patternlab = { - graph: PatternGraph.empty(), - patterns: [ - Pattern.createEmpty({ - name: '01-atoms-05-alerts-00-error', - subdir: '01-atoms\\05-alerts', - filename: '00-error.mustache', - data: null, - template: '

{{message}}

', - extendedTemlpate: '

{{message}}

', - patternBaseName: 'error', - patternLink: - '01-atoms-05-alerts-00-error/01-atoms-05-alerts-00-error.html', - patternGroup: 'atoms', - patternSubGroup: 'atoms\\05-alerts', - flatPatternPath: '01-atoms\\05-alerts', - patternPartial: 'atoms-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }), - ], - config: { - outputFileSuffixes: { - rendered: '.rendered', - rawTemplate: '', - markupOnly: '.markup-only', - }, - }, - }; - - lineage_hunter.find_lineage(currentPattern, patternlab); - - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); - - test.end(); -}); - -tap.test( - 'find_lineage - finds lineage with fuzzy partial with styleModifier', - function(test) { - //setup current pattern from what we would have during execution - var currentPattern = Pattern.createEmpty({ - name: '01-molecules-01-toast-00-error', - subdir: '01-molecules\\01-toast', - filename: '00-error.mustache', - data: null, - template: '{{> atoms-e:foo }}', - extendedTemplate: '{{>atoms-e:foo}}', - patternBaseName: 'error', - patternLink: - '01-molecules-01-toast-00-error/01-molecules-01-toast-00-error.html', - patternGroup: 'molecules', - patternSubGroup: 'molecules\\01-toast', - flatPatternPath: '01-molecules\\01-toast', - patternPartial: 'molecules-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }); - var patternlab = { - graph: PatternGraph.empty(), - patterns: [ - Pattern.createEmpty({ - name: '01-atoms-05-alerts-00-error', - subdir: '01-atoms\\05-alerts', - filename: '00-error.mustache', - data: null, - template: '

{{message}}

', - extendedTemplate: '

{{message}}

', - patternBaseName: 'error', - patternLink: - '01-atoms-05-alerts-00-error/01-atoms-05-alerts-00-error.html', - patternGroup: 'atoms', - patternSubGroup: 'atoms\\05-alerts', - flatPatternPath: '01-atoms\\05-alerts', - patternPartial: 'atoms-error', - patternState: '', - lineage: [], - lineageIndex: [], - lineageR: [], - lineageRIndex: [], - }), - ], - config: { - outputFileSuffixes: { - rendered: '.rendered', - rawTemplate: '', - markupOnly: '.markup-only', - }, - }, - }; - - var lineage_hunter = new lh(); - lineage_hunter.find_lineage(currentPattern, patternlab); - - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); + test.equal(pattern0LineageRIndex.length, 1); + test.equal(pattern0LineageRIndex[0], 'molecules-error'); test.end(); } ); -tap.test('find_lineage - does not apply lineage twice', function(test) { +tap.test('find_lineage - does not apply lineage twice', function (test) { //setup current pattern from what we would have during execution var currentPattern = createFakeEmptyErrorPattern(); extend(currentPattern, { @@ -640,18 +439,17 @@ tap.test('find_lineage - does not apply lineage twice', function(test) { graph: PatternGraph.empty(), patterns: [ Pattern.createEmpty({ - name: '01-atoms-05-alerts-00-error', - subdir: '01-atoms\\05-alerts', - filename: '00-error.mustache', + name: 'atoms-alerts-error', + subdir: 'atoms\\alerts', + filename: 'error.mustache', data: null, template: '

{{message}}

', extendedTemplate: '

{{message}}

', patternBaseName: 'error', - patternLink: - '01-atoms-05-alerts-00-error/01-atoms-05-alerts-00-error.html', + patternLink: 'atoms-alerts-error/atoms-alerts-error.html', patternGroup: 'atoms', - patternSubGroup: 'atoms\\05-alerts', - flatPatternPath: '01-atoms\\05-alerts', + patternSubgroup: 'atoms\\alerts', + flatPatternPath: 'atoms\\alerts', patternPartial: 'atoms-error', patternState: '', lineage: [], @@ -673,10 +471,10 @@ tap.test('find_lineage - does not apply lineage twice', function(test) { lineage_hunter.find_lineage(currentPattern, patternlab); lineage_hunter.find_lineage(currentPattern, patternlab); - test.equals(currentPattern.lineageIndex.length, 1); - test.equals(currentPattern.lineageIndex[0], 'atoms-error'); - test.equals(patternlab.patterns[0].lineageRIndex.length, 1); - test.equals( + test.equal(currentPattern.lineageIndex.length, 1); + test.equal(currentPattern.lineageIndex[0], 'atoms-error'); + test.equal(patternlab.patterns[0].lineageRIndex.length, 1); + test.equal( patternlab.patterns[0].lineageR[0].lineagePattern, 'molecules-error' ); @@ -684,11 +482,11 @@ tap.test('find_lineage - does not apply lineage twice', function(test) { var graph = patternlab.graph; var currentPatternLineageIndex = graph.lineageIndex(currentPattern); - test.equals(currentPatternLineageIndex.length, 1); - test.equals(currentPatternLineageIndex[0], 'atoms-error'); + test.equal(currentPatternLineageIndex.length, 1); + test.equal(currentPatternLineageIndex[0], 'atoms-error'); var patternZeroLineageR = graph.lineageR(patternlab.patterns[0]); - test.equals(patternZeroLineageR.length, 1); - test.equals(patternZeroLineageR[0].patternPartial, 'molecules-error'); + test.equal(patternZeroLineageR.length, 1); + test.equal(patternZeroLineageR[0].patternPartial, 'molecules-error'); test.end(); }); diff --git a/packages/core/test/list_item_hunter_tests.js b/packages/core/test/list_item_hunter_tests.js index 278de7dcc..5447f194f 100644 --- a/packages/core/test/list_item_hunter_tests.js +++ b/packages/core/test/list_item_hunter_tests.js @@ -16,10 +16,10 @@ engineLoader.loadAllEngines(config); tap.test( 'process_list_item_partials converts partial to simpler format', - test => { + (test) => { //arrange const pl = util.fakePatternLab(testPatternsPath); - const listPath = path.join('00-test', '685-list.mustache'); + const listPath = path.join('test', 'list.mustache'); const testPattern = loadPattern(listPath, pl); //usually decompose does this @@ -28,7 +28,7 @@ tap.test( //act list_item_hunter.process_list_item_partials(testPattern, pl).then(() => { //assert - test.equals( + test.equal( util.sanitized(testPattern.extendedTemplate), util.sanitized(` {{#listItems-three}} @@ -43,10 +43,10 @@ tap.test( tap.test( 'process_list_item_partials converts partial with includes to simpler format', - test => { + (test) => { //arrange const pl = util.fakePatternLab(testPatternsPath); - const listPath = path.join('00-test', 'listWithPartial.mustache'); + const listPath = path.join('test', 'listWithPartial.mustache'); const testPattern = loadPattern(listPath, pl); //usually decompose does this @@ -55,7 +55,7 @@ tap.test( //act list_item_hunter.process_list_item_partials(testPattern, pl).then(() => { //assert - test.equals( + test.equal( util.sanitized(testPattern.extendedTemplate), util.sanitized(` {{#listItems-two}} diff --git a/packages/core/test/loadPattern_tests.js b/packages/core/test/loadPattern_tests.js index 2ebec760f..d2903a6c0 100644 --- a/packages/core/test/loadPattern_tests.js +++ b/packages/core/test/loadPattern_tests.js @@ -12,91 +12,99 @@ patternEngines.loadAllEngines(config); const patterns_dir = `${__dirname}/files/_patterns`; -tap.test('loadPattern - returns null if file is not a pattern', function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - var patternPath = path.join('00-test', '03-styled-atom.json'); +tap.test( + 'loadPattern - returns null if file is not a pattern', + function (test) { + //arrange + const patternlab = util.fakePatternLab(patterns_dir); + var patternPath = path.join('test', 'styled-atom.json'); - //act - var result = loadPattern(patternPath, patternlab); + //act + var result = loadPattern(patternPath, patternlab); - //assert - test.equals(result, null); - test.end(); -}); + //assert + test.equal(result, null); + test.end(); + } +); -tap.test('loadPattern - loads pattern sibling json if found', function(test) { +tap.test('loadPattern - loads pattern sibling json if found', function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); - var patternPath = path.join('00-test', '03-styled-atom.mustache'); + var patternPath = path.join('test', 'styled-atom.mustache'); //act var result = loadPattern(patternPath, patternlab); //assert - test.equals(result.jsonFileData.message, 'baseMessage'); + test.equal(result.jsonFileData.message, 'baseMessage'); test.end(); }); tap.test( 'loadPattern - adds the pattern to the patternlab.partials object', - function(test) { + function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); - var fooPatternPath = path.join('00-test', '01-bar.mustache'); + var fooPatternPath = path.join('test', 'bar.mustache'); //act var result = loadPattern(fooPatternPath, patternlab); //assert - test.equals(util.sanitized(patternlab.partials['test-bar']), 'bar'); + test.equal(util.sanitized(patternlab.partials['test-bar']), 'bar'); test.end(); } ); -tap.test('loadPattern - returns pattern with template populated', function( - test -) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - var fooPatternPath = path.join('00-test', '01-bar.mustache'); - - //act - var result = loadPattern(fooPatternPath, patternlab); - - //assert - test.equals(util.sanitized(result.template), util.sanitized('bar')); - test.end(); -}); +tap.test( + 'loadPattern - returns pattern with template populated', + function (test) { + //arrange + const patternlab = util.fakePatternLab(patterns_dir); + var fooPatternPath = path.join('test', 'bar.mustache'); -tap.test('loadPattern - adds a markdown pattern if encountered', function( - test -) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - var colorsMarkDownPath = path.join('patternType1', 'patternSubType1.md'); + //act + var result = loadPattern(fooPatternPath, patternlab); - //act - var result = loadPattern(colorsMarkDownPath, patternlab); + //assert + test.equal(util.sanitized(result.template), util.sanitized('bar')); + test.end(); + } +); - //assert - const subTypePattern = - patternlab.subtypePatterns['patternType1-patternSubType1']; - test.equals(subTypePattern.patternSectionSubtype, true); - test.equals(subTypePattern.isPattern, false); - test.equals(subTypePattern.patternDesc, '

Colors

\n'); - test.equals(subTypePattern.engine, null); - test.equals(subTypePattern.flatPatternPath, 'patternType1-patternSubType1'); - test.equals(result, subTypePattern); - test.end(); -}); +// TODO: Fix doc pattern test when new logic in loadPattern is implemented +// tap.test('loadPattern - adds a markdown pattern if encountered', function( +// test +// ) { +// //arrange +// const patternlab = util.fakePatternLab(patterns_dir); +// var colorsMarkDownPath = path.join('patternGroup1', 'patternSubgroup1.md'); + +// //act +// var result = loadPattern(colorsMarkDownPath, patternlab); + +// //assert +// const subgroupPattern = +// patternlab.subgroupPatterns['patternGroup1-patternSubgroup1']; +// test.equal(subgroupPattern.patternSectionSubgroup, true); +// test.equal(subgroupPattern.isPattern, false); +// test.equal(subgroupPattern.patternDesc, '

Colors

\n'); +// test.equal(subgroupPattern.engine, null); +// test.equal( +// subgroupPattern.flatPatternPath, +// 'patternGroup1-patternSubgroup1' +// ); +// test.equal(result, subgroupPattern); +// test.end(); +// }); tap.test( 'loadPattern - does not load pseudopattern data on the base pattern', - test => { + (test) => { //arrange const patternlab = util.fakePatternLab(patterns_dir); - const basePatternPath = path.join('00-test', '474-pseudomodifier.mustache'); + const basePatternPath = path.join('test', 'pseudomodifier.mustache'); //act const result = loadPattern(basePatternPath, patternlab); @@ -107,3 +115,65 @@ tap.test( test.end(); } ); + +tap.test( + 'loadPattern - group and subgroup ordering will be taken from markdown files', + (test) => { + //arrange + const patternlab = util.fakePatternLab(patterns_dir); + + const basePatternAPath = path.join('orderTest', 'a', 'a-test.mustache'); + const basePatternBPath = path.join('orderTest', 'b', 'b-test.mustache'); + const basePatternCPath = path.join( + 'orderTest', + 'c', + 'subfolder', + 'subfolder.mustache' + ); + + //act + const resultPatternA = loadPattern(basePatternAPath, patternlab); + const resultPatternB = loadPattern(basePatternBPath, patternlab); + const resultPatternC = loadPattern(basePatternCPath, patternlab); + + //assert + console.log(resultPatternA.patternGroupData.order); + test.same( + resultPatternA.patternGroupData.order, + 1, + 'Pattern group should be loaded as 1' + ); + console.log(resultPatternA.patternSubgroupData.order || 0); + test.same( + resultPatternA.patternSubgroupData.order || 0, + 0, + 'Pattern Subgroup not be availabe and default to 0' + ); + + console.log(resultPatternB.patternGroupData.order); + test.same( + resultPatternB.patternGroupData.order, + 1, + 'Pattern group should be loaded as 1' + ); + console.log(resultPatternB.patternSubgroupData.order); + test.same( + resultPatternB.patternSubgroupData.order, + 2, + 'Pattern Subgroup should be loaded as 2' + ); + + test.same( + resultPatternC.patternGroupData.order, + 1, + 'Pattern group should be loaded as 1' + ); + test.same( + resultPatternC.patternSubgroupData.order, + -1, + 'Pattern Subgroup should be loaded as -1' + ); + + test.end(); + } +); diff --git a/packages/core/test/loaduitkits_tests.js b/packages/core/test/loaduitkits_tests.js index c0fc9a4b1..a4cf2bd3b 100644 --- a/packages/core/test/loaduitkits_tests.js +++ b/packages/core/test/loaduitkits_tests.js @@ -1,116 +1,72 @@ 'use strict'; const tap = require('tap'); +const path = require('path'); const rewire = require('rewire'); +const logger = require('../src/lib/log'); const loaduikits = rewire('../src/lib/loaduikits'); const testConfig = require('./util/patternlab-config.json'); -const findModulesMock = function() { - return [ - { - name: 'foo', - modulePath: 'node_modules/@pattern-lab/uikit-foo', - }, - { - name: 'bar', - modulePath: 'node_modules/@pattern-lab/uikit-bar', - }, - { - name: 'baz', - modulePath: 'node_modules/@pattern-lab/uikit-baz', - }, - ]; -}; +tap.test('loaduikits - does warn on missing package property', (test) => { + //arrange + const patternlab = { + config: testConfig, + uikits: {}, + }; -const fsMock = { - readFileSync: function(path, encoding) { - return 'file'; - }, -}; + patternlab.config.logLevel = 'warning'; + logger.log.on('warning', (msg) => test.ok(msg.includes('package:'))); -loaduikits.__set__({ - findModules: findModulesMock, - fs: fsMock, + //act + loaduikits(patternlab).then(() => { + logger.warning = () => {}; + test.done(); + }); }); -tap.test('loaduikits - maps fields correctly', function(test) { +tap.test('loaduikits - maps fields correctly', function (test) { //arrange const patternlab = { config: testConfig, - uikits: [], - }; - - const uikitFoo = { - name: 'uikit-foo', - enabled: true, - outputDir: 'foo', - excludedPatternStates: ['legacy'], - excludedTags: ['baz'], + uikits: {}, }; - patternlab.config.uikits = [uikitFoo]; - //act loaduikits(patternlab).then(() => { //assert - test.equals(patternlab.uikits['uikit-foo'].name, uikitFoo.name); - test.equals( - patternlab.uikits['uikit-foo'].modulePath, - 'node_modules/@pattern-lab/uikit-foo' - ); - test.ok(patternlab.uikits['uikit-foo'].enabled); - test.equals(patternlab.uikits['uikit-foo'].outputDir, uikitFoo.outputDir); - test.equals( - patternlab.uikits['uikit-foo'].excludedPatternStates, - uikitFoo.excludedPatternStates + test.equal(patternlab.uikits['uikit-workshop'].name, 'uikit-workshop'); + test.equal( + patternlab.uikits['uikit-workshop'].package, + '@pattern-lab/uikit-workshop' ); - test.equals( - patternlab.uikits['uikit-foo'].excludedTags, - uikitFoo.excludedTags + test.contains( + patternlab.uikits['uikit-workshop'].modulePath, + path.join('packages', 'uikit-workshop') ); + test.ok(patternlab.uikits['uikit-workshop'].enabled); + test.equal(patternlab.uikits['uikit-workshop'].outputDir, 'test/'); + test.deepEquals(patternlab.uikits['uikit-workshop'].excludedPatternStates, [ + 'legacy', + ]); + test.deepEquals(patternlab.uikits['uikit-workshop'].excludedTags, ['baz']); test.end(); }); }); -tap.test('loaduikits - only adds files for enabled uikits', function(test) { +tap.test('loaduikits - only adds files for enabled uikits', function (test) { //arrange const patternlab = { config: testConfig, - uikits: [], + uikits: {}, }; - patternlab.config.uikits = [ - { - name: 'uikit-foo', - enabled: true, - outputDir: 'foo', - excludedPatternStates: ['legacy'], - excludedTags: ['baz'], - }, - { - name: 'uikit-bar', - enabled: true, - outputDir: 'bar', - excludedPatternStates: ['development'], - excludedTags: ['baz', 'foo'], - }, - { - name: 'uikit-baz', - enabled: false, - outputDir: 'baz', - excludedPatternStates: [''], - excludedTags: [], - }, - ]; - //act loaduikits(patternlab).then(() => { //assert - test.ok(patternlab.uikits['uikit-foo']); - test.ok(patternlab.uikits['uikit-bar']); - test.notOk(patternlab.uikits['uikit-baz']); + test.ok(patternlab.uikits['uikit-workshop']); + test.notOk(patternlab.uikits['uikit-polyfills']); test.end(); }); }); diff --git a/packages/core/test/markModifiedPatterns_tests.js b/packages/core/test/markModifiedPatterns_tests.js index 173e0283f..18f06d646 100644 --- a/packages/core/test/markModifiedPatterns_tests.js +++ b/packages/core/test/markModifiedPatterns_tests.js @@ -13,7 +13,7 @@ const markModifiedPatterns = rewire('../src/lib/markModifiedPatterns'); const config = require('./util/patternlab-config.json'); const fsMock = { - readFileSync: function(path, encoding, cb) { + readFileSync: function (path, encoding, cb) { return ''; }, }; @@ -28,7 +28,7 @@ const public_dir = './test/public'; tap.only( 'markModifiedPatterns - finds patterns modified since a given date', - function(test) { + function (test) { //arrange markModifiedPatterns.__set__('fs', fsMock); @@ -40,7 +40,7 @@ tap.only( markupOnly: '.markup-only', }; - var pattern = new Pattern('00-test/01-bar.mustache'); + var pattern = new Pattern('test/bar.mustache'); pattern.extendedTemplate = undefined; pattern.template = 'bar'; @@ -75,7 +75,7 @@ tap.only( tap.test( 'markModifiedPatterns - finds patterns when modification date is missing', - function(test) { + function (test) { //arrange var patternlab = emptyPatternLab(); patternlab.partials = {}; @@ -83,7 +83,7 @@ tap.test( patternlab.config = { logLevel: 'quiet' }; patternlab.config.outputFileSuffixes = { rendered: '' }; - var pattern = new Pattern('00-test/01-bar.mustache'); + var pattern = new Pattern('test/bar.mustache'); pattern.extendedTemplate = undefined; pattern.template = 'bar'; pattern.lastModified = undefined; @@ -96,24 +96,25 @@ tap.test( ); // This is the case when we want to force recompilation -tap.test('markModifiedPatterns - finds patterns via compile state', function( - test -) { - //arrange - var patternlab = emptyPatternLab(); - patternlab.partials = {}; - patternlab.data = { link: {} }; - patternlab.config = { logLevel: 'quiet' }; - patternlab.config.outputFileSuffixes = { rendered: '' }; - - var pattern = new Pattern('00-test/01-bar.mustache'); - pattern.extendedTemplate = undefined; - pattern.template = 'bar'; - pattern.lastModified = 100000; - pattern.compileState = CompileState.NEEDS_REBUILD; - patternlab.patterns = [pattern]; - - let p = markModifiedPatterns(1000, patternlab); - test.same(p.modified.length, 1); - test.end(); -}); +tap.test( + 'markModifiedPatterns - finds patterns via compile state', + function (test) { + //arrange + var patternlab = emptyPatternLab(); + patternlab.partials = {}; + patternlab.data = { link: {} }; + patternlab.config = { logLevel: 'quiet' }; + patternlab.config.outputFileSuffixes = { rendered: '' }; + + var pattern = new Pattern('test/bar.mustache'); + pattern.extendedTemplate = undefined; + pattern.template = 'bar'; + pattern.lastModified = 100000; + pattern.compileState = CompileState.NEEDS_REBUILD; + patternlab.patterns = [pattern]; + + let p = markModifiedPatterns(1000, patternlab); + test.same(p.modified.length, 1); + test.end(); + } +); diff --git a/packages/core/test/markdown_parser_tests.js b/packages/core/test/markdown_parser_tests.js index 3e25a5934..717f5b27f 100644 --- a/packages/core/test/markdown_parser_tests.js +++ b/packages/core/test/markdown_parser_tests.js @@ -9,10 +9,10 @@ var markdown_parser = new mp(); tap.test( 'parses pattern description block correctly when frontmatter not present', - function(test) { + function (test) { //arrange var markdownFileName = path.resolve( - `${__dirname}/files/_patterns/00-test/02-baz.md` + `${__dirname}/files/_patterns/test/baz.md` ); var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8'); @@ -20,17 +20,17 @@ tap.test( var returnObject = markdown_parser.parse(markdownFileContents); //assert - test.equals(returnObject.markdown, '

Only baz

\n'); + test.equal(returnObject.markdown, '

Only baz

\n'); test.end(); } ); tap.test( 'parses pattern description block correctly when frontmatter present', - function(test) { + function (test) { //arrange var markdownFileName = path.resolve( - `${__dirname}/files/_patterns/00-test/01-bar.md` + `${__dirname}/files/_patterns/test/bar.md` ); var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8'); @@ -38,19 +38,19 @@ tap.test( var returnObject = markdown_parser.parse(markdownFileContents); //assert - test.equals( + test.equal( returnObject.markdown, '

A Simple Bit of Markup

\n

Foo cannot get simpler than bar, amiright?

\n' ); - test.equals(returnObject.state, 'complete'); + test.equal(returnObject.state, 'complete'); test.end(); } ); -tap.test('parses frontmatter only when no markdown present', function(test) { +tap.test('parses frontmatter only when no markdown present', function (test) { //arrange var markdownFileName = path.resolve( - `${__dirname}/files/_patterns/00-test/03-styled-atom.md` + `${__dirname}/files/_patterns/test/styled-atom.md` ); var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8'); @@ -58,7 +58,7 @@ tap.test('parses frontmatter only when no markdown present', function(test) { var returnObject = markdown_parser.parse(markdownFileContents); //assert - test.equals(returnObject.markdown, ''); - test.equals(returnObject.state, 'inprogress'); + test.equal(returnObject.markdown, ''); + test.equal(returnObject.state, 'inprogress'); test.end(); }); diff --git a/packages/core/test/object_factory_tests.js b/packages/core/test/object_factory_tests.js index 463dce978..6684628df 100644 --- a/packages/core/test/object_factory_tests.js +++ b/packages/core/test/object_factory_tests.js @@ -30,121 +30,301 @@ var pl = fakePatternLab(); var engineLoader = require('../src/lib/pattern_engines'); engineLoader.loadAllEngines(config); -tap.test('test Pattern initializes correctly', function(test) { - var p = new Pattern('00-atoms/00-global/00-colors.mustache', { d: 123 }); - test.equals( +tap.test('test Pattern initializes correctly', function (test) { + var p = new Pattern('atoms/global/colors.mustache', { d: 123 }); + test.equal( p.relPath, - '00-atoms' + path.sep + '00-global' + path.sep + '00-colors.mustache' + 'atoms' + path.sep + 'global' + path.sep + 'colors.mustache' ); - test.equals(p.name, '00-atoms-00-global-00-colors'); - test.equals(p.subdir, '00-atoms' + path.sep + '00-global'); - test.equals(p.fileName, '00-colors'); - test.equals(p.fileExtension, '.mustache'); - test.equals(p.jsonFileData.d, 123); - test.equals(p.patternBaseName, 'colors'); - test.equals(p.patternName, 'Colors'); - test.equals( + test.equal(p.name, 'atoms-global-colors'); + test.equal(p.subdir, 'atoms' + path.sep + 'global'); + test.equal(p.fileName, 'colors'); + test.equal(p.fileExtension, '.mustache'); + test.equal(p.jsonFileData.d, 123); + test.equal(p.patternBaseName, 'colors'); + test.equal(p.patternName, 'Colors'); + test.equal( p.getPatternLink(pl), - '00-atoms-00-global-00-colors' + - path.sep + - '00-atoms-00-global-00-colors.rendered.html' + 'atoms-global-colors' + path.sep + 'atoms-global-colors.rendered.html' ); - test.equals(p.patternGroup, 'atoms'); - test.equals(p.patternSubGroup, 'global'); - test.equals(p.flatPatternPath, '00-atoms-00-global'); - test.equals(p.patternPartial, 'atoms-colors'); - test.equals(p.template, ''); - test.equals(p.patternPartialCode, ''); - test.equals(p.lineage.length, 0); - test.equals(p.lineageIndex.length, 0); - test.equals(p.lineageR.length, 0); - test.equals(p.lineageRIndex.length, 0); - test.equals(p.patternState, ''); + test.equal(p.patternGroup, 'atoms'); + test.equal(p.patternSubgroup, 'global'); + test.equal(p.flatPatternPath, 'atoms-global'); + test.equal(p.patternPartial, 'atoms-colors'); + test.equal(p.template, ''); + test.equal(p.patternPartialCode, ''); + test.equal(p.lineage.length, 0); + test.equal(p.lineageIndex.length, 0); + test.equal(p.lineageR.length, 0); + test.equal(p.lineageRIndex.length, 0); + test.equal(p.patternState, ''); test.end(); }); -tap.test('test Pattern with one-directory subdir works as expected', function( - test -) { - var p = new Pattern('00-atoms/00-colors.mustache', { d: 123 }); - test.equals(p.relPath, '00-atoms' + path.sep + '00-colors.mustache'); - test.equals(p.name, '00-atoms-00-colors'); - test.equals(p.subdir, '00-atoms'); - test.equals(p.fileName, '00-colors'); - test.equals(p.fileExtension, '.mustache'); - test.equals(p.jsonFileData.d, 123); - test.equals(p.patternBaseName, 'colors'); - test.equals(p.patternName, 'Colors'); - test.equals( - p.getPatternLink(pl), - '00-atoms-00-colors' + path.sep + '00-atoms-00-colors.rendered.html' - ); - test.equals(p.patternGroup, 'atoms'); - test.equals(p.flatPatternPath, '00-atoms'); - test.equals(p.patternPartial, 'atoms-colors'); - test.equals(p.template, ''); - test.equals(p.lineage.length, 0); - test.equals(p.lineageIndex.length, 0); - test.equals(p.lineageR.length, 0); - test.equals(p.lineageRIndex.length, 0); - test.end(); -}); +tap.test( + 'test Pattern initializes correctly with pattern in sepatated directory', + function (test) { + var p = new Pattern('atoms/global/colors/colors.mustache', { + d: 123, + }); + test.equal( + p.relPath, + 'atoms' + + path.sep + + 'global' + + path.sep + + 'colors' + + path.sep + + 'colors.mustache' + ); + test.equal(p.name, 'atoms-global-colors'); + test.equal(p.subdir, path.join('atoms', 'global', 'colors')); + test.equal(p.fileName, 'colors'); + test.equal(p.fileExtension, '.mustache'); + test.equal(p.jsonFileData.d, 123); + test.equal(p.patternBaseName, 'colors'); + test.equal(p.patternName, 'Colors'); + test.equal( + p.getPatternLink(pl), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.rendered.html' + ); + test.equal(p.patternGroup, 'atoms'); + test.equal(p.patternSubgroup, 'global'); + test.equal(p.flatPatternPath, 'atoms-global'); + test.equal(p.patternPartial, 'atoms-colors'); + test.equal(p.template, ''); + test.equal(p.patternPartialCode, ''); + test.equal(p.lineage.length, 0); + test.equal(p.lineageIndex.length, 0); + test.equal(p.lineageR.length, 0); + test.equal(p.lineageRIndex.length, 0); + test.equal(p.patternState, ''); + test.end(); + } +); + +tap.test( + 'test Pattern name for variants correctly initialzed', + function (test) { + var p1 = new Pattern('atoms/global/colors/colors~variant.mustache', { + d: 123, + }); + var p2 = new Pattern('atoms/global/colors/colors~variant-minus.json', { + d: 123, + }); + test.equal(p1.name, 'atoms-global-colors-variant'); + test.equal(p2.name, 'atoms-global-colors-variant-minus'); + test.end(); + } +); + +tap.test( + 'test Pattern with one-directory subdir works as expected', + function (test) { + var p = new Pattern('atoms/colors.mustache', { d: 123 }); + test.equal(p.relPath, 'atoms' + path.sep + 'colors.mustache'); + test.equal(p.name, 'atoms-colors'); + test.equal(p.subdir, 'atoms'); + test.equal(p.fileName, 'colors'); + test.equal(p.fileExtension, '.mustache'); + test.equal(p.jsonFileData.d, 123); + test.equal(p.patternBaseName, 'colors'); + test.equal(p.patternName, 'Colors'); + test.equal( + p.getPatternLink(pl), + 'atoms-colors' + path.sep + 'atoms-colors.rendered.html' + ); + test.equal(p.patternGroup, 'atoms'); + test.equal(p.flatPatternPath, 'atoms'); + test.equal(p.patternPartial, 'atoms-colors'); + test.equal(p.template, ''); + test.equal(p.lineage.length, 0); + test.equal(p.lineageIndex.length, 0); + test.equal(p.lineageR.length, 0); + test.equal(p.lineageRIndex.length, 0); + test.end(); + } +); + +tap.test( + 'test Pattern with own-directory gets resetted as expected', + function (test) { + var p = new Pattern('atoms/button/button.mustache', { d: 123 }, pl); + p.promoteFromDirectoryToFlatPattern(pl); + + test.equal(p.relPath, path.join('atoms', 'button', 'button.mustache')); + test.equal(p.name, 'atoms-button'); + test.equal(p.subdir, path.join('atoms', 'button')); + test.equal(p.fileName, 'button'); + test.equal(p.fileExtension, '.mustache'); + test.equal(p.jsonFileData.d, 123); + test.equal(p.patternBaseName, 'button'); + test.equal(p.patternName, 'Button'); + test.equal( + p.getPatternLink(pl), + path.join('atoms-button', 'atoms-button.rendered.html') + ); + test.equal(p.patternGroup, 'atoms'); + test.equal(p.flatPatternPath, 'atoms'); + test.equal(p.patternPartial, 'atoms-button'); + test.equal(p.template, ''); + test.equal(p.lineage.length, 0); + test.equal(p.lineageIndex.length, 0); + test.equal(p.lineageR.length, 0); + test.equal(p.lineageRIndex.length, 0); + test.end(); + } +); tap.test( 'test Pattern with no numbers in pattern group works as expected', - function(test) { + function (test) { var p = new Pattern('atoms/colors.mustache', { d: 123 }); - test.equals(p.relPath, 'atoms' + path.sep + 'colors.mustache'); - test.equals(p.name, 'atoms-colors'); - test.equals(p.subdir, 'atoms'); - test.equals(p.fileName, 'colors'); - test.equals( + test.equal(p.relPath, 'atoms' + path.sep + 'colors.mustache'); + test.equal(p.name, 'atoms-colors'); + test.equal(p.subdir, 'atoms'); + test.equal(p.fileName, 'colors'); + test.equal( p.getPatternLink(pl), 'atoms-colors' + path.sep + 'atoms-colors.rendered.html' ); - test.equals(p.patternGroup, 'atoms'); - test.equals(p.flatPatternPath, 'atoms'); - test.equals(p.patternPartial, 'atoms-colors'); + test.equal(p.patternGroup, 'atoms'); + test.equal(p.flatPatternPath, 'atoms'); + test.equal(p.patternPartial, 'atoms-colors'); test.end(); } ); -tap.test('test Pattern capitalizes patternDisplayName correctly', function( - test -) { - var p = new Pattern('00-atoms/00-global/00-colors-alt.mustache', { d: 123 }); - test.equals(p.patternBaseName, 'colors-alt'); - test.equals(p.patternName, 'Colors Alt'); - test.end(); -}); +tap.test( + 'test Pattern capitalizes patternDisplayName correctly', + function (test) { + var p = new Pattern('atoms/global/colors-alt.mustache', { d: 123 }); + test.equal(p.patternBaseName, 'colors-alt'); + test.equal(p.patternName, 'Colors Alt'); + test.end(); + } +); -tap.test('The forms of Pattern.getPatternLink() work as expected', function( - test -) { - var p = new Pattern('00-atoms/00-global/00-colors.hbs'); - test.equals( - p.getPatternLink(pl), - '00-atoms-00-global-00-colors' + - path.sep + - '00-atoms-00-global-00-colors.rendered.html' - ); - test.equals( - p.getPatternLink(pl, 'rendered'), - '00-atoms-00-global-00-colors' + - path.sep + - '00-atoms-00-global-00-colors.rendered.html' - ); - test.equals( - p.getPatternLink(pl, 'rawTemplate'), - '00-atoms-00-global-00-colors' + - path.sep + - '00-atoms-00-global-00-colors.hbs' - ); - test.equals( - p.getPatternLink(pl, 'markupOnly'), - '00-atoms-00-global-00-colors' + - path.sep + - '00-atoms-00-global-00-colors.markup-only.html' - ); - test.end(); -}); +tap.test( + 'test Pattern get dir level no separated pattern directory', + function (test) { + var p = new Pattern('atoms/global/colors-alt.mustache', { d: 123 }); + console.log(p); + test.equal(p.getDirLevel(0, { patternHasOwnDir: false }), 'atoms'); + test.equal(p.getDirLevel(1, { patternHasOwnDir: false }), 'global'); + test.equal(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third level + var p = new Pattern('atoms/colors-alt.mustache', { d: 123 }); + test.equal(p.getDirLevel(0, { patternHasOwnDir: false }), 'atoms'); + test.equal(p.getDirLevel(1, { patternHasOwnDir: false }), ''); // There is no second level + test.equal(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third level + var p = new Pattern('colors-alt.mustache', { d: 123 }); + test.equal(p.getDirLevel(0, { patternHasOwnDir: false }), 'root'); // No first level means root + test.equal(p.getDirLevel(1, { patternHasOwnDir: false }), ''); // There is no second level + test.equal(p.getDirLevel(2, { patternHasOwnDir: false }), ''); // There is no third leveL + test.end(); + } +); + +tap.test( + 'test Pattern get dir level with separated pattern directory', + function (test) { + var p = new Pattern('atoms/global/colors-alt/colors-alt.mustache', { + d: 123, + }); + test.equal(p.getDirLevel(0, { patternHasOwnDir: true }), 'atoms'); + test.equal(p.getDirLevel(1, { patternHasOwnDir: true }), 'global'); + test.equal(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third level + + var p = new Pattern('atoms/colors-alt/colors-alt.mustache', { + d: 123, + }); + test.equal(p.getDirLevel(0, { patternHasOwnDir: true }), 'atoms'); + test.equal(p.getDirLevel(1, { patternHasOwnDir: true }), ''); // There is no second level + test.equal(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third level + + var p = new Pattern('colors-alt/colors-alt.mustache', { d: 123 }); + test.equal(p.getDirLevel(0, { patternHasOwnDir: true }), 'root'); // No first level means root + test.equal(p.getDirLevel(1, { patternHasOwnDir: true }), ''); // There is no second level + test.equal(p.getDirLevel(2, { patternHasOwnDir: true }), ''); // There is no third leveL + + var p = new Pattern('atoms/global/colors-alt/colors-alt~variant.mustache', { + d: 123, + }); + test.equal(p.name, 'atoms-global-colors-alt-variant'); + test.equal(p.flatPatternPath, 'atoms-global'); + test.equal(p.patternBaseName, 'colors-alt-variant'); + + test.end(); + } +); + +tap.test( + 'test Patterns that are nested deeper without own directory', + function (test) { + var p = new Pattern('atoms/global/random-folder/colors-alt.mustache', { + d: 123, + }); + test.equal(p.name, 'atoms-global-colors-alt'); + test.equal(p.flatPatternPath, 'atoms-global'); + + var p = new Pattern( + 'atoms/global/random-folder/another-folder/colors-alt.mustache', + { + d: 123, + } + ); + test.equal(p.name, 'atoms-global-colors-alt'); + test.equal(p.flatPatternPath, 'atoms-global'); + + var p = new Pattern( + 'atoms/global/random-folder/another-folder/some-folder/colors-alt.mustache', + { d: 123 } + ); + test.equal(p.name, 'atoms-global-colors-alt'); + test.equal(p.flatPatternPath, 'atoms-global'); + + var p = new Pattern( + 'atoms/global/random-folder/another-folder/colors-alt/colors-alt.mustache', + { d: 123 } + ); + test.equal(p.name, 'atoms-global-colors-alt'); + test.equal(p.flatPatternPath, 'atoms-global'); + + var p = new Pattern( + 'atoms/global/random-folder/another-folder/some-folder/colors-alt~variant.mustache', + { d: 123 } + ); + test.equal(p.name, 'atoms-global-colors-alt-variant'); + test.equal(p.flatPatternPath, 'atoms-global'); + test.equal(p.patternBaseName, 'colors-alt-variant'); + test.end(); + } +); + +tap.test( + 'The forms of Pattern.getPatternLink() work as expected', + function (test) { + var p = new Pattern('atoms/global/colors.hbs'); + test.equal( + p.getPatternLink(pl), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.rendered.html' + ); + test.equal( + p.getPatternLink(pl, 'rendered'), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.rendered.html' + ); + test.equal( + p.getPatternLink(pl, 'rawTemplate'), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.hbs' + ); + test.equal( + p.getPatternLink(pl, 'markupOnly'), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.markup-only.html' + ); + test.equal( + p.getPatternLink(pl, 'custom', '.custom-extension'), + 'atoms-global-colors' + path.sep + 'atoms-global-colors.custom-extension' + ); + test.end(); + } +); diff --git a/packages/core/test/parameter_hunter_tests.js b/packages/core/test/parameter_hunter_tests.js deleted file mode 100644 index 3c3328648..000000000 --- a/packages/core/test/parameter_hunter_tests.js +++ /dev/null @@ -1,465 +0,0 @@ -'use strict'; - -const path = require('path'); -const util = require('./util/test_utils.js'); -const tap = require('tap'); - -const loadPattern = require('../src/lib/loadPattern'); -const ph = require('../src/lib/parameter_hunter'); -const processIterative = require('../src/lib/processIterative'); - -const parameter_hunter = new ph(); - -const config = require('./util/patternlab-config.json'); -const engineLoader = require('../src/lib/pattern_engines'); -engineLoader.loadAllEngines(config); - -const testPatternsPath = path.resolve(__dirname, 'files', '_patterns'); - -tap.test('parameter hunter finds and extends templates', function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]) - .then(() => { - //act - parameter_hunter - .find_parameters(testPattern, pl) - .then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized( - '

{{foo}}

A life is like a garden. Perfect moments can be had, but not preserved, except in memory.

' - ) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); -}); - -tap.test( - 'parameter hunter finds and extends templates with verbose partials', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join( - '00-test', - 'sticky-comment-verbose.mustache' - ); - var testPattern = loadPattern(testPatternPath, pl); - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]) - .then(() => { - //act - parameter_hunter - .find_parameters(testPattern, pl) - .then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized( - '

{{foo}}

A life is like a garden. Perfect moments can be had, but not preserved, except in memory.

' - ) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -//previous tests were for unquoted parameter keys and single-quoted values. -//test other quoting options. -tap.test( - 'parameter hunter parses parameters with unquoted keys and unquoted values', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = '{{> test-comment(description: true) }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with unquoted keys and double-quoted values', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = '{{> test-comment(description: "true") }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with single-quoted keys and unquoted values', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = "{{> test-comment('description': true) }}"; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with single-quoted keys and single-quoted values wrapping internal escaped single-quotes', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - "{{> test-comment('description': 'true not,\\'true\\'') }}"; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized(`

{{foo}}

true not,'true'

`) - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with single-quoted keys and double-quoted values wrapping internal single-quotes', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - "{{> test-comment('description': \"true not:'true'\") }}"; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized(`

{{foo}}

true not:'true'

`) - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with double-unquoted keys and unquoted values', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = '{{> test-comment("description": true) }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with double-quoted keys and single-quoted values wrapping internal double-quotes', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - '{{> test-comment("description": \'true not{"true"\') }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true not{"true"

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with double-quoted keys and double-quoted values wrapping internal escaped double-quotes', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - '{{> test-comment("description": "true not}\\"true\\"") }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

true not}"true"

') - ); - test.end(); - }); - }); - } -); - -tap.test( - 'parameter hunter parses parameters with combination of quoting schemes for keys and values', - function(test) { - //arrange - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - '{{> test-comment(description: true, \'foo\': false, "bar": false, \'single\': true, \'singlesingle\': \'true\', \'singledouble\': "true", "double": true, "doublesingle": \'true\', "doubledouble": "true") }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

false

true

') - ); - test.end(); - }); - }); - } -); - -//todo https://github.com/pattern-lab/patternlab-node/issues/673 -// tap.test('parameter hunter parses parameters with values containing a closing parenthesis', function (test) { -// //arrange -// const pl = util.fakePatternLab(testPatternsPath); - -// var commentPath = path.join('00-test', 'comment.mustache'); -// var commentPattern = loadPattern(commentPath, pl); - -// var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); -// var testPattern = loadPattern(testPatternPath, pl); - -// //override the file -// testPattern.template = "{{> test-comment(description: 'Hello ) World') }}"; -// testPattern.extendedTemplate = testPattern.template; -// testPattern.parameteredPartials[0] = testPattern.template; - -// var p1 = processIterative(commentPattern, pl); -// var p2 = processIterative(testPattern, pl); - -// Promise.all([p1, p2]).then(() => { -// //act -// parameter_hunter.find_parameters(testPattern, pl).then(() => { -// //assert -// test.equals(util.sanitized(testPattern.extendedTemplate), util.sanitized('

Hello ) World

')); -// test.end(); -// }); -// }); -// }); - -tap.test('parameter hunter skips malformed parameters', function(test) { - const pl = util.fakePatternLab(testPatternsPath); - - var commentPath = path.join('00-test', 'comment.mustache'); - var commentPattern = loadPattern(commentPath, pl); - - var testPatternPath = path.join('00-test', 'sticky-comment.mustache'); - var testPattern = loadPattern(testPatternPath, pl); - - //override the file - testPattern.template = - '{{> test-comment( missing-val: , : missing-key, : , , foo: "Hello World") }}'; - testPattern.extendedTemplate = testPattern.template; - testPattern.parameteredPartials[0] = testPattern.template; - - var p1 = processIterative(commentPattern, pl); - var p2 = processIterative(testPattern, pl); - - Promise.all([p1, p2]).then(() => { - //act - parameter_hunter.find_parameters(testPattern, pl).then(() => { - //assert - console.log( - '\nPattern Lab should catch JSON.parse() errors and output useful debugging information...' - ); - test.equals( - util.sanitized(testPattern.extendedTemplate), - util.sanitized('

{{foo}}

{{description}}

') - ); - test.end(); - }); - }); -}); diff --git a/packages/core/test/parseAllLinks_tests.js b/packages/core/test/parseAllLinks_tests.js index 271b3ee5b..7077bf454 100644 --- a/packages/core/test/parseAllLinks_tests.js +++ b/packages/core/test/parseAllLinks_tests.js @@ -17,20 +17,26 @@ const patterns_dir = './test/files/_patterns'; tap.test( 'parseDataLinks - replaces found link.* data for their expanded links', - function(test) { + function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); patternlab.graph = PatternGraph.empty(); - patternlab.patterns = [ - Pattern.createEmpty({ patternPartial: 'twitter-brad' }, patternlab), - Pattern.createEmpty({ patternPartial: 'twitter-dave' }, patternlab), - Pattern.createEmpty({ patternPartial: 'twitter-brian' }, patternlab), - ]; - patternlab.data.link = {}; + addPattern(new Pattern('twitter/brad.hbs', {}, patternlab), patternlab); + addPattern(new Pattern('twitter/dave.hbs', {}, patternlab), patternlab); + addPattern(new Pattern('twitter/brian.hbs', {}, patternlab), patternlab); + addPattern( + new Pattern('twitter/people/someone.hbs', {}, patternlab), + patternlab + ); + // Test with pattern prefix + addPattern( + new Pattern('facebook/people/someone2.hbs', {}, patternlab), + patternlab + ); // copies essential logic from loadPattern - const navPattern = new Pattern('00-test/nav.mustache'); + const navPattern = new Pattern('test/nav.mustache', {}, patternlab); const patternData = dataLoader.loadDataFromFile( path.resolve( __dirname, @@ -43,74 +49,138 @@ tap.test( navPattern.jsonFileData = patternData; addPattern(navPattern, patternlab); - //for the sake of the test, also imagining I have the following pages... - patternlab.data.link['twitter-brad'] = 'https://twitter.com/brad_frost'; - patternlab.data.link['twitter-dave'] = 'https://twitter.com/dmolsen'; - patternlab.data.link['twitter-brian'] = 'https://twitter.com/bmuenzenmeyer'; - patternlab.data.brad = { url: 'link.twitter-brad' }; patternlab.data.dave = { url: 'link.twitter-dave' }; patternlab.data.brian = { url: 'link.twitter-brian' }; + patternlab.data.someone = { url: 'link.twitter-someone' }; + patternlab.data.someone2 = { url: 'link.facebook-someone2' }; - let pattern; - for (let i = 0; i < patternlab.patterns.length; i++) { - if (patternlab.patterns[i].patternPartial === 'test-nav') { - pattern = patternlab.patterns[i]; - } - } + let pattern = patternlab.patterns.find( + (p) => p.patternPartial === 'test-nav' + ); //assert before - test.equals( + test.equal( pattern.jsonFileData.brad.url, 'link.twitter-brad', 'brad pattern data should be found' ); - test.equals( + test.equal( pattern.jsonFileData.dave.url, 'link.twitter-dave', 'dave pattern data should be found' ); - test.equals( + test.equal( pattern.jsonFileData.brian.url, 'link.twitter-brian', 'brian pattern data should be found' ); + test.equal( + pattern.jsonFileData.someone.url, + 'link.twitter-someone', + 'brian pattern data should be found' + ); + test.equal( + pattern.jsonFileData.someone2.url, + 'link.facebook-someone2', + 'brian pattern data should be found' + ); + test.equal( + pattern.jsonFileData['viewall-twitter'].url, + 'link.viewall-twitter-all', + 'view all twitter link should be found' + ); + test.equal( + pattern.jsonFileData['viewall-twitter-people'].url, + 'link.viewall-twitter-people', + 'view all twitter people link should be found' + ); + test.equal( + pattern.jsonFileData['viewall-facebook'].url, + 'link.viewall-facebook-all', + 'view all facebook link should be found' + ); + test.equal( + pattern.jsonFileData['viewall-facebook-people'].url, + 'link.viewall-facebook-people', + 'view all facebook people link should be found' + ); //act parseAllLinks(patternlab); //assert after - test.equals( + test.equal( pattern.jsonFileData.brad.url, - 'https://twitter.com/brad_frost', + '/patterns/twitter-brad/twitter-brad.rendered.html', 'brad pattern data should be replaced' ); - test.equals( + test.equal( pattern.jsonFileData.dave.url, - 'https://twitter.com/dmolsen', + '/patterns/twitter-dave/twitter-dave.rendered.html', 'dave pattern data should be replaced' ); - test.equals( + test.equal( pattern.jsonFileData.brian.url, - 'https://twitter.com/bmuenzenmeyer', + '/patterns/twitter-brian/twitter-brian.rendered.html', 'brian pattern data should be replaced' ); + test.equal( + pattern.jsonFileData.someone.url, + '/patterns/twitter-people-someone/twitter-people-someone.rendered.html', + 'twitter people someone pattern data should be replaced' + ); + test.equal( + pattern.jsonFileData.someone2.url, + '/patterns/facebook-people-someone2/facebook-people-someone2.rendered.html', + 'facebook people someone2 pattern data should be replaced with prefix pattern' + ); + test.equal( + pattern.jsonFileData['viewall-twitter'].url, + '/patterns/twitter/index.html', + 'view all twitter link should be replaced' + ); + test.equal( + pattern.jsonFileData['viewall-twitter-people'].url, + '/patterns/twitter-people/index.html', + 'view all twitter people link should be replaced' + ); + test.equal( + pattern.jsonFileData['viewall-facebook'].url, + '/patterns/facebook/index.html', + 'view all facebook link should be replaced' + ); + test.equal( + pattern.jsonFileData['viewall-facebook-people'].url, + '/patterns/facebook-people/index.html', + 'view all facebook people link should be replaced' + ); - test.equals( + test.equal( patternlab.data.brad.url, - 'https://twitter.com/brad_frost', + '/patterns/twitter-brad/twitter-brad.rendered.html', 'global brad data should be replaced' ); - test.equals( + test.equal( patternlab.data.dave.url, - 'https://twitter.com/dmolsen', + '/patterns/twitter-dave/twitter-dave.rendered.html', 'global dave data should be replaced' ); - test.equals( + test.equal( patternlab.data.brian.url, - 'https://twitter.com/bmuenzenmeyer', + '/patterns/twitter-brian/twitter-brian.rendered.html', 'global brian data should be replaced' ); + test.equal( + patternlab.data.someone.url, + '/patterns/twitter-people-someone/twitter-people-someone.rendered.html', + 'twitter people someone pattern data should be replaced' + ); + test.equal( + patternlab.data.someone2.url, + '/patterns/facebook-people-someone2/facebook-people-someone2.rendered.html', + 'facebook people someone2 pattern data should be replaced with prefix pattern' + ); test.end(); } ); diff --git a/packages/core/test/patternWrapClasses_tests.js b/packages/core/test/patternWrapClasses_tests.js new file mode 100644 index 000000000..a00d06dd1 --- /dev/null +++ b/packages/core/test/patternWrapClasses_tests.js @@ -0,0 +1,53 @@ +'use strict'; + +const path = require('path'); +const tap = require('tap'); + +const loadPattern = require('../src/lib/loadPattern'); +const patternWrapClassesChangePatternTemplate = require('../src/lib/patternWrapClasses'); +const util = require('./util/test_utils.js'); +const patternEngines = require('../src/lib/pattern_engines'); +const config = require('./util/patternlab-config.json'); + +patternEngines.loadAllEngines(config); + +const patterns_dir = `${__dirname}/files/_patterns`; + +tap.test('reading pattern wrap class from markdown', function (test) { + const patternlab = util.fakePatternLab(patterns_dir); + patternlab.config = { + ...patternlab.config, + patternWrapClassesEnable: true, + patternWrapClassesKey: ['theme-class'], + }; + + const patternPathMarkdown = path.join( + 'test', + 'pattern-wrap-class-markdown.mustache' + ); + const patternMarkdown = loadPattern(patternPathMarkdown, patternlab); + patternWrapClassesChangePatternTemplate(patternlab, patternMarkdown); + const patternPartialMarkdown = + '
'; + + test.equal(patternMarkdown.patternPartialCode, patternPartialMarkdown); + test.end(); +}); + +tap.test('reading pattern wrap class from json', function (test) { + const patternlab = util.fakePatternLab(patterns_dir); + patternlab.config = { + ...patternlab.config, + patternWrapClassesEnable: true, + patternWrapClassesKey: ['theme-class'], + }; + + const patternPathJson = path.join('test', 'pattern-wrap-class-json.mustache'); + const patternJson = loadPattern(patternPathJson, patternlab); + patternWrapClassesChangePatternTemplate(patternlab, patternJson); + const patternPartialJson = + '
'; + + test.equal(patternJson.patternPartialCode, patternPartialJson); + test.end(); +}); diff --git a/packages/core/test/pattern_engines_tests.js b/packages/core/test/pattern_engines_tests.js index f79b129dd..3a1e78f1f 100644 --- a/packages/core/test/pattern_engines_tests.js +++ b/packages/core/test/pattern_engines_tests.js @@ -10,15 +10,15 @@ patternEngines.loadAllEngines(config); // the mustache test pattern, stolen from object_factory unit tests var mustacheTestPattern = new Pattern( - 'source/_patterns/00-atoms/00-global/00-colors-alt.mustache', + 'source/_patterns/atoms/global/colors-alt.mustache', { d: 123 } ); var mustacheTestPseudoPatternBasePattern = new Pattern( - 'source/_patterns/04-pages/00-homepage.mustache', + 'source/_patterns/pages/homepage.mustache', { d: 123 } ); var mustacheTestPseudoPattern = new Pattern( - 'source/_patterns/04-pages/00-homepage~emergency.json', + 'source/_patterns/pages/homepage~emergency.json', { d: 123 } ); mustacheTestPseudoPattern.isPseudoPattern = true; @@ -27,20 +27,19 @@ var engineNames = Object.keys(patternEngines); tap.test( 'getEngineNameForPattern returns "mustache" from test pattern', - function(test) { - var engineName = patternEngines.getEngineNameForPattern( - mustacheTestPattern - ); - test.equals(engineName, 'mustache'); + function (test) { + var engineName = + patternEngines.getEngineNameForPattern(mustacheTestPattern); + test.equal(engineName, 'mustache'); test.end(); } ); tap.test( 'getEngineNameForPattern returns "mustache" for a plain string template as a backwards compatibility measure', - function(test) { + function (test) { test.plan(1); - test.equals( + test.equal( patternEngines.getEngineNameForPattern('plain text string'), 'mustache' ); @@ -50,10 +49,10 @@ tap.test( tap.test( 'getEngineNameForPattern returns "mustache" for an artificial empty template', - function(test) { + function (test) { test.plan(1); var emptyPattern = Pattern.createEmpty(); - test.equals( + test.equal( patternEngines.getEngineNameForPattern(emptyPattern), 'mustache' ); @@ -63,40 +62,40 @@ tap.test( tap.test( 'getEngineForPattern returns a reference to the mustache engine from test pattern', - function(test) { + function (test) { var engine = patternEngines.getEngineForPattern(mustacheTestPattern); - test.equals(engine, patternEngines.mustache); + test.equal(engine, patternEngines.mustache); test.end(); } ); tap.test( 'getEngineForPattern returns a reference to the mustache engine from test pseudo-pattern', - function(test) { + function (test) { var engine = patternEngines.getEngineForPattern(mustacheTestPseudoPattern); - test.equals(engine, patternEngines.mustache); + test.equal(engine, patternEngines.mustache); test.end(); } ); tap.test( 'isPseudoPatternJSON correctly identifies pseudo-pattern JSON filenames', - function(test) { + function (test) { // each test case var filenames = { - '00-homepage~emergency.json': true, + 'homepage~emergency.json': true, '~emergency.json': true, - '00-homepage~emergency.js': false, - '00-homepage-emergency.js': false, - '00-homepage.hbs': false, - '00-homepage.json': false, + 'homepage~emergency.js': false, + 'homepage-emergency.js': false, + 'homepage.hbs': false, + 'homepage.json': false, 'greatpic.jpg': false, }; // expect one test per test case test.plan(Object.keys(filenames).length); // loop over each test case and test it - Object.keys(filenames).forEach(function(filename) { + Object.keys(filenames).forEach(function (filename) { var expectedResult = filenames[filename], actualResult = patternEngines.isPseudoPatternJSON(filename), testMessage = @@ -114,22 +113,22 @@ tap.test( tap.test( 'isPatternFile correctly identifies pattern files and rejects non-pattern files', - function(test) { + function (test) { // each test case var filenames = { - '00-comment-thread.mustache': true, - '00-comment-thread.fakeextthatdoesntexist': false, - '00-comment-thread': false, - '_00-comment-thread.mustache': true, - '.00-comment-thread.mustache': false, - '00-comment-thread.json': false, - '00-homepage~emergency.json': true, + 'comment-thread.mustache': true, + 'comment-thread.fakeextthatdoesntexist': false, + 'comment-thread': false, + '_comment-thread.mustache': true, + '.comment-thread.mustache': false, + 'comment-thread.json': false, + 'homepage~emergency.json': true, }; // expect one test per test case test.plan(Object.keys(filenames).length); // loop over each test case and test it - Object.keys(filenames).forEach(function(filename) { + Object.keys(filenames).forEach(function (filename) { var expectedResult = filenames[filename], actualResult = patternEngines.isPatternFile(filename), testMessage = @@ -160,10 +159,10 @@ function testProps(object, propTests, test) { } var isOneOfTheseTypes = possibleTypes - .map(function(type) { + .map(function (type) { return typeof object[propName] === type; }) - .reduce(function(isPrevType, isCurrentType) { + .reduce(function (isPrevType, isCurrentType) { return isPrevType || isCurrentType; }); @@ -183,7 +182,7 @@ function testProps(object, propTests, test) { } // go over each property test and run it - Object.keys(propTests).forEach(function(propName) { + Object.keys(propTests).forEach(function (propName) { var propType = propTests[propName]; testProp(propName, propType); }); @@ -191,7 +190,7 @@ function testProps(object, propTests, test) { tap.test( 'patternEngines object contains at least the default mustache engine', - function(test) { + function (test) { test.plan(1); test.ok(patternEngines.hasOwnProperty('mustache')); test.end(); @@ -200,7 +199,7 @@ tap.test( tap.test( 'patternEngines object reports that it supports the .mustache extension', - function(test) { + function (test) { test.plan(1); test.ok(patternEngines.isFileExtensionSupported('.mustache')); test.end(); @@ -208,10 +207,10 @@ tap.test( ); // make one big test group for each pattern engine -engineNames.forEach(function(engineName) { +engineNames.forEach(function (engineName) { tap.test( 'engine ' + engineName + ' contains expected properties and methods', - function(test) { + function (test) { var propertyTests = { engine: ['object', 'function'], engineName: 'string', @@ -229,7 +228,7 @@ engineNames.forEach(function(engineName) { tap.test( 'patternEngines getSupportedFileExtensions flattens known engine extensions into a single array', - function(test) { + function (test) { //arrange patternEngines.fooEngine = { engineFileExtension: ['.foo1', '.foo2'], diff --git a/packages/core/test/pattern_graph_tests.js b/packages/core/test/pattern_graph_tests.js index a2618031c..4bbff233a 100644 --- a/packages/core/test/pattern_graph_tests.js +++ b/packages/core/test/pattern_graph_tests.js @@ -22,21 +22,21 @@ var patternlab = { }, }; -var mockGraph = function() { +var mockGraph = function () { return PatternGraph.empty(); }; -tap.test('checkVersion - Current version returns true', test => { +tap.test('checkVersion - Current version returns true', (test) => { test.same(PatternGraph.checkVersion({ version: VERSION }), true); test.end(); }); -tap.test('checkVersion - Older version returns false', test => { +tap.test('checkVersion - Older version returns false', (test) => { test.same(PatternGraph.checkVersion({ version: VERSION - 1 }), false); test.end(); }); -tap.test('Loading an empty graph works', test => { +tap.test('Loading an empty graph works', (test) => { var g = PatternGraph.loadFromFile( path.resolve(__dirname, 'public'), 'does not exist' @@ -45,7 +45,7 @@ tap.test('Loading an empty graph works', test => { test.end(); }); -tap.test('PatternGraph.fromJson() - Loading a graph from JSON', test => { +tap.test('PatternGraph.fromJson() - Loading a graph from JSON', (test) => { var graph = PatternGraph.loadFromFile( path.resolve(__dirname, 'public'), 'testDependencyGraph.json' @@ -58,9 +58,9 @@ tap.test('PatternGraph.fromJson() - Loading a graph from JSON', test => { tap.test( 'PatternGraph.fromJson() - Loading a graph from JSON using an older version throws error', - test => { + (test) => { test.throws( - function() { + function () { PatternGraph.fromJson({ version: 0 }); }, {}, @@ -71,7 +71,7 @@ tap.test( } ); -tap.test('toJson() - Storing a graph to JSON correctly', test => { +tap.test('toJson() - Storing a graph to JSON correctly', (test) => { var graph = mockGraph(); graph.timestamp = 1337; var atomFoo = Pattern.create('atom-foo', null, { @@ -101,7 +101,7 @@ tap.test('toJson() - Storing a graph to JSON correctly', test => { tap.test( 'Storing and loading a graph from JSON return the identical graph', - test => { + (test) => { var oldGraph = mockGraph(); oldGraph.timestamp = 1337; var atomFoo = Pattern.create('atom-foo', null, { @@ -128,7 +128,7 @@ tap.test( } ); -tap.test('clone()', test => { +tap.test('clone()', (test) => { var oldGraph = mockGraph(); oldGraph.timestamp = 1337; var atomFoo = Pattern.create('atom-foo', null, { @@ -154,7 +154,7 @@ tap.test('clone()', test => { test.end(); }); -tap.test('Adding a node', test => { +tap.test('Adding a node', (test) => { var g = mockGraph(); var pattern = Pattern.create('atom-foo', null, { compileState: CompileState.CLEAN, @@ -170,7 +170,7 @@ tap.test('Adding a node', test => { test.end(); }); -tap.test('Adding a node twice', test => { +tap.test('Adding a node twice', (test) => { var g = mockGraph(); var pattern = Pattern.create('atom-foo', null, { compileState: CompileState.CLEAN, @@ -182,7 +182,7 @@ tap.test('Adding a node twice', test => { test.end(); }); -tap.test('Adding two nodes', test => { +tap.test('Adding two nodes', (test) => { var g = mockGraph(); var atomFoo = Pattern.create('atom-foo', { compileState: CompileState.CLEAN, @@ -197,25 +197,22 @@ tap.test('Adding two nodes', test => { test.end(); }); -tap.test('Adding two nodes with only different subpattern types', test => { +tap.test('Adding two nodes with only different subpattern types', (test) => { var g = mockGraph(); - var atomFoo = Pattern.create('00-atoms/00-foo/baz.html', { + var atomFoo = Pattern.create('atoms/foo/baz.html', { compileState: CompileState.CLEAN, }); - var moleculeFoo = Pattern.create('00-atoms/00-bar/baz.html', { + var moleculeFoo = Pattern.create('atoms/bar/baz.html', { compileState: CompileState.CLEAN, }); g.add(atomFoo); g.add(moleculeFoo); var actual = g.nodes(); - test.same(posixPath(actual), [ - '00-atoms/00-foo/baz.html', - '00-atoms/00-bar/baz.html', - ]); + test.same(posixPath(actual), ['atoms/foo/baz.html', 'atoms/bar/baz.html']); test.end(); }); -tap.test('Linking two nodes', test => { +tap.test('Linking two nodes', (test) => { var g = mockGraph(); var atomFoo = Pattern.create('atom-foo', null, { compileState: CompileState.CLEAN, @@ -234,7 +231,7 @@ tap.test('Linking two nodes', test => { test.end(); }); -tap.test('remove() - Removing a node', test => { +tap.test('remove() - Removing a node', (test) => { var g = mockGraph(); var atomFoo = Pattern.create('atom-foo', null, { compileState: CompileState.CLEAN, @@ -259,7 +256,7 @@ tap.test('remove() - Removing a node', test => { test.end(); }); -tap.test('filter() - Removing nodes via filter', test => { +tap.test('filter() - Removing nodes via filter', (test) => { var g = mockGraph(); var atomFoo = Pattern.create('atom-foo', null, { compileState: CompileState.CLEAN, @@ -270,7 +267,7 @@ tap.test('filter() - Removing nodes via filter', test => { g.add(atomFoo); g.add(moleculeFoo); test.same(g.nodes(), ['atom-foo', 'molecule-foo']); - g.filter(n => n != 'molecule-foo'); + g.filter((n) => n != 'molecule-foo'); test.same( g.graph.nodes(), ['atom-foo'], @@ -286,23 +283,23 @@ tap.test('filter() - Removing nodes via filter', test => { // Prevents nodes from escaping the scope, at the same time have some default graph for lineage to // test on -(function() { - var atomFoo = Pattern.create('00-atom/xy/foo', null, { +(function () { + var atomFoo = Pattern.create('atom/xy/foo', null, { compileState: CompileState.CLEAN, }); - var atomIsolated = Pattern.create('00-atom/xy/isolated', null, { + var atomIsolated = Pattern.create('atom/xy/isolated', null, { compileState: CompileState.CLEAN, }); - var moleculeFoo = Pattern.create('01-molecule/xy/foo', null, { + var moleculeFoo = Pattern.create('molecule/xy/foo', null, { compileState: CompileState.CLEAN, }); - var moleculeBar = Pattern.create('01-molecule/xy/bar', null, { + var moleculeBar = Pattern.create('molecule/xy/bar', null, { compileState: CompileState.CLEAN, }); - var organismFoo = Pattern.create('02-organism/xy/foo', null, { + var organismFoo = Pattern.create('organism/xy/foo', null, { compileState: CompileState.CLEAN, }); - var organismBar = Pattern.create('02-organism/xy/bar', null, { + var organismBar = Pattern.create('organism/xy/bar', null, { compileState: CompileState.CLEAN, }); @@ -327,26 +324,32 @@ tap.test('filter() - Removing nodes via filter', test => { g.link(moleculeFoo, atomFoo); g.link(moleculeBar, atomFoo); - tap.test('lineage() - Calculate the lineage of a node', test => { - test.same(posixPath(g.lineage(organismFoo).map(p => p.relPath)), [ - '01-molecule/xy/foo', + tap.test('lineage() - Calculate the lineage of a node', (test) => { + test.same(posixPath(g.lineage(organismFoo).map((p) => p.relPath)), [ + 'molecule/xy/foo', ]); - test.same(posixPath(g.lineage(organismBar).map(p => p.relPath)), [ - '01-molecule/xy/foo', - '01-molecule/xy/bar', + test.same(posixPath(g.lineage(organismBar).map((p) => p.relPath)), [ + 'molecule/xy/foo', + 'molecule/xy/bar', ]); - test.same(posixPath(g.lineage(moleculeFoo).map(p => p.relPath)), [ - '00-atom/xy/foo', + test.same(posixPath(g.lineage(moleculeFoo).map((p) => p.relPath)), [ + 'atom/xy/foo', ]); - test.same(posixPath(g.lineage(moleculeBar).map(p => p.relPath)), [ - '00-atom/xy/foo', + test.same(posixPath(g.lineage(moleculeBar).map((p) => p.relPath)), [ + 'atom/xy/foo', ]); - test.same(g.lineage(atomFoo).map(p => p.relPath), []); - test.same(g.lineage(atomIsolated).map(p => p.relPath), []); + test.same( + g.lineage(atomFoo).map((p) => p.relPath), + [] + ); + test.same( + g.lineage(atomIsolated).map((p) => p.relPath), + [] + ); test.end(); }); - tap.test('lineageIndex() - Calculate the lineage of a node', test => { + tap.test('lineageIndex() - Calculate the lineage of a node', (test) => { test.same(g.lineageIndex(organismFoo), ['molecule-foo']); test.same(g.lineageIndex(organismBar), ['molecule-foo', 'molecule-bar']); test.same(g.lineageIndex(moleculeFoo), ['atom-foo']); @@ -356,68 +359,80 @@ tap.test('filter() - Removing nodes via filter', test => { test.end(); }); - tap.test('lineageR() - Calculate the reverse lineage of a node', test => { - test.same(g.lineageR(organismFoo).map(p => p.relPath), []); - test.same(g.lineageR(organismBar).map(p => p.relPath), []); - test.same(posixPath(g.lineageR(moleculeFoo).map(p => p.relPath)), [ - '02-organism/xy/foo', - '02-organism/xy/bar', + tap.test('lineageR() - Calculate the reverse lineage of a node', (test) => { + test.same( + g.lineageR(organismFoo).map((p) => p.relPath), + [] + ); + test.same( + g.lineageR(organismBar).map((p) => p.relPath), + [] + ); + test.same(posixPath(g.lineageR(moleculeFoo).map((p) => p.relPath)), [ + 'organism/xy/foo', + 'organism/xy/bar', ]); - test.same(posixPath(g.lineageR(moleculeBar).map(p => p.relPath)), [ - '02-organism/xy/bar', + test.same(posixPath(g.lineageR(moleculeBar).map((p) => p.relPath)), [ + 'organism/xy/bar', ]); - test.same(posixPath(g.lineageR(atomFoo).map(p => p.relPath)), [ - '01-molecule/xy/foo', - '01-molecule/xy/bar', + test.same(posixPath(g.lineageR(atomFoo).map((p) => p.relPath)), [ + 'molecule/xy/foo', + 'molecule/xy/bar', ]); - test.same(g.lineageR(atomIsolated).map(p => p.relPath), []); + test.same( + g.lineageR(atomIsolated).map((p) => p.relPath), + [] + ); test.end(); }); - tap.test('lineageRIndex() - Calculate the lineage index of a node', test => { - test.same(g.lineageRIndex(organismFoo), []); - test.same(g.lineageRIndex(organismBar), []); - test.same(g.lineageRIndex(moleculeFoo), ['organism-foo', 'organism-bar']); - test.same(g.lineageRIndex(moleculeBar), ['organism-bar']); - test.same(g.lineageRIndex(atomFoo), ['molecule-foo', 'molecule-bar']); - test.same(g.lineageRIndex(atomIsolated), []); - test.end(); - }); + tap.test( + 'lineageRIndex() - Calculate the lineage index of a node', + (test) => { + test.same(g.lineageRIndex(organismFoo), []); + test.same(g.lineageRIndex(organismBar), []); + test.same(g.lineageRIndex(moleculeFoo), ['organism-foo', 'organism-bar']); + test.same(g.lineageRIndex(moleculeBar), ['organism-bar']); + test.same(g.lineageRIndex(atomFoo), ['molecule-foo', 'molecule-bar']); + test.same(g.lineageRIndex(atomIsolated), []); + test.end(); + } + ); })(); -(function() { +(function () { function TestGraph() { function csAt(args, idx) { return { compileState: args[idx] || CompileState.CLEAN }; } var i = 0; var atomFoo = (this.atomFoo = Pattern.create( - '00-atom/xy/foo', + 'atom/xy/foo', null, csAt(arguments, i++) )); var atomIsolated = (this.atomIsolated = Pattern.create( - '00-atom/xy/isolated', + 'atom/xy/isolated', null, csAt(arguments, i++) )); var moleculeFoo = (this.moleculeFoo = Pattern.create( - '01-molecule/xy/foo', + 'molecule/xy/foo', null, csAt(arguments, i++) )); var moleculeBar = (this.moleculeBar = Pattern.create( - '01-molecule/xy/bar', + 'molecule/xy/bar', null, csAt(arguments, i++) )); var organismFoo = (this.organismFoo = Pattern.create( - '02-organism/xy/foo', + 'organism/xy/foo', null, csAt(arguments, i++) )); var organismBar = (this.organismBar = Pattern.create( - '02-organism/xy/bar', + 'organism/xy/bar', null, csAt(arguments, i++) )); @@ -446,17 +461,17 @@ tap.test('filter() - Removing nodes via filter', test => { tap.test( 'compileOrder() - A clean graph results in no nodes to recompile', - test => { + (test) => { var g = new TestGraph(); var co = g.graph.compileOrder(); - test.equals(0, co.length); + test.equal(0, co.length); test.end(); } ); tap.test( 'compileOrder() - Recompile isolated atoms does not do anything else', - test => { + (test) => { var g = new TestGraph( // atomFoo CompileState.CLEAN, @@ -466,7 +481,7 @@ tap.test('filter() - Removing nodes via filter', test => { var co = g.graph.compileOrder(); test.same([g.atomIsolated], co, 'Only recompile atomIsolated'); - co.forEach(p => + co.forEach((p) => test.same( p.compileState, CompileState.NEEDS_REBUILD, @@ -480,18 +495,18 @@ tap.test('filter() - Removing nodes via filter', test => { tap.test( 'compileOrder() - Changing a linked atom bubbles back to the organisms', - test => { + (test) => { // Almost every pattern - except atomIsolated - has a transitive dependency on atomFoo var g = new TestGraph(CompileState.NEEDS_REBUILD); var co = g.graph.compileOrder(); - test.equals(5, co.length); + test.equal(5, co.length); test.same( [g.atomFoo, g.moleculeFoo, g.organismFoo, g.moleculeBar, g.organismBar], co, 'Recompile everything except atomIsolated' ); - co.forEach(p => + co.forEach((p) => test.same( p.compileState, CompileState.NEEDS_REBUILD, @@ -505,7 +520,7 @@ tap.test('filter() - Removing nodes via filter', test => { tap.test( 'compileOrder() - Changing a molecule leaves atoms untouched', - test => { + (test) => { // Bubble up from molecules to organisms, leaving atoms unchanged as they were not modified var g = new TestGraph(null, null, CompileState.NEEDS_REBUILD); var co = g.graph.compileOrder(); @@ -515,7 +530,7 @@ tap.test('filter() - Removing nodes via filter', test => { co, 'Recompile moleculeFoo and transitive dependencies' ); - co.forEach(p => + co.forEach((p) => test.same( p.compileState, CompileState.NEEDS_REBUILD, @@ -528,7 +543,7 @@ tap.test('filter() - Removing nodes via filter', test => { tap.test( 'compileOrder() - Changing an organism leaves atoms and molecules untouched', - test => { + (test) => { // Almost every pattern - except atomIsolated - has a transitive dependency on atomFoo var g = new TestGraph( // atoms @@ -552,7 +567,7 @@ tap.test('filter() - Removing nodes via filter', test => { } ); - tap.test('compileOrder() - Recompile everything', test => { + tap.test('compileOrder() - Recompile everything', (test) => { // Almost every pattern - except atomIsolated - has a transitive dependency on atomFoo // Also recompile atomIsolated var g = new TestGraph( @@ -573,7 +588,7 @@ tap.test('filter() - Removing nodes via filter', test => { compileOrder, 'Recompile everything except atomIsolated' ); - compileOrder.forEach(p => + compileOrder.forEach((p) => test.same( p.compileState, CompileState.NEEDS_REBUILD, diff --git a/packages/core/test/pattern_registry_tests.js b/packages/core/test/pattern_registry_tests.js index bf2e71914..72eef2c4f 100644 --- a/packages/core/test/pattern_registry_tests.js +++ b/packages/core/test/pattern_registry_tests.js @@ -7,7 +7,7 @@ var tap = require('tap'); // #540 Copied from pattern_assembler_tests tap.test( 'get_pattern_by_key - returns the fuzzy result when no others found', - function(test) { + function (test) { var pattern_registry = new PatternRegistry(); var pattern = { @@ -21,13 +21,13 @@ tap.test( //act var result = pattern_registry.getPartial('character-han'); //assert - test.equals(result, pattern); + test.equal(result, pattern); test.end(); } ); // #540 Copied from pattern_assembler_tests -tap.test('remove - remove an existing pattern', function(test) { +tap.test('remove - remove an existing pattern', function (test) { var pattern_registry = new PatternRegistry(); var pattern = { @@ -45,7 +45,7 @@ tap.test('remove - remove an existing pattern', function(test) { }); // #540 Copied from pattern_assembler_tests -tap.test('getPartial - returns the exact key if found', function(test) { +tap.test('getPartial - returns the exact key if found', function (test) { //arrange var pattern_registry = new PatternRegistry(); let patterns = [ @@ -62,11 +62,11 @@ tap.test('getPartial - returns the exact key if found', function(test) { fileName: 'molecules-primary-nav', }, ]; - patterns.forEach(p => pattern_registry.put(p)); + patterns.forEach((p) => pattern_registry.put(p)); //act var result = pattern_registry.getPartial('molecules-primary-nav'); //assert - test.equals(result, patterns[1]); + test.equal(result, patterns[1]); test.end(); }); diff --git a/packages/core/test/patternlab_tests.js b/packages/core/test/patternlab_tests.js index 741fbca15..b2971bec6 100644 --- a/packages/core/test/patternlab_tests.js +++ b/packages/core/test/patternlab_tests.js @@ -9,16 +9,16 @@ var plEngineModule = rewire('../src/lib/patternlab'); //set up a global mocks - we don't want to be writing/rendering any files right now const fsMock = { - outputFileSync: function(path, content) { + outputFileSync: function (path, content) { /* INTENTIONAL NOOP */ }, - readJSONSync: function(path, encoding) { + readJSONSync: function (path, encoding) { return fs.readJSONSync(path, encoding); }, - emptyDir: function(path) { + emptyDir: function (path) { return fs.emptyDir(path); }, - readFileSync: function(path, encoding) { + readFileSync: function (path, encoding) { return fs.readFileSync(path, encoding); }, }; @@ -30,27 +30,28 @@ plEngineModule.__set__({ tap.test( 'buildPatternData - should merge all JSON files in the data folder except listitems', - function(test) { + function (test) { const data_dir = `${__dirname}/files/_data/`; var pl = new plEngineModule(config); var dataResult = pl.buildPatternData(data_dir, fs); - test.equals(dataResult.data, 'test'); - test.equals(dataResult.foo, 'bar'); - test.equals(dataResult.test_list_item, undefined); + test.equal(dataResult.data, 'test'); + test.equal(dataResult.foo, 'bar'); + test.equal(dataResult.test_list_item, undefined); test.end(); } ); -tap.test('buildPatternData - can load json, yaml, and yml files', function( - test -) { - const data_dir = `${__dirname}/files/_data/`; - - var pl = new plEngineModule(config); - var dataResult = pl.buildPatternData(data_dir, fs); - test.equals(dataResult.from_yml, 'from_yml'); - test.equals(dataResult.from_yaml, 'from_yaml'); - test.equals(dataResult.from_json, 'from_json'); - test.end(); -}); +tap.test( + 'buildPatternData - can load json, yaml, and yml files', + function (test) { + const data_dir = `${__dirname}/files/_data/`; + + var pl = new plEngineModule(config); + var dataResult = pl.buildPatternData(data_dir, fs); + test.equal(dataResult.from_yml, 'from_yml'); + test.equal(dataResult.from_yaml, 'from_yaml'); + test.equal(dataResult.from_json, 'from_json'); + test.end(); + } +); diff --git a/packages/core/test/processRecursive_tests.js b/packages/core/test/processRecursive_tests.js index 8522c0403..e9ae0c4d8 100644 --- a/packages/core/test/processRecursive_tests.js +++ b/packages/core/test/processRecursive_tests.js @@ -16,14 +16,14 @@ engineLoader.loadAllEngines(config); const patterns_dir = `${__dirname}/files/_patterns`; -tap.test('processRecursive recursively includes partials', function(test) { +tap.test('processRecursive recursively includes partials', function (test) { //assert const patternlab = util.fakePatternLab(patterns_dir); - var fooPatternPath = path.join('00-test', '00-foo.mustache'); + var fooPatternPath = path.join('test', 'foo.mustache'); var fooPattern = loadPattern(fooPatternPath, patternlab); - var barPatternPath = path.join('00-test', '01-bar.mustache'); + var barPatternPath = path.join('test', 'bar.mustache'); var barPattern = loadPattern(barPatternPath, patternlab); var p1 = processIterative(fooPattern, patternlab); @@ -36,7 +36,7 @@ tap.test('processRecursive recursively includes partials', function(test) { .then(() => { //assert const expectedValue = 'bar'; - test.equals( + test.equal( util.sanitized(fooPattern.extendedTemplate), util.sanitized(expectedValue) ); @@ -47,284 +47,18 @@ tap.test('processRecursive recursively includes partials', function(test) { .catch(test.threw); }); -tap.test( - 'processRecursive - correctly replaces all stylemodifiers when multiple duplicate patterns with different stylemodifiers found', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var groupPath = path.join('00-test', '04-group.mustache'); - var groupPattern = loadPattern(groupPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(groupPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(groupPath, patternlab) - .then(() => { - //assert - const expectedValue = - '
{{message}} {{message}} {{message}} {{message}}
'; - test.equals( - util.sanitized(groupPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.only( - 'processRecursive - correctly replaces multiple stylemodifier classes on same partial', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var groupPath = path.join( - '00-test', - '10-multiple-classes-numeric.mustache' - ); - var groupPattern = loadPattern(groupPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(groupPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(groupPath, patternlab) - .then(() => { - //assert - const expectedValue = - '
{{message}} {{message}} bar
'; - test.equals( - util.sanitized(groupPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.test( - 'processRecursive - correctly ignores a partial without a style modifier when the same partial later has a style modifier', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var mixedPath = path.join('00-test', '06-mixed.mustache'); - var mixedPattern = loadPattern(mixedPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(mixedPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(mixedPath, patternlab) - .then(() => { - //assert. here we expect {{styleModifier}} to be in the first group, since it was not replaced by anything. rendering with data will then remove this (correctly) - const expectedValue = - '
{{message}} {{message}} {{message}} {{message}}
'; - test.equals( - util.sanitized(mixedPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.test( - 'processRecursive - correctly ignores bookended partials without a style modifier when the same partial has a style modifier between', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var bookendPath = path.join('00-test', '09-bookend.mustache'); - var bookendPattern = loadPattern(bookendPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(bookendPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(bookendPath, patternlab) - .then(() => { - //assert. here we expect {{styleModifier}} to be in the first and last group, since it was not replaced by anything. rendering with data will then remove this (correctly) - const expectedValue = - '
{{message}} {{message}} {{message}} {{message}}
'; - test.equals( - util.sanitized(bookendPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.test( - 'processRecursive - correctly ignores a partial without a style modifier when the same partial later has a style modifier and pattern parameters', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var mixedPath = path.join('00-test', '07-mixed-params.mustache'); - var mixedPattern = loadPattern(mixedPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(mixedPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(mixedPath, patternlab) - .then(() => { - //assert. here we expect {{styleModifier}} to be in the first span, since it was not replaced by anything. rendering with data will then remove this (correctly) - const expectedValue = - '
{{message}} 2 3 4
'; - test.equals( - util.sanitized(mixedPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.test( - 'processRecursive - correctly ignores bookended partials without a style modifier when the same partial has a style modifier and pattern parameters between', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var bookendPath = path.join('00-test', '08-bookend-params.mustache'); - var bookendPattern = loadPattern(bookendPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(bookendPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(bookendPath, patternlab) - .then(() => { - //assert. here we expect {{styleModifier}} to be in the first and last span, since it was not replaced by anything. rendering with data will then remove this (correctly) - const expectedValue = - '
{{message}} 2 3 {{message}}
'; - test.equals( - util.sanitized(bookendPattern.extendedTemplate), - util.sanitized(expectedValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - -tap.test( - 'processRecursive - does not pollute previous patterns when a later one is found with a styleModifier', - function(test) { - //arrange - const patternlab = util.fakePatternLab(patterns_dir); - - var atomPath = path.join('00-test', '03-styled-atom.mustache'); - var atomPattern = loadPattern(atomPath, patternlab); - - var anotherPath = path.join('00-test', '12-another-styled-atom.mustache'); - var anotherPattern = loadPattern(anotherPath, patternlab); - - var p1 = processIterative(atomPattern, patternlab); - var p2 = processIterative(anotherPattern, patternlab); - - Promise.all([p1, p2]) - .then(() => { - //act - processRecursive(anotherPath, patternlab) - .then(() => { - //assert - const expectedCleanValue = - ' {{message}} '; - const expectedSetValue = - ' {{message}} '; - - //this is the "atom" - it should remain unchanged - test.equals( - util.sanitized(atomPattern.template), - util.sanitized(expectedCleanValue) - ); - test.equals( - util.sanitized(atomPattern.extendedTemplate), - util.sanitized(expectedCleanValue) - ); - - // this is the style modifier pattern, which should resolve correctly - test.equals( - util.sanitized(anotherPattern.template), - '{{> test-styled-atom:test_1 }}' - ); - test.equals( - util.sanitized(anotherPattern.extendedTemplate), - util.sanitized(expectedSetValue) - ); - test.end(); - }) - .catch(test.threw); - }) - .catch(test.threw); - } -); - tap - .test('processRecursive - ensure deep-nesting works', function(test) { + .test('processRecursive - ensure deep-nesting works', function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); - var atomPath = path.join('00-test', '01-bar.mustache'); + var atomPath = path.join('test', 'bar.mustache'); var atomPattern = loadPattern(atomPath, patternlab); - var templatePath = path.join('00-test', '00-foo.mustache'); + var templatePath = path.join('test', 'foo.mustache'); var templatePattern = loadPattern(templatePath, patternlab); - var pagesPath = path.join('00-test', '14-inception.mustache'); + var pagesPath = path.join('test', 'inception.mustache'); var pagesPattern = loadPattern(pagesPath, patternlab); var p1 = processIterative(atomPattern, patternlab); @@ -342,31 +76,28 @@ tap //act return test.test( 'processRecursive - ensure deep-nesting works2', - function(tt) { + function (tt) { //assert const expectedCleanValue = 'bar'; const expectedSetValue = 'bar'; //this is the "atom" - it should remain unchanged - tt.equals(util.sanitized(atomPattern.template), expectedCleanValue); - tt.equals( + tt.equal(util.sanitized(atomPattern.template), expectedCleanValue); + tt.equal( util.sanitized(atomPattern.extendedTemplate), expectedCleanValue ); //this is the "template pattern" - it should have an updated extendedTemplate but an unchanged template - tt.equals( - util.sanitized(templatePattern.template), - '{{> test-bar }}' - ); - tt.equals( + tt.equal(util.sanitized(templatePattern.template), '{{> test-bar }}'); + tt.equal( util.sanitized(templatePattern.extendedTemplate), expectedSetValue ); //this is the "pages pattern" - it should have an updated extendedTemplate equal to the template pattern but an unchanged template - tt.equals(util.sanitized(pagesPattern.template), '{{> test-foo }}'); - tt.equals( + tt.equal(util.sanitized(pagesPattern.template), '{{> test-foo }}'); + tt.equal( util.sanitized(pagesPattern.extendedTemplate), expectedSetValue ); @@ -378,18 +109,15 @@ tap }) .catch(tap.threw); -tap.test('hidden patterns can be called by their nice names', function(test) { +tap.test('hidden patterns can be called by their nice names', function (test) { //arrange const patternlab = util.fakePatternLab(patterns_dir); //act - var hiddenPatternPath = path.join('00-test', '_00-hidden-pattern.mustache'); + var hiddenPatternPath = path.join('test', '_hidden-pattern.mustache'); var hiddenPattern = loadPattern(hiddenPatternPath, patternlab); - var testPatternPath = path.join( - '00-test', - '15-hidden-pattern-tester.mustache' - ); + var testPatternPath = path.join('test', 'hidden-pattern-tester.mustache'); var testPattern = loadPattern(testPatternPath, patternlab); var p1 = processIterative(hiddenPattern, patternlab); @@ -399,9 +127,9 @@ tap.test('hidden patterns can be called by their nice names', function(test) { //act processRecursive(hiddenPatternPath, patternlab).then(() => { processRecursive(testPatternPath, patternlab).then(() => { - testPattern.render().then(results => { + testPattern.render().then((results) => { //assert - test.equals( + test.equal( util.sanitized(results), util.sanitized( "Hello there! Here's the hidden atom: [This is the hidden atom]" @@ -415,39 +143,40 @@ tap.test('hidden patterns can be called by their nice names', function(test) { }); }); -tap.test('parses pattern title correctly when frontmatter present', function( - test -) { - //arrange - var pl = util.fakePatternLab(patterns_dir); +tap.test( + 'parses pattern title correctly when frontmatter present', + function (test) { + //arrange + var pl = util.fakePatternLab(patterns_dir); - var testPatternPath = path.join('00-test', '01-bar.mustache'); - var testPattern = loadPattern(testPatternPath, pl); + var testPatternPath = path.join('test', 'bar.mustache'); + var testPattern = loadPattern(testPatternPath, pl); - //act - Promise.all([ - processIterative(testPattern, pl), - processRecursive(testPatternPath, pl), - ]) - .then(results => { - //assert - test.equals( - results[0].patternName, - 'An Atom Walks Into a Bar', - 'patternName not overridden' - ); - test.end(); - }) - .catch(test.threw); -}); + //act + Promise.all([ + processIterative(testPattern, pl), + processRecursive(testPatternPath, pl), + ]) + .then((results) => { + //assert + test.equal( + results[0].patternName, + 'An Atom Walks Into a Bar', + 'patternName not overridden' + ); + test.end(); + }) + .catch(test.threw); + } +); tap.test( 'parses pattern extra frontmatter correctly when frontmatter present', - function(test) { + function (test) { //arrange var pl = util.fakePatternLab(patterns_dir); - var testPatternPath = path.join('00-test', '01-bar.mustache'); + var testPatternPath = path.join('test', 'bar.mustache'); var testPattern = loadPattern(testPatternPath, pl); //act @@ -455,9 +184,9 @@ tap.test( processIterative(testPattern, pl), processRecursive(testPatternPath, pl), ]) - .then(results => { + .then((results) => { //assert - test.equals(results[0].allMarkdown.joke, 'bad', 'extra key not added'); + test.equal(results[0].allMarkdown.joke, 'bad', 'extra key not added'); test.end(); }) .catch(test.threw); diff --git a/packages/core/test/pseudopattern_hunter_tests.js b/packages/core/test/pseudopattern_hunter_tests.js index 1464f28b4..1f9c5e541 100644 --- a/packages/core/test/pseudopattern_hunter_tests.js +++ b/packages/core/test/pseudopattern_hunter_tests.js @@ -42,94 +42,145 @@ function stubPatternlab() { return pl; } -tap.test('pseudpattern found and added as a pattern', function(test) { +tap.test('pseudpattern found and added as a pattern', function (test) { //arrange var pl = stubPatternlab(); - var atomPattern = loadPattern('00-test/03-styled-atom.mustache', pl); + var atomPattern = loadPattern('test/styled-atom.mustache', pl); addPattern(atomPattern, pl); //act var patternCountBefore = pl.patterns.length; return pph.find_pseudopatterns(atomPattern, pl).then(() => { //assert - test.equals(patternCountBefore + 1, pl.patterns.length); - test.equals(pl.patterns[1].patternPartial, 'test-styled-atom-alt'); - test.equals( + test.equal(patternCountBefore + 1, pl.patterns.length); + test.equal(pl.patterns[1].patternPartial, 'test-styled-atom-alt'); + test.equal( JSON.stringify(pl.patterns[1].jsonFileData), JSON.stringify({ message: 'alternateMessage' }) ); - test.equals( + test.equal( pl.patterns[1].patternLink, - '00-test-03-styled-atom-alt' + - path.sep + - '00-test-03-styled-atom-alt.html' + 'test-styled-atom-alt' + path.sep + 'test-styled-atom-alt.html' ); }); }); -tap.test('pseudpattern does not pollute base pattern data', function(test) { +tap.test('pseudpattern does not pollute base pattern data', function (test) { //arrange var pl = stubPatternlab(); - var atomPattern = loadPattern('00-test/03-styled-atom.mustache', pl); + var atomPattern = loadPattern('test/styled-atom.mustache', pl); //act var patternCountBefore = pl.patterns.length; return pph.find_pseudopatterns(atomPattern, pl).then(() => { //assert - test.equals(pl.patterns[0].patternPartial, 'test-styled-atom'); - test.equals( + test.equal(pl.patterns[0].patternPartial, 'test-styled-atom'); + test.equal( JSON.stringify(pl.patterns[0].jsonFileData), JSON.stringify({ message: 'baseMessage' }) ); }); }); -tap.test( - 'pseudpattern variant includes stylePartials and parameteredPartials', - function(test) { - //arrange - var pl = stubPatternlab(); - - var atomPattern = new Pattern('00-test/03-styled-atom.mustache'); - atomPattern.template = fs.readFileSync( - patterns_dir + '00-test/03-styled-atom.mustache', - 'utf8' - ); - atomPattern.extendedTemplate = atomPattern.template; - atomPattern.stylePartials = atomPattern.findPartialsWithStyleModifiers( - atomPattern - ); - atomPattern.parameteredPartials = atomPattern.findPartialsWithPatternParameters( - atomPattern - ); +tap.test('pseudpattern variant includes parameteredPartials', function (test) { + //arrange + var pl = stubPatternlab(); - var pseudoPattern = new Pattern('00-test/474-pseudomodifier.mustache'); - pseudoPattern.template = fs.readFileSync( - patterns_dir + '00-test/474-pseudomodifier.mustache', - 'utf8' - ); - pseudoPattern.extendedTemplate = atomPattern.template; - pseudoPattern.stylePartials = pseudoPattern.findPartialsWithStyleModifiers( - pseudoPattern + var atomPattern = new Pattern('test/styled-atom.mustache'); + atomPattern.template = fs.readFileSync( + patterns_dir + 'test/styled-atom.mustache', + 'utf8' + ); + atomPattern.extendedTemplate = atomPattern.template; + atomPattern.parameteredPartials = + atomPattern.findPartialsWithPatternParameters(atomPattern); + + var pseudoPattern = new Pattern('test/pseudomodifier.mustache'); + pseudoPattern.template = fs.readFileSync( + patterns_dir + 'test/pseudomodifier.mustache', + 'utf8' + ); + pseudoPattern.extendedTemplate = atomPattern.template; + pseudoPattern.parameteredPartials = + pseudoPattern.findPartialsWithPatternParameters(pseudoPattern); + + addPattern(atomPattern, pl); + addPattern(pseudoPattern, pl); + + //act + return pph.find_pseudopatterns(pseudoPattern, pl).then(() => { + //assert + test.equal(pl.patterns[2].patternPartial, 'test-pseudomodifier-test'); + test.equal( + pl.patterns[2].parameteredPartials, + pseudoPattern.parameteredPartials ); - pseudoPattern.parameteredPartials = pseudoPattern.findPartialsWithPatternParameters( - pseudoPattern + }); +}); + +tap.test('pseudo pattern variant data should merge arrays', function (test) { + const pl = stubPatternlab(); + pl.config.patternMergeVariantArrays = true; + + const pattern = loadPattern('test/variant-test.mustache', pl); + + addPattern(pattern, pl); + + return pph.find_pseudopatterns(pattern, pl).then(() => { + test.equal(pl.patterns[1].patternPartial, 'test-variant-test-merge'); + test.equal( + JSON.stringify(pl.patterns[1].jsonFileData), + JSON.stringify({ + a: 2, + b: [8, 3], + c: { d: [6, 7], e: 8, f: { a: ['a'], b: ['x'], c: ['c'] } }, + }) ); + }); +}); - addPattern(atomPattern, pl); - addPattern(pseudoPattern, pl); - - //act - return pph.find_pseudopatterns(pseudoPattern, pl).then(() => { - //assert - test.equals(pl.patterns[2].patternPartial, 'test-pseudomodifier-test'); - test.equals(pl.patterns[2].stylePartials, pseudoPattern.stylePartials); - test.equals( - pl.patterns[2].parameteredPartials, - pseudoPattern.parameteredPartials +tap.test( + 'pseudo pattern variant data should merge arrays if config "patternMergeVariantArrays" is not available as default behavior', + function (test) { + const pl = stubPatternlab(); + + const pattern = loadPattern('test/variant-test.mustache', pl); + + addPattern(pattern, pl); + + return pph.find_pseudopatterns(pattern, pl).then(() => { + test.equal(pl.patterns[1].patternPartial, 'test-variant-test-merge'); + test.equal( + JSON.stringify(pl.patterns[1].jsonFileData), + JSON.stringify({ + a: 2, + b: [8, 3], + c: { d: [6, 7], e: 8, f: { a: ['a'], b: ['x'], c: ['c'] } }, + }) ); }); } ); + +tap.test('pseudo pattern variant data should override arrays', function (test) { + const pl = stubPatternlab(); + pl.config.patternMergeVariantArrays = false; + + const pattern = loadPattern('test/variant-test.mustache', pl); + + addPattern(pattern, pl); + + return pph.find_pseudopatterns(pattern, pl).then(() => { + test.equal(pl.patterns[1].patternPartial, 'test-variant-test-merge'); + test.equal( + JSON.stringify(pl.patterns[1].jsonFileData), + JSON.stringify({ + a: 2, + b: [8], + c: { d: [6, 7], e: 8, f: { a: ['a'], b: ['x'], c: ['c'] } }, + }) + ); + }); +}); diff --git a/packages/core/test/replaceParameter_tests.js b/packages/core/test/replaceParameter_tests.js index 41fde31c1..c3dfc129f 100644 --- a/packages/core/test/replaceParameter_tests.js +++ b/packages/core/test/replaceParameter_tests.js @@ -6,44 +6,44 @@ const tap = require('tap'); const replaceParameter = require('../src/lib/replaceParameter'); -tap.test('replaces simple value', function(test) { +tap.test('replaces simple value', function (test) { const result = replaceParameter('{{key}}', 'key', 'value'); - test.equals(result, 'value'); + test.equal(result, 'value'); test.end(); }); -tap.test('replaces simple boolean true value', function(test) { +tap.test('replaces simple boolean true value', function (test) { const result = replaceParameter('{{key}}', 'key', true); - test.equals(result, 'true'); + test.equal(result, 'true'); test.end(); }); -tap.test('replaces simple boolean false value', function(test) { +tap.test('replaces simple boolean false value', function (test) { const result = replaceParameter('{{key}}', 'key', false); - test.equals(result, 'false'); + test.equal(result, 'false'); test.end(); }); -tap.test('replaces raw value', function(test) { +tap.test('replaces raw value', function (test) { const result = replaceParameter('{{{key}}}', 'key', 'value'); - test.equals(result, 'value'); + test.equal(result, 'value'); test.end(); }); -tap.test('replaces boolean true section', function(test) { +tap.test('replaces boolean true section', function (test) { const result = replaceParameter('1{{#key}}value{{/key}}2', 'key', true); - test.equals(result, '1value2'); + test.equal(result, '1value2'); test.end(); }); -tap.only('replaces boolean true section with spaces', function(test) { +tap.only('replaces boolean true section with spaces', function (test) { const result = replaceParameter('1{{ #key }}value{{ /key }}2', 'key', true); - test.equals(result, '1value2'); + test.equal(result, '1value2'); test.end(); }); -tap.test('replaces boolean section false', function(test) { +tap.test('replaces boolean section false', function (test) { const result = replaceParameter('1{{#key}}value{{/key}}2', 'key', false); - test.equals(result, '12'); + test.equal(result, '12'); test.end(); }); diff --git a/packages/core/test/style_modifier_hunter_tests.js b/packages/core/test/style_modifier_hunter_tests.js deleted file mode 100644 index bdbc1e994..000000000 --- a/packages/core/test/style_modifier_hunter_tests.js +++ /dev/null @@ -1,110 +0,0 @@ -'use strict'; - -var tap = require('tap'); - -var smh = require('../src/lib/style_modifier_hunter'); - -tap.test( - 'uses the partial stylemodifer to modify the patterns extendedTemplate', - function(test) { - //arrange - var pl = {}; - pl.partials = {}; - pl.config = {}; - pl.config.logLevel = 'quiet'; - - var pattern = { - extendedTemplate: '
', - }; - - var style_modifier_hunter = new smh(); - - //act - style_modifier_hunter.consume_style_modifier( - pattern, - '{{> partial:bar}}', - pl - ); - - //assert - test.equals(pattern.extendedTemplate, '
'); - test.end(); - } -); - -tap.test('replaces style modifiers with spaces in the syntax', function(test) { - //arrange - var pl = {}; - pl.partials = {}; - pl.config = {}; - pl.config.logLevel = 'quiet'; - - var pattern = { - extendedTemplate: '
', - }; - - var style_modifier_hunter = new smh(); - - //act - style_modifier_hunter.consume_style_modifier( - pattern, - '{{> partial:bar}}', - pl - ); - - //assert - test.equals(pattern.extendedTemplate, '
'); - test.end(); -}); - -tap.test('replaces multiple style modifiers', function(test) { - //arrange - var pl = {}; - pl.partials = {}; - pl.config = {}; - pl.config.logLevel = 'quiet'; - - var pattern = { - extendedTemplate: '
', - }; - - var style_modifier_hunter = new smh(); - - //act - style_modifier_hunter.consume_style_modifier( - pattern, - '{{> partial:bar|baz|dum}}', - pl - ); - - //assert - test.equals(pattern.extendedTemplate, '
'); - test.end(); -}); - -tap.test( - 'does not alter pattern extendedTemplate if styleModifier not found in partial', - function(test) { - //arrange - var pl = {}; - pl.partials = {}; - pl.config = {}; - pl.config.logLevel = 'quiet'; - - var pattern = { - extendedTemplate: '
', - }; - - var style_modifier_hunter = new smh(); - - //act - style_modifier_hunter.consume_style_modifier(pattern, '{{> partial}}', pl); - - //assert - test.equals( - pattern.extendedTemplate, - '
' - ); - test.end(); - } -); diff --git a/packages/core/test/ui_builder_tests.js b/packages/core/test/ui_builder_tests.js index 607d9fd95..1070151d6 100644 --- a/packages/core/test/ui_builder_tests.js +++ b/packages/core/test/ui_builder_tests.js @@ -15,14 +15,14 @@ engineLoader.loadAllEngines(config); //set up a global mocks - we don't want to be writing/rendering any files right now var fsMock = { - outputFileSync: function(path, data, cb) {}, - outputFile: function(path, data, cb) {}, + outputFileSync: function (path, data, cb) {}, + outputFile: function (path, data, cb) {}, }; -var renderMock = function(template, data, partials) { +var renderMock = function (template, data, partials) { return Promise.resolve(''); }; -var buildFooterMock = function(patternlab, patternPartial) { +var buildFooterMock = function (patternlab, patternPartial) { return Promise.resolve(''); }; @@ -69,48 +69,49 @@ function createFakePatternLab(customProps) { tap.test( 'isPatternExcluded - returns true when pattern filename starts with underscore', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({}); - var pattern = new Pattern('00-test/_ignored-pattern.mustache'); + var pattern = new Pattern('test/ignored-pattern.mustache'); + pattern.hidden = true; //act var result = ui.isPatternExcluded(pattern, patternlab, uikit); //assert - test.equals(result, true); + test.equal(result, true); test.end(); } ); tap.test( 'isPatternExcluded - returns true when pattern is defaultPattern', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({}); - var pattern = new Pattern('00-test/foo.mustache'); + var pattern = new Pattern('test/foo.mustache'); patternlab.config.defaultPattern = 'test-foo'; //act var result = ui.isPatternExcluded(pattern, patternlab, uikit); //assert - test.equals(result, true); + test.equal(result, true); test.end(); } ); tap.test( 'isPatternExcluded - returns true when pattern within underscored directory - top level', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({}); var pattern = Pattern.createEmpty({ relPath: path.sep + - '_hidden' + + 'hidden' + path.sep + - 'patternsubtype' + + 'patternSubgroup' + path.sep + 'foo.mustache', isPattern: true, @@ -118,45 +119,53 @@ tap.test( patternPartial: 'hidden-foo', }); + pattern.patternGroupData = { + hidden: true, + }; + //act var result = ui.isPatternExcluded(pattern, patternlab, uikit); //assert - test.equals(result, true); + test.equal(result, true); test.end(); } ); tap.test( - 'isPatternExcluded - returns true when pattern within underscored directory - subtype level', - function(test) { + 'isPatternExcluded - returns true when pattern within underscored directory - subgroup level', + function (test) { //arrange var patternlab = createFakePatternLab({}); var pattern = Pattern.createEmpty({ relPath: - 'shown' + path.sep + '_patternsubtype' + path.sep + 'foo.mustache', + 'shown' + path.sep + 'patternsubtype' + path.sep + 'foo.mustache', isPattern: true, fileName: 'foo.mustache', patternPartial: 'shown-foo', }); + pattern.patternSubgroupData = { + hidden: true, + }; + //act var result = ui.isPatternExcluded(pattern, patternlab, uikit); //assert - test.equals(result, true); + test.equal(result, true); test.end(); } ); tap.test( 'isPatternExcluded - returns true when pattern state found withing uikit exclusions', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({}); var pattern = Pattern.createEmpty({ relPath: - 'shown' + path.sep + '_patternsubtype' + path.sep + 'foo.mustache', + 'shown' + path.sep + '_patternSubgroup' + path.sep + 'foo.mustache', isPattern: true, fileName: 'foo.mustache', patternPartial: 'shown-foo', @@ -169,129 +178,147 @@ tap.test( }); //assert - test.equals(result, true); + test.equal(result, true); test.end(); } ); -tap.test('groupPatterns - creates pattern groups correctly', function(test) { +tap.test('groupPatterns - creates pattern groups correctly', function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('00-test/bar.mustache'), - new Pattern('00-test/foo.mustache'), - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache'), - new Pattern('patternType1/patternSubType2/black.mustache'), - new Pattern('patternType1/patternSubType2/grey.mustache'), - new Pattern('patternType1/patternSubType2/white.mustache') + new Pattern('foobar.mustache'), + new Pattern('test/bar.mustache'), + new Pattern('test/foo.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') ); ui.resetUIBuilderState(patternlab); //act var result = ui.groupPatterns(patternlab, uikit); - test.equals( - result.patternGroups.patternType1.patternSubType1.blue.patternPartial, - 'patternType1-blue' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup1.blue.patternPartial, + 'patternGroup1-blue' ); - test.equals( - result.patternGroups.patternType1.patternSubType1.red.patternPartial, - 'patternType1-red' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup1.red.patternPartial, + 'patternGroup1-red' ); - test.equals( - result.patternGroups.patternType1.patternSubType1.yellow.patternPartial, - 'patternType1-yellow' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup1.yellow.patternPartial, + 'patternGroup1-yellow' ); - test.equals( - result.patternGroups.patternType1.patternSubType2.black.patternPartial, - 'patternType1-black' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup2.black.patternPartial, + 'patternGroup1-black' ); - test.equals( - result.patternGroups.patternType1.patternSubType2.grey.patternPartial, - 'patternType1-grey' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup2.grey.patternPartial, + 'patternGroup1-grey' ); - test.equals( - result.patternGroups.patternType1.patternSubType2.white.patternPartial, - 'patternType1-white' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup2.white.patternPartial, + 'patternGroup1-white' ); - test.equals( - patternlab.patternTypes[0].patternItems[0].patternPartial, + // Pattern groups are now sorted. Because of the missing prefix, they won't be + // found from the recursive file issuer in the order that was given by the + // number prefix. Now it will be by name if no order is set by group or + // subgroup frontmatter. + + //The groups for this test will be in the following order + //"patternGroup1", "root" (because it's a top-level flat pattern) and at last "test" + + // Flat patterns + test.equal( + patternlab.patternGroups[1].patternItems[0].patternPartial, + 'root-foobar', + 'flat pattern foobar on root' + ); + test.equal( + patternlab.patternGroups[2].patternItems[0].patternPartial, 'test-bar', 'first pattern item should be test-bar' ); - test.equals( - patternlab.patternTypes[0].patternItems[1].patternPartial, + test.equal( + patternlab.patternGroups[2].patternItems[1].patternPartial, 'test-foo', 'second pattern item should be test-foo' ); - //todo: patternlab.patternTypes[0].patternItems[1] looks malformed + //todo: patternlab.patternGroups[0].patternItems[1] looks malformed test.end(); }); -tap.test('groupPatterns - orders patterns when provided from md', function( - test -) { - //arrange - var patternlab = createFakePatternLab({ - patterns: [], - patternGroups: {}, - subtypePatterns: {}, - }); +tap.test( + 'groupPatterns - orders patterns when provided from md', + function (test) { + //arrange + var patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subgroupPatterns: {}, + }); - patternlab.patterns.push( - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache') - ); - ui.resetUIBuilderState(patternlab); + // Should be sorted by order and secondly by name + patternlab.patterns.push( + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache') + ); + ui.resetUIBuilderState(patternlab); - patternlab.patterns[1].order = 1; + // Set order of red to 1 to sort it after the others + patternlab.patterns[1].order = 1; - //act - ui.groupPatterns(patternlab, uikit); - - let patternType = _.find(patternlab.patternTypes, [ - 'patternType', - 'patternType1', - ]); - let patternSubType = _.find(patternType.patternTypeItems, [ - 'patternSubtype', - 'patternSubType1', - ]); - var items = patternSubType.patternSubtypeItems; - - //zero is viewall - test.equals(items[1].patternPartial, 'patternType1-red'); - test.equals(items[2].patternPartial, 'patternType1-blue'); - test.equals(items[3].patternPartial, 'patternType1-yellow'); + //act + ui.groupPatterns(patternlab, uikit); - test.end(); -}); + let patternGroup = _.find(patternlab.patternGroups, [ + 'patternGroup', + 'patternGroup1', + ]); + let patternSubgroup = _.find(patternGroup.patternGroupItems, [ + 'patternSubgroup', + 'patternSubgroup1', + ]); + var items = patternSubgroup.patternSubgroupItems; + + // Viewall should come last since it shows all patterns that are above + test.equal(items[0].patternPartial, 'patternGroup1-blue'); + test.equal(items[1].patternPartial, 'patternGroup1-yellow'); + test.equal(items[2].patternPartial, 'patternGroup1-red'); + + test.end(); + } +); tap.test( 'groupPatterns - retains pattern order from name when order provided from md is malformed', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache') + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache') ); ui.resetUIBuilderState(patternlab); @@ -300,39 +327,39 @@ tap.test( //act ui.groupPatterns(patternlab, uikit); - let patternType = _.find(patternlab.patternTypes, [ - 'patternType', - 'patternType1', + let patternGroup = _.find(patternlab.patternGroups, [ + 'patternGroup', + 'patternGroup1', ]); - let patternSubType = _.find(patternType.patternTypeItems, [ - 'patternSubtype', - 'patternSubType1', + let patternSubgroup = _.find(patternGroup.patternGroupItems, [ + 'patternSubgroup', + 'patternSubgroup1', ]); - var items = patternSubType.patternSubtypeItems; + var items = patternSubgroup.patternSubgroupItems; - //zero is viewall - test.equals(items[1].patternPartial, 'patternType1-blue'); - test.equals(items[2].patternPartial, 'patternType1-red'); - test.equals(items[3].patternPartial, 'patternType1-yellow'); + // Viewall should come last since it shows all patterns that are above + test.equal(items[0].patternPartial, 'patternGroup1-blue'); + test.equal(items[1].patternPartial, 'patternGroup1-red'); + test.equal(items[2].patternPartial, 'patternGroup1-yellow'); test.end(); } ); tap.test( - 'groupPatterns - sorts viewall subtype pattern to the beginning', - function(test) { + 'groupPatterns - sorts viewall subgroup pattern to the beginning', + function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache') + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache') ); ui.resetUIBuilderState(patternlab); @@ -343,48 +370,48 @@ tap.test( //act ui.groupPatterns(patternlab, uikit); - let patternType = _.find(patternlab.patternTypes, [ - 'patternType', - 'patternType1', + let patternGroup = _.find(patternlab.patternGroups, [ + 'patternGroup', + 'patternGroup1', ]); - let patternSubType = _.find(patternType.patternTypeItems, [ - 'patternSubtype', - 'patternSubType1', + let patternSubgroup = _.find(patternGroup.patternGroupItems, [ + 'patternSubgroup', + 'patternSubgroup1', ]); - var items = patternSubType.patternSubtypeItems; + var items = patternSubgroup.patternSubgroupItems; - //zero is viewall - test.equals( - items[0].patternPartial, - 'viewall-patternType1-patternSubType1' + // Viewall should come last since it shows all patterns that are above + test.equal( + items[3].patternPartial, + 'viewall-patternGroup1-patternSubgroup1' ); - test.equals(items[1].patternPartial, 'patternType1-blue'); - test.equals(items[2].patternPartial, 'patternType1-yellow'); - test.equals(items[3].patternPartial, 'patternType1-red'); + test.equal(items[0].patternPartial, 'patternGroup1-blue'); + test.equal(items[1].patternPartial, 'patternGroup1-yellow'); + test.equal(items[2].patternPartial, 'patternGroup1-red'); test.end(); } ); tap.test( - 'groupPatterns - creates documentation patterns for each type and subtype if not exists', - function(test) { + 'groupPatterns - creates documentation patterns for each type and subgroup if not exists', + function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('00-test/foo.mustache'), - new Pattern('00-test/bar.mustache'), - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache'), - new Pattern('patternType1/patternSubType2/black.mustache'), - new Pattern('patternType1/patternSubType2/grey.mustache'), - new Pattern('patternType1/patternSubType2/white.mustache') + new Pattern('test/foo.mustache'), + new Pattern('test/bar.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') ); ui.resetUIBuilderState(patternlab); @@ -392,17 +419,17 @@ tap.test( var result = ui.groupPatterns(patternlab, uikit); //assert - test.equals( - result.patternGroups.patternType1.patternSubType1[ - 'viewall-patternType1-patternSubType1' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup1[ + 'viewall-patternGroup1-patternSubgroup1' ].patternPartial, - 'viewall-patternType1-patternSubType1' + 'viewall-patternGroup1-patternSubgroup1' ); - test.equals( - result.patternGroups.patternType1.patternSubType2[ - 'viewall-patternType1-patternSubType2' + test.equal( + result.patternGroups.patternGroup1.patternSubgroup2[ + 'viewall-patternGroup1-patternSubgroup2' ].patternPartial, - 'viewall-patternType1-patternSubType2' + 'viewall-patternGroup1-patternSubgroup2' ); test.end(); @@ -411,23 +438,23 @@ tap.test( tap.test( 'groupPatterns - adds each pattern to the patternPaths object', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('00-test/foo.mustache'), - new Pattern('00-test/bar.mustache'), - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache'), - new Pattern('patternType1/patternSubType2/black.mustache'), - new Pattern('patternType1/patternSubType2/grey.mustache'), - new Pattern('patternType1/patternSubType2/white.mustache') + new Pattern('test/foo.mustache'), + new Pattern('test/bar.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') ); ui.resetUIBuilderState(patternlab); @@ -435,31 +462,31 @@ tap.test( var result = ui.groupPatterns(patternlab, uikit); //assert - test.equals(patternlab.patternPaths['test']['foo'], '00-test-foo'); - test.equals(patternlab.patternPaths['test']['bar'], '00-test-bar'); - test.equals( - patternlab.patternPaths['patternType1']['blue'], - 'patternType1-patternSubType1-blue' + test.equal(patternlab.patternPaths['test']['foo'], 'test-foo'); + test.equal(patternlab.patternPaths['test']['bar'], 'test-bar'); + test.equal( + patternlab.patternPaths['patternGroup1']['blue'], + 'patternGroup1-patternSubgroup1-blue' ); - test.equals( - patternlab.patternPaths['patternType1']['red'], - 'patternType1-patternSubType1-red' + test.equal( + patternlab.patternPaths['patternGroup1']['red'], + 'patternGroup1-patternSubgroup1-red' ); - test.equals( - patternlab.patternPaths['patternType1']['yellow'], - 'patternType1-patternSubType1-yellow' + test.equal( + patternlab.patternPaths['patternGroup1']['yellow'], + 'patternGroup1-patternSubgroup1-yellow' ); - test.equals( - patternlab.patternPaths['patternType1']['black'], - 'patternType1-patternSubType2-black' + test.equal( + patternlab.patternPaths['patternGroup1']['black'], + 'patternGroup1-patternSubgroup2-black' ); - test.equals( - patternlab.patternPaths['patternType1']['grey'], - 'patternType1-patternSubType2-grey' + test.equal( + patternlab.patternPaths['patternGroup1']['grey'], + 'patternGroup1-patternSubgroup2-grey' ); - test.equals( - patternlab.patternPaths['patternType1']['white'], - 'patternType1-patternSubType2-white' + test.equal( + patternlab.patternPaths['patternGroup1']['white'], + 'patternGroup1-patternSubgroup2-white' ); test.end(); @@ -468,23 +495,23 @@ tap.test( tap.test( 'groupPatterns - adds each pattern to the view all paths object', - function(test) { + function (test) { //arrange var patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, }); patternlab.patterns.push( - new Pattern('00-test/foo.mustache'), - new Pattern('00-test/bar.mustache'), - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache'), - new Pattern('patternType1/patternSubType2/black.mustache'), - new Pattern('patternType1/patternSubType2/grey.mustache'), - new Pattern('patternType1/patternSubType2/white.mustache') + new Pattern('test/foo.mustache'), + new Pattern('test/bar.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') ); ui.resetUIBuilderState(patternlab); @@ -492,40 +519,40 @@ tap.test( var result = ui.groupPatterns(patternlab, uikit); //assert - test.equals('todo', 'todo'); + test.equal('todo', 'todo'); test.end(); } ); -tap.test('resetUIBuilderState - reset global objects', function(test) { +tap.test('resetUIBuilderState - reset global objects', function (test) { //arrange var patternlab = createFakePatternLab({ patternPaths: { foo: 1 }, viewAllPaths: { bar: 2 }, - patternTypes: ['baz'], + patternGroups: ['baz'], }); //act ui.resetUIBuilderState(patternlab); //assert - test.equals(patternlab.patternPaths.foo, undefined); - test.equals(patternlab.viewAllPaths.bar, undefined); - test.equals(patternlab.patternTypes.length, 0); + test.equal(patternlab.patternPaths.foo, undefined); + test.equal(patternlab.viewAllPaths.bar, undefined); + test.equal(patternlab.patternGroups.length, 0); test.end(); }); tap.test( - 'buildViewAllPages - adds viewall page for each type and subtype', - function(test) { + 'buildViewAllPages - adds viewall page for each type and subgroup NOT! for flat patterns', + function (test) { //arrange const mainPageHeadHtml = ''; const patternlab = createFakePatternLab({ patterns: [], patternGroups: {}, - subtypePatterns: {}, + subgroupPatterns: {}, footer: {}, userFoot: {}, cacheBuster: 1234, @@ -533,53 +560,127 @@ tap.test( patternlab.patterns.push( //this flat pattern is found and causes trouble for the rest of the crew - new Pattern('00-test/foo.mustache'), - new Pattern('patternType1/patternSubType1/blue.mustache'), - new Pattern('patternType1/patternSubType1/red.mustache'), - new Pattern('patternType1/patternSubType1/yellow.mustache'), - new Pattern('patternType1/patternSubType2/black.mustache'), - new Pattern('patternType1/patternSubType2/grey.mustache'), - new Pattern('patternType1/patternSubType2/white.mustache') + new Pattern('test/foo.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') ); ui.resetUIBuilderState(patternlab); const styleguidePatterns = ui.groupPatterns(patternlab, uikit); //act - ui - .buildViewAllPages( - mainPageHeadHtml, - patternlab, - styleguidePatterns, - uikit - ) - .then(allPatterns => { - //assert - //this was a nuanced one. buildViewAllPages() had return false; statements - //within _.forOwn(...) loops, causing premature termination of the entire loop - //when what was intended was a continue - //we expect 8 here because: - // - foo.mustache is flat and therefore does not have a viewall page - // - the colors.mustache files make 6 - // - patternSubType1 and patternSubType2 make 8 - //while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, - //it's important to ensure that this method does not get prematurely terminated - //we choose to do that by checking it's return number of patterns - - //todo: this workaround matches the code at the moment - const uniquePatterns = _.uniq( - _.flatMapDeep(allPatterns, pattern => { - return pattern; - }) - ); - - test.equals( - uniquePatterns.length, - 8, - '2 viewall pages should be added' - ); - - test.end(); - }); + ui.buildViewAllPages( + mainPageHeadHtml, + patternlab, + styleguidePatterns, + uikit + ).then((allPatterns) => { + // assert + // this was a nuanced one. buildViewAllPages() had return false; statements + // within _.forOwn(...) loops, causing premature termination of the entire loop + // when what was intended was a continue + // we expect 10 here because: + // - foo.mustache is flat and therefore does not have a viewall page + // - the colors.mustache files make 6 + // - patternSubgroup1 and patternSubgroup2 make 8 + // - the general view all page make 9 + // while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, + // it's important to ensure that this method does not get prematurely terminated + // we choose to do that by checking it's return number of patterns + + const uniquePatterns = ui.uniqueAllPatterns(allPatterns, patternlab); + + /** + * - view-patternGroup1-all + * -- viewall-patternGroup1-patternSubgroup1 + * --- blue + * --- red + * --- yellow + * -- viewall-patternGroup1-patternSubgroup2 + * --- black + * --- grey + * --- white + */ + test.equal(uniquePatterns.length, 9, '3 viewall pages should be added'); + + test.end(); + }); + } +); + +tap.test( + 'buildViewAllPages - adds viewall page for each type and subgroup FOR! flat patterns', + function (test) { + //arrange + const mainPageHeadHtml = ''; + const patternlab = createFakePatternLab({ + patterns: [], + patternGroups: {}, + subgroupPatterns: {}, + footer: {}, + userFoot: {}, + cacheBuster: 1234, + }); + + patternlab.config.renderFlatPatternsOnViewAllPages = true; + + patternlab.patterns.push( + //this flat pattern is found and causes trouble for the rest of the crew + new Pattern('test/foo.mustache'), + new Pattern('patternGroup1/patternSubgroup1/blue.mustache'), + new Pattern('patternGroup1/patternSubgroup1/red.mustache'), + new Pattern('patternGroup1/patternSubgroup1/yellow.mustache'), + new Pattern('patternGroup1/patternSubgroup2/black.mustache'), + new Pattern('patternGroup1/patternSubgroup2/grey.mustache'), + new Pattern('patternGroup1/patternSubgroup2/white.mustache') + ); + ui.resetUIBuilderState(patternlab); + + const styleguidePatterns = ui.groupPatterns(patternlab, uikit); + + //act + ui.buildViewAllPages( + mainPageHeadHtml, + patternlab, + styleguidePatterns, + uikit + ).then((allPatterns) => { + // assert + // this was a nuanced one. buildViewAllPages() had return false; statements + // within _.forOwn(...) loops, causing premature termination of the entire loop + // when what was intended was a continue + // we expect 8 here because: + // - foo.mustache is flat and therefore does not have a viewall page + // - the colors.mustache files make 6 + // - patternSubgroup1 and patternSubgroup2 make 8 + // - the general view all page make 9 + // - the view-all page of test and test-foo make 11 + // while most of that heavy lifting occurs inside groupPatterns and not buildViewAllPages, + // it's important to ensure that this method does not get prematurely terminated + // we choose to do that by checking it's return number of patterns + + const uniquePatterns = ui.uniqueAllPatterns(allPatterns, patternlab); + + /** + * - viewall-test-all + * -- test-foo + * - view-patternGroup1-all + * -- viewall-patternGroup1-patternSubgroup1 + * --- blue + * --- red + * --- yellow + * -- viewall-patternGroup1-patternSubgroup2 + * --- black + * --- grey + * --- white + */ + test.equal(uniquePatterns.length, 11, '4 viewall pages should be added'); + + test.end(); + }); } ); diff --git a/packages/core/test/uikitExcludePattern_tests.js b/packages/core/test/uikitExcludePattern_tests.js index a31f4c3f3..f19301d12 100644 --- a/packages/core/test/uikitExcludePattern_tests.js +++ b/packages/core/test/uikitExcludePattern_tests.js @@ -6,7 +6,7 @@ const uikitExcludePattern = require('../src/lib/uikitExcludePattern'); tap.test( 'uikitExcludePattern - returns false when uikit has no excluded states', - test => { + (test) => { //arrange const uikit = { excludedPatternStates: [] }; const pattern = { patternState: 'complete' }; @@ -22,7 +22,7 @@ tap.test( tap.test( 'uikitExcludePattern - returns false pattern does not have same state as uikit exclusions', - test => { + (test) => { //arrange const uikit = { excludedPatternStates: ['complete'] }; const pattern = { patternState: 'inprogress' }; @@ -38,7 +38,7 @@ tap.test( tap.test( 'uikitExcludePattern - returns true when uikit has same state as pattern', - test => { + (test) => { //arrange const uikit = { excludedPatternStates: ['inreview', 'complete'] }; const pattern = { patternState: 'complete' }; @@ -51,3 +51,51 @@ tap.test( test.end(); } ); + +tap.test( + 'uikitExcludePattern - returns false when uikit has no excluded tags', + (test) => { + //arrange + const uikit = { excludedTags: [] }; + const pattern = { tags: 'foo-tag' }; + + //act + const result = uikitExcludePattern(pattern, uikit); + + //assert + test.false(result); + test.end(); + } +); + +tap.test( + 'uikitExcludePattern - returns false pattern does not have same tags as uikit exclusions', + (test) => { + //arrange + const uikit = { excludedTags: ['bat-tag'] }; + const pattern = { tags: 'foo-tag' }; + + //act + const result = uikitExcludePattern(pattern, uikit); + + //assert + test.false(result); + test.end(); + } +); + +tap.test( + 'uikitExcludePattern - returns true when uikit has same tags as pattern', + (test) => { + //arrange + const uikit = { excludedTags: ['bar-tag', 'foo-tag'] }; + const pattern = { tags: 'foo-tag' }; + + //act + const result = uikitExcludePattern(pattern, uikit); + + //assert + test.true(result); + test.end(); + } +); diff --git a/packages/core/test/util/patternlab-config.json b/packages/core/test/util/patternlab-config.json index c2edf9561..e101b2ad4 100644 --- a/packages/core/test/util/patternlab-config.json +++ b/packages/core/test/util/patternlab-config.json @@ -7,12 +7,12 @@ "meta": "./test/files/_meta/", "styleguide": "./test/files/styleguide/", "patternlabFiles": { - "general-header": "./test/files/partials/general-header.mustache", - "general-footer": "./test/files/partials/general-footer.mustache", - "patternSection": "./test/files/partials/patternSection.mustache", - "patternSectionSubtype": - "./test/files/partials/patternSectionSubtype.mustache", - "viewall": "./test/files/viewall.mustache" + "general-header": "views/partials/general-header.mustache", + "general-footer": "views/partials/general-footer.mustache", + "patternSection": "views/partials/patternSection.mustache", + "patternSectionSubgroup": + "views/partials/patternSectionSubgroup.mustache", + "viewall": "views/viewall.mustache" }, "js": "./test/files/js", "images": "./test/files/images", @@ -57,6 +57,8 @@ "patternExportPatternPartials": [], "patternExportDirectory": "./pattern_exports/", "patternExtension": "mustache", + "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "cacheBust": true, "outputFileSuffixes": { "rendered": ".rendered", @@ -71,11 +73,28 @@ "density": "compact", "layout": "horizontal" }, + "engines": { + "handlebars": { + "package": "@pattern-lab/engine-handlebars", + "fileExtensions": [ + "handlebars", + "hbs" + ], + "extend": "helpers/*.js" + } + }, "uikits": [ { "name": "uikit-workshop", - "outputDir": "packages/core/test/", + "outputDir": "test/", "enabled": true, + "excludedPatternStates": ["legacy"], + "excludedTags": ["baz"] + }, + { + "name": "uikit-polyfills", + "outputDir": "test/", + "enabled": false, "excludedPatternStates": [], "excludedTags": [] } diff --git a/packages/core/test/util/test_utils.js b/packages/core/test/util/test_utils.js index 36d3f6e1d..0558f500a 100644 --- a/packages/core/test/util/test_utils.js +++ b/packages/core/test/util/test_utils.js @@ -11,7 +11,7 @@ module.exports = { graph: PatternGraph.empty(), partials: {}, patterns: [], - subtypePatterns: {}, + subgroupPatterns: {}, footer: '', header: '', listitems: {}, @@ -33,7 +33,7 @@ module.exports = { * Strip out control characters from output if needed so make comparisons easier * @param output - the template to strip */ - sanitized: outputTemplate => { + sanitized: (outputTemplate) => { return outputTemplate .replace(/\n/g, ' ') .replace(/\r/g, ' ') @@ -45,7 +45,7 @@ module.exports = { * normalize a string (probably a path) to posix - style * @param s - the string or array of strings to normalize path separators to posix - style */ - posixPath: s => { + posixPath: (s) => { if (Array.isArray(s)) { var paths = []; for (let i = 0; i < s.length; i++) { diff --git a/packages/core/test/watchAssets_tests.js b/packages/core/test/watchAssets_tests.js index d72cd0715..ab96f3b0b 100644 --- a/packages/core/test/watchAssets_tests.js +++ b/packages/core/test/watchAssets_tests.js @@ -12,7 +12,7 @@ const patterns_dir = './test/files/_patterns'; tap.test( 'watchAssets - adds assetWatcher to patternlab.watchers for given key ', - test => { + (test) => { const pl = util.fakePatternLab(patterns_dir, { watchers: [] }); const key = 'images'; @@ -25,15 +25,15 @@ tap.test( true ); - test.equals(_.keys(pl.watchers)[0], 'images'); + test.equal(_.keys(pl.watchers)[0], 'images'); test.end(); } ); -tap.test('watchAssets - complete path copied', test => { - const copyFileMock = function(p, des) { - test.equals(des, path.resolve('/proj/public/images/sample/waterfall.jpg')); +tap.test('watchAssets - complete path copied', (test) => { + const copyFileMock = function (p, des) { + test.equal(des, path.resolve('/proj/public/images/sample/waterfall.jpg')); }; //set our mocks in place of usual require() diff --git a/packages/core/test/watchPatternLabFiles_tests.js b/packages/core/test/watchPatternLabFiles_tests.js index f61b873e6..0dcc7fbc1 100644 --- a/packages/core/test/watchPatternLabFiles_tests.js +++ b/packages/core/test/watchPatternLabFiles_tests.js @@ -12,7 +12,7 @@ const patterns_dir = './test/files/_patterns'; tap.test( 'watchPatternLabFiles - adds watcher to patternlab.watchers for given patternWatchPath', - test => { + (test) => { const pl = util.fakePatternLab(patterns_dir, { watchers: [], engines: {}, @@ -37,7 +37,7 @@ tap.test( // should have two for _data and _meta // should have five for '.json', '.yml', '.yaml', '.md' and '.mustache' - test.equals(Object.keys(pl.watchers).length, 7); + test.equal(Object.keys(pl.watchers).length, 7); test.end(); } diff --git a/packages/create/CHANGELOG.md b/packages/create/CHANGELOG.md new file mode 100644 index 000000000..edc41d235 --- /dev/null +++ b/packages/create/CHANGELOG.md @@ -0,0 +1,308 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/compare/v5.15.1...v5.15.2) (2021-11-03) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/compare/v5.15.0...v5.15.1) (2021-10-16) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/compare/v5.14.3...v5.15.0) (2021-07-01) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.1) (2020-06-28) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.0) (2020-06-28) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/compare/v5.9.3...v5.10.0) (2020-05-09) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [5.9.1](https://github.com/pattern-lab/patternlab-node/compare/v5.9.0...v5.9.1) (2020-04-24) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/compare/v5.8.0...v5.9.0) (2020-04-24) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.7.0](https://github.com/pattern-lab/patternlab-node/compare/v5.6.0...v5.7.0) (2020-02-17) + +**Note:** Version bump only for package create-pattern-lab + + + + + + +# [5.4.0](https://github.com/pattern-lab/patternlab-node/compare/v5.3.3...v5.4.0) (2019-11-26) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.3.0](https://github.com/pattern-lab/patternlab-node/compare/v5.2.0...v5.3.0) (2019-11-13) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.1.0](https://github.com/pattern-lab/patternlab-node/compare/v5.0.2...v5.1.0) (2019-10-29) + +**Note:** Version bump only for package create-pattern-lab + + + + + +# [5.0.0](https://github.com/pattern-lab/patternlab-node/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + +**Note:** Version bump only for package create-pattern-lab + + + + + + +## [1.0.11](https://github.com/pattern-lab/patternlab-node/compare/create-pattern-lab@1.0.10...create-pattern-lab@1.0.11) (2019-10-14) + +**Note:** Version bump only for package create-pattern-lab + + + + + + +## [1.0.8](https://github.com/pattern-lab/patternlab-node/compare/create-pattern-lab@1.0.7...create-pattern-lab@1.0.8) (2019-08-23) + +**Note:** Version bump only for package create-pattern-lab + + + + + +## [1.0.7](https://github.com/pattern-lab/patternlab-node/compare/create-pattern-lab@1.0.6...create-pattern-lab@1.0.7) (2019-08-23) + +**Note:** Version bump only for package create-pattern-lab + + + + + + +## [1.0.6](https://github.com/sghoweri/patternlab-node/compare/create-pattern-lab@1.0.5...create-pattern-lab@1.0.6) (2019-05-16) + +**Note:** Version bump only for package create-pattern-lab diff --git a/packages/create/README.md b/packages/create/README.md index 53e6f5770..28d56e5da 100644 --- a/packages/create/README.md +++ b/packages/create/README.md @@ -12,5 +12,5 @@ This is the same as using the main Pattern Lab CLI's `init` command: ```bash npm i -g @pattern-lab/cli -pattern-lab init +patternlab init ``` diff --git a/packages/create/package.json b/packages/create/package.json index 1444122a0..2785e53c6 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,16 +1,20 @@ { "name": "create-pattern-lab", - "version": "1.0.5", + "version": "6.1.0", "description": "", "bin": "index.js", "main": "index.js", "scripts": {}, "dependencies": { - "@pattern-lab/cli": "^0.0.3-alpha.0" + "@pattern-lab/cli": "^6.1.0" }, "author": "", "license": "MIT", "publishConfig": { "access": "public" + }, + "gitHead": "80f62be442223e09bafb30d0529cbd768e03f2ac", + "engines": { + "node": ">=16.20.0" } } diff --git a/packages/development-edition-engine-handlebars/.gitignore b/packages/development-edition-engine-handlebars/.gitignore index 0679bd2b5..534543a52 100644 --- a/packages/development-edition-engine-handlebars/.gitignore +++ b/packages/development-edition-engine-handlebars/.gitignore @@ -7,3 +7,4 @@ Thumbs.db .idea/ public dependencyGraph.json +source/* diff --git a/packages/development-edition-engine-handlebars/.nvmrc b/packages/development-edition-engine-handlebars/.nvmrc index 95c4e8d27..59ea99ee6 100644 --- a/packages/development-edition-engine-handlebars/.nvmrc +++ b/packages/development-edition-engine-handlebars/.nvmrc @@ -1 +1 @@ -10.0.0 \ No newline at end of file +16.20 diff --git a/packages/development-edition-engine-handlebars/CHANGELOG.md b/packages/development-edition-engine-handlebars/CHANGELOG.md index e39939cb7..635e4b857 100644 --- a/packages/development-edition-engine-handlebars/CHANGELOG.md +++ b/packages/development-edition-engine-handlebars/CHANGELOG.md @@ -3,6 +3,500 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [6.0.3](https://github.com/pattern-lab/patternlab-node/compare/v6.0.2...v6.0.3) (2023-03-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + + +### Bug Fixes + +* **annotations:** displaying annotation tooltips correctly ([#1406](https://github.com/pattern-lab/patternlab-node/issues/1406)) ([3f33ce5](https://github.com/pattern-lab/patternlab-node/commit/3f33ce5c51f2f7a6afd86d3500b7659afd0198e6)), closes [#2](https://github.com/pattern-lab/patternlab-node/issues/2) [#1](https://github.com/pattern-lab/patternlab-node/issues/1) + + + + + +## [5.15.7](https://github.com/pattern-lab/patternlab-node/compare/v5.15.6...v5.15.7) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.6](https://github.com/pattern-lab/patternlab-node/compare/v5.15.5...v5.15.6) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.3](https://github.com/pattern-lab/patternlab-node/compare/v5.15.2...v5.15.3) (2021-11-21) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/compare/v5.15.1...v5.15.2) (2021-11-03) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/compare/v5.15.0...v5.15.1) (2021-10-16) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/compare/v5.14.3...v5.15.0) (2021-07-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.1) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.0) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.10.2](https://github.com/pattern-lab/patternlab-node/compare/v5.10.1...v5.10.2) (2020-05-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([b4eb12e](https://github.com/pattern-lab/patternlab-node/commit/b4eb12e68ceb402964a7e303610e5b0c008876ba)) + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.9.2](https://github.com/pattern-lab/patternlab-node/compare/v5.9.1...v5.9.2) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.9.1](https://github.com/pattern-lab/patternlab-node/compare/v5.9.0...v5.9.1) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/compare/v5.8.0...v5.9.0) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.7.2](https://github.com/pattern-lab/patternlab-node/compare/v5.7.1...v5.7.2) (2020-03-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.7.1](https://github.com/pattern-lab/patternlab-node/compare/v5.7.0...v5.7.1) (2020-02-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.7.0](https://github.com/pattern-lab/patternlab-node/compare/v5.6.0...v5.7.0) (2020-02-17) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.6.0](https://github.com/pattern-lab/patternlab-node/compare/v5.5.0...v5.6.0) (2020-01-18) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + + +# [5.5.0](https://github.com/pattern-lab/patternlab-node/compare/v5.4.2...v5.5.0) (2019-12-19) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.4.2](https://github.com/pattern-lab/patternlab-node/compare/v5.4.1...v5.4.2) (2019-11-27) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.4.1](https://github.com/pattern-lab/patternlab-node/compare/v5.4.0...v5.4.1) (2019-11-26) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.4.0](https://github.com/pattern-lab/patternlab-node/compare/v5.3.3...v5.4.0) (2019-11-26) + + +### Features + +* major improvements to local UIKit workflow ([4dc9173](https://github.com/pattern-lab/patternlab-node/commit/4dc9173a5a44b422e9677824de3728048b7c4f05)) + + + + + +## [5.3.3](https://github.com/pattern-lab/patternlab-node/compare/v5.3.2...v5.3.3) (2019-11-22) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + + +## [5.3.2](https://github.com/pattern-lab/patternlab-node/compare/v5.3.1...v5.3.2) (2019-11-14) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.3.1](https://github.com/pattern-lab/patternlab-node/compare/v5.3.0...v5.3.1) (2019-11-13) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.3.0](https://github.com/pattern-lab/patternlab-node/compare/v5.2.0...v5.3.0) (2019-11-13) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.2.0](https://github.com/pattern-lab/patternlab-node/compare/v5.1.0...v5.2.0) (2019-11-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + + +# [5.1.0](https://github.com/pattern-lab/patternlab-node/compare/v5.0.2...v5.1.0) (2019-10-29) + + +### Features + +* **config:** add new default pattern export options ([a7487a0](https://github.com/pattern-lab/patternlab-node/commit/a7487a0681cb11e6f3c5c8eaefd62e5648ad5ea3)) + + + + + +## [5.0.2](https://github.com/pattern-lab/patternlab-node/compare/v5.0.1...v5.0.2) (2019-10-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +## [5.0.1](https://github.com/pattern-lab/patternlab-node/compare/v5.0.0...v5.0.1) (2019-10-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [5.0.0](https://github.com/pattern-lab/patternlab-node/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + + +### Bug Fixes + +* Rename Handlebars and Nunjucks extension setting to "extend" ([74e5af2](https://github.com/pattern-lab/patternlab-node/commit/74e5af28c4e714fdfc1db535b94c52f3dc14a3a4)) +* update the default pattern that displays in the Handlebars demo ([ff1d85f](https://github.com/pattern-lab/patternlab-node/commit/ff1d85f2852fc4f210841e8e0aaf14b55165ce58)) + + +### Features + +* **engine-handlebars:** Demonstration of custom Handlebars helper ([f330b5b](https://github.com/pattern-lab/patternlab-node/commit/f330b5bca72f2f34bfafe5c2c64e6b0b8823eb1c)) +* **plugin-tab, core:** initial plugin hook exploration ([2f3d39a](https://github.com/pattern-lab/patternlab-node/commit/2f3d39ac6b125ad4c6b872e27ee224ce2ea33a12)) +* introduce netlify preview ([6c5d332](https://github.com/pattern-lab/patternlab-node/commit/6c5d332479fb6836bd8bd5530a074d13440f8ae4)) + + + + + + +## [0.1.6](https://github.com/pattern-lab/patternlab-node/compare/@pattern-lab/development-edition-engine-handlebars@0.1.5...@pattern-lab/development-edition-engine-handlebars@0.1.6) (2019-10-14) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + + +## [0.1.5](https://github.com/pattern-lab/patternlab-node/compare/@pattern-lab/development-edition-engine-handlebars@0.1.4...@pattern-lab/development-edition-engine-handlebars@0.1.5) (2019-10-14) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + + +## [0.1.1](https://github.com/pattern-lab/patternlab-node/compare/@pattern-lab/development-edition-engine-handlebars@0.1.0...@pattern-lab/development-edition-engine-handlebars@0.1.1) (2019-08-23) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + +# [0.1.0](https://github.com/pattern-lab/patternlab-node/compare/@pattern-lab/development-edition-engine-handlebars@0.0.3...@pattern-lab/development-edition-engine-handlebars@0.1.0) (2019-08-23) + + +### Bug Fixes + +* Rename Handlebars and Nunjucks extension setting to "extend" ([74e5af2](https://github.com/pattern-lab/patternlab-node/commit/74e5af2)) + + +### Features + +* **engine-handlebars:** Demonstration of custom Handlebars helper ([f330b5b](https://github.com/pattern-lab/patternlab-node/commit/f330b5b)) + + + + + + +## [0.0.3](https://github.com/pattern-lab/patternlab-node/compare/@pattern-lab/development-edition-engine-handlebars@0.0.3-alpha.0...@pattern-lab/development-edition-engine-handlebars@0.0.3) (2019-05-16) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-handlebars + + + + + ## 0.0.1-beta.0 (2019-02-09) diff --git a/packages/development-edition-engine-handlebars/README.md b/packages/development-edition-engine-handlebars/README.md index 722416c2a..27766e215 100644 --- a/packages/development-edition-engine-handlebars/README.md +++ b/packages/development-edition-engine-handlebars/README.md @@ -9,4 +9,20 @@ This Development Edition is a variant of [Edition Node](https://github.com/patte * Develop the [Handlebars Engine](https://github.com/pattern-lab/patternlab-node/tree/master/packages/engine-handlebars) * Build and test against Handlebars pattern tree -> Development Editions of Pattern Lab provide the ability to work on and commit changes to select packages within the overall Pattern Lab [ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). This Edition is NOT stable. +> Development Editions of Pattern Lab provide the ability to work on and commit changes to select packages within the overall Pattern Lab [ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). This Edition is NOT stable. + + +## Working on Pattern Lab's UI Locally + +### Step 1: Install Dependencies +Run the following in the root of the Pattern Lab repo: + +``` +yarn run setup +``` + +### Step 2 (Optional) +If you want to build using a fuller set of examples than what comes with this default Handlebars demo, run `yarn run preview:hbs`. Otherwise skip to step 3. + +### Step 3 +Finally, go back into this folder, `cd packages/development-edition-engine-handlebars`, and start up the local dev server which watches UIKit and the local Pattern Lab instance for changes, live reloads, etc by running `yarn dev` diff --git a/packages/development-edition-engine-handlebars/helpers/test.js b/packages/development-edition-engine-handlebars/helpers/test.js new file mode 100644 index 000000000..6ddbc2bba --- /dev/null +++ b/packages/development-edition-engine-handlebars/helpers/test.js @@ -0,0 +1,5 @@ +module.exports = function (Handlebars) { + Handlebars.registerHelper('test', function () { + return 'This is a test helper'; + }); +}; diff --git a/packages/development-edition-engine-handlebars/package.json b/packages/development-edition-engine-handlebars/package.json index 1869d4dd5..52c59b7d6 100644 --- a/packages/development-edition-engine-handlebars/package.json +++ b/packages/development-edition-engine-handlebars/package.json @@ -1,14 +1,16 @@ { "name": "@pattern-lab/development-edition-engine-handlebars", "private": true, - "version": "0.0.3-alpha.0", + "version": "6.1.0", "description": "The tree of components we use to test, develop and validate the Handlebars engine", "scripts": { "pl:build": "patternlab build --config ./patternlab-config.json", "pl:help": "patternlab --help", "pl:install": "patternlab install --config ./patternlab-config.json", "pl:serve": "patternlab serve --config ./patternlab-config.json", - "pl:version": "patternlab --version" + "pl:starterkit": "patternlab add --starterkits @pattern-lab/starterkit-handlebars-demo", + "pl:version": "patternlab --version", + "dev": "node ./node_modules/@pattern-lab/uikit-workshop/build-tools.js" }, "keywords": [ "Pattern Lab", @@ -24,14 +26,15 @@ "url": "git://github.com/pattern-lab/patternlab-node.git" }, "engines": { - "node": ">=10.0" + "node": ">=16.20.0" }, "dependencies": { - "@pattern-lab/cli": "^0.0.3-alpha.0", - "@pattern-lab/core": "^3.0.1-alpha.0", - "@pattern-lab/engine-handlebars": "^2.0.0-beta.1", - "@pattern-lab/engine-mustache": "^2.0.1-alpha.0", - "@pattern-lab/starterkit-mustache-demo": "^5.0.0", - "@pattern-lab/uikit-workshop": "^1.0.1-alpha.0" + "@pattern-lab/cli": "^6.1.0", + "@pattern-lab/core": "^6.1.0", + "@pattern-lab/engine-handlebars": "^6.1.0", + "@pattern-lab/engine-mustache": "^6.1.0", + "@pattern-lab/plugin-tab": "^6.1.0", + "@pattern-lab/starterkit-handlebars-demo": "^6.1.0", + "@pattern-lab/uikit-workshop": "^6.1.0" } } diff --git a/packages/development-edition-engine-handlebars/patternlab-config.json b/packages/development-edition-engine-handlebars/patternlab-config.json index dae655991..a8873d362 100644 --- a/packages/development-edition-engine-handlebars/patternlab-config.json +++ b/packages/development-edition-engine-handlebars/patternlab-config.json @@ -4,9 +4,9 @@ "defaultPattern": "all", "defaultShowPatternInfo": false, "ishControlsHide": { - "s": true, - "m": true, - "l": true, + "s": false, + "m": false, + "l": false, "full": false, "random": true, "disco": true, @@ -21,9 +21,18 @@ "tools-docs": false }, "ishViewportRange": { - "s": [240, 500], - "m": [500, 800], - "l": [800, 2600] + "s": [ + 240, + 500 + ], + "m": [ + 500, + 800 + ], + "l": [ + 800, + 2600 + ] }, "logLevel": "info", "outputFileSuffixes": { @@ -43,7 +52,7 @@ "general-header": "views/partials/general-header.mustache", "general-footer": "views/partials/general-footer.mustache", "patternSection": "views/partials/patternSection.mustache", - "patternSectionSubtype": "views/partials/patternSectionSubtype.mustache", + "patternSectionSubgroup": "views/partials/patternSectionSubgroup.mustache", "viewall": "views/viewall.mustache" }, "js": "source/js", @@ -64,9 +73,18 @@ } }, "patternExtension": "hbs", - "patternStateCascade": ["inprogress", "inreview", "complete"], + "patternStateCascade": [ + "inprogress", + "inreview", + "complete" + ], + "patternExportAll": false, "patternExportDirectory": "pattern_exports", "patternExportPatternPartials": [], + "patternExportPreserveDirectoryStructure": true, + "patternExportRaw": false, + "patternMergeVariantArrays": false, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, @@ -75,15 +93,38 @@ "theme": { "color": "dark", "density": "compact", - "layout": "horizontal" + "layout": "horizontal", + "noViewAll": false }, "uikits": [ { "name": "uikit-workshop", + "package": "@pattern-lab/uikit-workshop", "outputDir": "", "enabled": true, "excludedPatternStates": [], "excludedTags": [] } - ] + ], + "engines": { + "handlebars": { + "package": "@pattern-lab/engine-handlebars", + "fileExtensions": [ + "handlebars", + "hbs" + ], + "extend": "helpers/*.js" + } + }, + "plugins": { + "@pattern-lab/plugin-tab": { + "enabled": true, + "initialized": false, + "options": { + "tabsToAdd": [ + "scss" + ] + } + } + } } diff --git a/packages/development-edition-engine-handlebars/source/_data/data.json b/packages/development-edition-engine-handlebars/source/_data/data.json index 250376db0..0967ef424 100644 --- a/packages/development-edition-engine-handlebars/source/_data/data.json +++ b/packages/development-edition-engine-handlebars/source/_data/data.json @@ -1,34 +1 @@ -{ - "version": "2", - "swatches": [ - { - "color": { - "hex": "#031636", - "cmyk": "94 59 0 79" - }, - "label": "dark blue" - }, - { - "color": { - "hex": "#0D80F0", - "cmyk": "95 47 0 6" - }, - "label": "light blue" - }, - { - "color": { - "hex": "#4c4c4c", - "cmyk": "0 0 0 70" - }, - "label": "dark grey" - }, - { - "color": { - "hex": "#b2b2b2", - "cmyk": "0 0 0 30" - }, - "label": "light grey", - "inverted": true - } - ] -} +{} diff --git a/packages/development-edition-engine-handlebars/source/_data/listitems.json b/packages/development-edition-engine-handlebars/source/_data/listitems.json index c35d1076d..0967ef424 100644 --- a/packages/development-edition-engine-handlebars/source/_data/listitems.json +++ b/packages/development-edition-engine-handlebars/source/_data/listitems.json @@ -1,6 +1 @@ -{ - "1": {}, - "2": {}, - "3": {}, - "4": {} -} +{} diff --git a/packages/development-edition-engine-handlebars/source/_meta/README.md b/packages/development-edition-engine-handlebars/source/_meta/README.md index c6c8c3b8e..b5d2c4537 100644 --- a/packages/development-edition-engine-handlebars/source/_meta/README.md +++ b/packages/development-edition-engine-handlebars/source/_meta/README.md @@ -1,5 +1,5 @@ This is the default location to place meta files, otherwise known a pattern's header and footer. -Pattern Lab builds each pattern while prepending and appending the header and footer. Read more about [pattern headers and footers](http://patternlab.io/docs/pattern-header-footer.html). +Pattern Lab builds each pattern while prepending and appending the header and footer. Read more about [pattern headers and footers](https://patternlab.io/docs/modifying-the-pattern-header-and-footer/). If you wish to rename this directory, make sure you update the `paths.source.meta` property within `patternlab-config.json`. diff --git a/packages/development-edition-engine-handlebars/source/_meta/_00-head.hbs b/packages/development-edition-engine-handlebars/source/_meta/_00-head.hbs deleted file mode 100644 index 9058b6521..000000000 --- a/packages/development-edition-engine-handlebars/source/_meta/_00-head.hbs +++ /dev/null @@ -1,19 +0,0 @@ - - - - - {{ title }} - - - - - - - - - {{{ patternLabHead }}} - - - - - diff --git a/packages/development-edition-engine-handlebars/source/_meta/_foot.hbs b/packages/development-edition-engine-handlebars/source/_meta/_foot.hbs new file mode 100644 index 000000000..2c8fd83b5 --- /dev/null +++ b/packages/development-edition-engine-handlebars/source/_meta/_foot.hbs @@ -0,0 +1,8 @@ + + + {{{ patternLabFoot }}} + + + + + \ No newline at end of file diff --git a/packages/development-edition-engine-handlebars/source/_meta/_foot.mustache b/packages/development-edition-engine-handlebars/source/_meta/_foot.mustache new file mode 100644 index 000000000..98d360860 --- /dev/null +++ b/packages/development-edition-engine-handlebars/source/_meta/_foot.mustache @@ -0,0 +1,9 @@ + + + + + {{{ patternLabFoot }}} + + + + diff --git a/packages/development-edition-engine-handlebars/source/_meta/_head.hbs b/packages/development-edition-engine-handlebars/source/_meta/_head.hbs new file mode 100644 index 000000000..76899a54a --- /dev/null +++ b/packages/development-edition-engine-handlebars/source/_meta/_head.hbs @@ -0,0 +1,18 @@ + + + + {{ title }} + + + + + + + + + {{{ patternLabHead }}} + + + + + diff --git a/packages/development-edition-engine-handlebars/source/_meta/_head.mustache b/packages/development-edition-engine-handlebars/source/_meta/_head.mustache new file mode 100644 index 000000000..76899a54a --- /dev/null +++ b/packages/development-edition-engine-handlebars/source/_meta/_head.mustache @@ -0,0 +1,18 @@ + + + + {{ title }} + + + + + + + + + {{{ patternLabHead }}} + + + + + diff --git a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.hbs b/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.hbs deleted file mode 100644 index 804dcbfe5..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.hbs +++ /dev/null @@ -1,5 +0,0 @@ -
- {{label}} - hex: {{color.hex}} - cmyk: {{color.cmyk}} -
diff --git a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.json b/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.json deleted file mode 100644 index 15d3872ba..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "color": { - "hex": "#031636", - "cmyk": "94 59 0 79" - }, - "label": "dark blue" -} diff --git a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.md b/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.md deleted file mode 100644 index 3f2d7ea0f..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/atoms/swatches/swatch.md +++ /dev/null @@ -1 +0,0 @@ -Pattern Lab Tip: Note the use of the [built-in handlebars helper, `if`](https://handlebarsjs.com/builtin_helpers.html) and the ability to address data using dot notation [paths](https://handlebarsjs.com/#paths). diff --git a/packages/development-edition-engine-handlebars/source/_patterns/atoms/type.md b/packages/development-edition-engine-handlebars/source/_patterns/atoms/type.md deleted file mode 100644 index 245bc9dcd..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/atoms/type.md +++ /dev/null @@ -1 +0,0 @@ -Type diff --git a/packages/development-edition-engine-handlebars/source/_patterns/atoms/type/annotation.hbs b/packages/development-edition-engine-handlebars/source/_patterns/atoms/type/annotation.hbs deleted file mode 100644 index 7d556dbab..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/atoms/type/annotation.hbs +++ /dev/null @@ -1 +0,0 @@ -{{#if annotation}}{{annotation}}{{else}}v{{version}}{{/if}} diff --git a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants.md b/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants.md deleted file mode 100644 index 345e6aef7..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants.md +++ /dev/null @@ -1 +0,0 @@ -Test diff --git a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.hbs b/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.hbs deleted file mode 100644 index 9cb654819..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.hbs +++ /dev/null @@ -1,8 +0,0 @@ -
    -
  • hi12 - {{> atoms-annotation annotation="possible colors"}} -
  • - {{#each swatches}} -
  • {{> atoms-swatch }}
  • - {{/each}} -
diff --git a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.md b/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.md deleted file mode 100644 index 131286757..000000000 --- a/packages/development-edition-engine-handlebars/source/_patterns/molecules/variants/swatches.md +++ /dev/null @@ -1 +0,0 @@ -Pattern Lab Tip: Note the use of the [built-in handlebars helper, `each`](https://handlebarsjs.com/builtin_helpers.html). diff --git a/packages/development-edition-engine-handlebars/source/css/style.css b/packages/development-edition-engine-handlebars/source/css/style.css index 7f25a7fe6..e69de29bb 100644 --- a/packages/development-edition-engine-handlebars/source/css/style.css +++ b/packages/development-edition-engine-handlebars/source/css/style.css @@ -1,3 +0,0 @@ -.annotation { - color: #b2b2b2; -} diff --git a/packages/development-edition-engine-handlebars/source/fonts/.gitkeep b/packages/development-edition-engine-handlebars/source/fonts/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/development-edition-engine-react/.nvmrc b/packages/development-edition-engine-react/.nvmrc index 95c4e8d27..59ea99ee6 100644 --- a/packages/development-edition-engine-react/.nvmrc +++ b/packages/development-edition-engine-react/.nvmrc @@ -1 +1 @@ -10.0.0 \ No newline at end of file +16.20 diff --git a/packages/development-edition-engine-react/CHANGELOG.md b/packages/development-edition-engine-react/CHANGELOG.md index 7d2ddb035..6924275e4 100644 --- a/packages/development-edition-engine-react/CHANGELOG.md +++ b/packages/development-edition-engine-react/CHANGELOG.md @@ -3,6 +3,460 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.1.0](https://github.com/pattern-lab/edition-node-gulp/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [6.0.3](https://github.com/pattern-lab/edition-node-gulp/compare/v6.0.2...v6.0.3) (2023-03-12) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [6.0.1](https://github.com/pattern-lab/edition-node-gulp/compare/v6.0.0...v6.0.1) (2023-02-01) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [6.0.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.17.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.16.4...v5.17.0) (2022-09-25) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.16.4](https://github.com/pattern-lab/edition-node-gulp/compare/v5.16.2...v5.16.4) (2022-09-23) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.16.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.16.1...v5.16.2) (2022-02-07) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.16.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.16.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.7...v5.16.0) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.7](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.6...v5.15.7) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.6](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.5...v5.15.6) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.5](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.4](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.3](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.2...v5.15.3) (2021-11-21) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.1...v5.15.2) (2021-11-03) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.15.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.15.0...v5.15.1) (2021-10-16) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.15.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.14.3...v5.15.0) (2021-07-01) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.14.3](https://github.com/pattern-lab/edition-node-gulp/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.14.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.14.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.14.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.13.3](https://github.com/pattern-lab/edition-node-gulp/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.13.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.13.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.13.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.12.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.11.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.10.2...v5.11.1) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.11.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.10.2...v5.11.0) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.10.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.10.1...v5.10.2) (2020-05-24) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.10.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.10.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/edition-node-gulp/issues/1192) ([420e829](https://github.com/pattern-lab/edition-node-gulp/commit/420e8293c033557ede073bc13e68955a450a3c8e)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/edition-node-gulp/issues/1192) ([b4eb12e](https://github.com/pattern-lab/edition-node-gulp/commit/b4eb12e68ceb402964a7e303610e5b0c008876ba)) + + + + + +## [5.9.3](https://github.com/pattern-lab/edition-node-gulp/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.9.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.9.1...v5.9.2) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.9.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.8.0...v5.9.0) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.7.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.7.1...v5.7.2) (2020-03-24) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.7.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.7.0...v5.7.1) (2020-02-24) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.7.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.6.0...v5.7.0) (2020-02-17) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.6.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.5.0...v5.6.0) (2020-01-18) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +# [5.5.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.4.2...v5.5.0) (2019-12-19) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.4.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.4.1...v5.4.2) (2019-11-27) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.4.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.4.0...v5.4.1) (2019-11-26) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.4.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.3.3...v5.4.0) (2019-11-26) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.3.3](https://github.com/pattern-lab/edition-node-gulp/compare/v5.3.2...v5.3.3) (2019-11-22) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +## [5.3.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.3.1...v5.3.2) (2019-11-14) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.3.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.3.0...v5.3.1) (2019-11-13) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.3.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.2.0...v5.3.0) (2019-11-13) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.2.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.1.0...v5.2.0) (2019-11-12) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +# [5.1.0](https://github.com/pattern-lab/edition-node-gulp/compare/v5.0.2...v5.1.0) (2019-10-29) + + +### Features + +* **core:** fix pattern export all conflicts ([b210d82](https://github.com/pattern-lab/edition-node-gulp/commit/b210d820ba8ac0b64c82c7ff0f18c9f8a900fce2)) + + + + + +## [5.0.2](https://github.com/pattern-lab/edition-node-gulp/compare/v5.0.1...v5.0.2) (2019-10-28) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +## [5.0.1](https://github.com/pattern-lab/edition-node-gulp/compare/v5.0.0...v5.0.1) (2019-10-28) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + +# [5.0.0](https://github.com/pattern-lab/edition-node-gulp/compare/v3.0.0-beta.3...v5.0.0) (2019-10-25) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +## [0.1.8](https://github.com/pattern-lab/edition-node-gulp/compare/@pattern-lab/engine-react-testing-tree@0.1.7...@pattern-lab/engine-react-testing-tree@0.1.8) (2019-10-14) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +## [0.1.7](https://github.com/pattern-lab/edition-node-gulp/compare/@pattern-lab/engine-react-testing-tree@0.1.6...@pattern-lab/engine-react-testing-tree@0.1.7) (2019-10-14) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +## [0.1.3](https://github.com/pattern-lab/edition-node-gulp/compare/@pattern-lab/engine-react-testing-tree@0.1.2...@pattern-lab/engine-react-testing-tree@0.1.3) (2019-08-23) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + + +## [0.1.2](https://github.com/pattern-lab/edition-node-gulp/compare/@pattern-lab/engine-react-testing-tree@0.1.2-alpha.0...@pattern-lab/engine-react-testing-tree@0.1.2) (2019-05-16) + +**Note:** Version bump only for package @pattern-lab/engine-react-testing-tree + + + + + ## [0.1.1-beta.1](https://github.com/pattern-lab/edition-node-gulp/compare/@pattern-lab/engine-react-testing-tree@0.1.1-alpha.4...@pattern-lab/engine-react-testing-tree@0.1.1-beta.1) (2019-02-09) diff --git a/packages/development-edition-engine-react/README.md b/packages/development-edition-engine-react/README.md index bdb531d95..2c21a20f4 100644 --- a/packages/development-edition-engine-react/README.md +++ b/packages/development-edition-engine-react/README.md @@ -11,4 +11,4 @@ This Development Edition is a variant of [Edition Node Gulp](https://github.com/ If you'd like to help with the React Engine, please reference the [contribution guidelines](https://github.com/pattern-lab/patternlab-node/blob/master/.github/CONTRIBUTING.md). -> Development Editions of Pattern Lab provide the ability to work on and commit changes to select packages within the overall Pattern Lab [ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). This Edition is NOT stable. +> Development Editions of Pattern Lab provide the ability to work on and commit changes to select packages within the overall Pattern Lab [ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). This Edition is NOT stable. diff --git a/packages/development-edition-engine-react/gulpfile.js b/packages/development-edition-engine-react/gulpfile.js index 8d8653659..3f3658f89 100644 --- a/packages/development-edition-engine-react/gulpfile.js +++ b/packages/development-edition-engine-react/gulpfile.js @@ -33,40 +33,36 @@ function serve() { }); } -gulp.task('patternlab:version', function() { +gulp.task('patternlab:version', function () { patternlab.version(); }); -gulp.task('patternlab:help', function() { +gulp.task('patternlab:help', function () { patternlab.help(); }); -gulp.task('patternlab:patternsonly', function() { +gulp.task('patternlab:patternsonly', function () { patternlab.patternsonly(config.cleanPublic); }); -gulp.task('patternlab:liststarterkits', function() { +gulp.task('patternlab:liststarterkits', function () { patternlab.liststarterkits(); }); -gulp.task('patternlab:loadstarterkit', function() { +gulp.task('patternlab:loadstarterkit', function () { patternlab.loadstarterkit(argv.kit, argv.clean); }); -gulp.task('patternlab:build', function() { +gulp.task('patternlab:build', function () { build().then(() => { // do something else when this promise resolves }); }); -gulp.task('patternlab:serve', function() { +gulp.task('patternlab:serve', function () { serve().then(() => { // do something else when this promise resolves }); }); -gulp.task('patternlab:installplugin', function() { - patternlab.installplugin(argv.plugin); -}); - gulp.task('default', ['patternlab:help']); diff --git a/packages/development-edition-engine-react/package.json b/packages/development-edition-engine-react/package.json index befc52d5e..ed5c6f21d 100644 --- a/packages/development-edition-engine-react/package.json +++ b/packages/development-edition-engine-react/package.json @@ -1,16 +1,16 @@ { "name": "@pattern-lab/engine-react-testing-tree", "description": "The tree of components we use to test, develop and validate the React engine", - "version": "0.1.2-alpha.0", + "version": "6.1.0", "private": true, "main": "gulpfile.js", "dependencies": { - "@pattern-lab/core": "^3.0.1-alpha.0", - "@pattern-lab/engine-mustache": "^2.0.1-alpha.0", - "@pattern-lab/engine-react": "^0.2.1-beta.1", - "@pattern-lab/uikit-workshop": "^1.0.1-alpha.0", - "gulp": "3.9.1", - "minimist": "^1.2.0", + "@pattern-lab/core": "^6.1.0", + "@pattern-lab/engine-mustache": "^6.1.0", + "@pattern-lab/engine-react": "^6.1.0", + "@pattern-lab/uikit-workshop": "^6.1.0", + "gulp": "4.0.2", + "minimist": "^1.2.5", "react": "16.2.0" }, "keywords": [ @@ -31,6 +31,6 @@ }, "license": "MIT", "engines": { - "node": ">=10.0" + "node": ">=16.20.0" } } diff --git a/packages/development-edition-engine-react/patternlab-config.json b/packages/development-edition-engine-react/patternlab-config.json index a50a29b60..23f8673e8 100644 --- a/packages/development-edition-engine-react/patternlab-config.json +++ b/packages/development-edition-engine-react/patternlab-config.json @@ -46,8 +46,8 @@ "./node_modules/@pattern-lab/uikit-workshop/views/partials/general-footer.mustache", "patternSection": "./node_modules/@pattern-lab/uikit-workshop/views/partials/patternSection.mustache", - "patternSectionSubtype": - "./node_modules/@pattern-lab/uikit-workshop/views/partials/patternSectionSubtype.mustache", + "patternSectionSubgroup": + "./node_modules/@pattern-lab/uikit-workshop/views/partials/patternSectionSubgroup.mustache", "viewall": "./node_modules/@pattern-lab/uikit-workshop/views/viewall.mustache" }, @@ -70,8 +70,13 @@ }, "patternExtension": "mustache", "patternStateCascade": ["inprogress", "inreview", "complete"], + "patternExportAll": false, + "patternExportPreserveDirectoryStructure": false, + "patternExportRaw": false, "patternExportDirectory": "./pattern_exports/", "patternExportPatternPartials": [], + "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, "serverOptions": { "wait": 1000 }, @@ -82,5 +87,13 @@ "color": "dark", "density": "compact", "layout": "horizontal" + }, + "engines": { + "react": { + "package": "@pattern-lab/engine-react", + "fileExtensions": [ + "jsx" + ] + } } } diff --git a/packages/development-edition-engine-react/source/_annotations/README.md b/packages/development-edition-engine-react/source/_annotations/README.md index 42592a09b..b67b5511f 100644 --- a/packages/development-edition-engine-react/source/_annotations/README.md +++ b/packages/development-edition-engine-react/source/_annotations/README.md @@ -1,5 +1,5 @@ This is the default location to place annotations. -Pattern Lab uses annotations defined here to markup the UI. Read more about [annotations](http://patternlab.io/docs/pattern-adding-annotations.html). +Pattern Lab uses annotations defined here to markup the UI. Read more about [annotations](https://patternlab.io/docs/adding-annotations/). If you wish to rename this directory, make sure you update the `paths.source.annotations` property within `patternlab-config.json`. diff --git a/packages/development-edition-engine-react/source/_data/README.md b/packages/development-edition-engine-react/source/_data/README.md index 3b9ea1ea4..50589abc7 100644 --- a/packages/development-edition-engine-react/source/_data/README.md +++ b/packages/development-edition-engine-react/source/_data/README.md @@ -1,5 +1,5 @@ This is the default location to place global data files. -Pattern Lab uses data defined here as the global fallback if a template does not provide its own data. Read more about [data](http://patternlab.io/docs/data-overview.html). +Pattern Lab uses data defined here as the global fallback if a template does not provide its own data. Read more about [data](https://patternlab.io/docs/overview-of-data/). If you wish to rename this directory, make sure you update the `paths.source.data` property within `patternlab-config.json`. diff --git a/packages/development-edition-engine-react/source/_meta/README.md b/packages/development-edition-engine-react/source/_meta/README.md index c6c8c3b8e..b5d2c4537 100644 --- a/packages/development-edition-engine-react/source/_meta/README.md +++ b/packages/development-edition-engine-react/source/_meta/README.md @@ -1,5 +1,5 @@ This is the default location to place meta files, otherwise known a pattern's header and footer. -Pattern Lab builds each pattern while prepending and appending the header and footer. Read more about [pattern headers and footers](http://patternlab.io/docs/pattern-header-footer.html). +Pattern Lab builds each pattern while prepending and appending the header and footer. Read more about [pattern headers and footers](https://patternlab.io/docs/modifying-the-pattern-header-and-footer/). If you wish to rename this directory, make sure you update the `paths.source.meta` property within `patternlab-config.json`. diff --git a/packages/development-edition-engine-react/source/_meta/_00-head.html b/packages/development-edition-engine-react/source/_meta/_00-head.html deleted file mode 100644 index cf826617a..000000000 --- a/packages/development-edition-engine-react/source/_meta/_00-head.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - {{ title }} - - - - - - - - {{{ patternLabHead }}} - - - - diff --git a/packages/development-edition-engine-react/source/_meta/_00-head.mustache b/packages/development-edition-engine-react/source/_meta/_00-head.mustache deleted file mode 100644 index 069727248..000000000 --- a/packages/development-edition-engine-react/source/_meta/_00-head.mustache +++ /dev/null @@ -1,17 +0,0 @@ - - - - {{ title }} - - - - - - - - {{{ patternLabHead }}} - - - - - diff --git a/packages/development-edition-engine-react/source/_meta/_01-foot.html b/packages/development-edition-engine-react/source/_meta/_01-foot.html deleted file mode 100644 index 2feb91336..000000000 --- a/packages/development-edition-engine-react/source/_meta/_01-foot.html +++ /dev/null @@ -1,6 +0,0 @@ - - -{{{ patternLabFoot }}} - - - diff --git a/packages/development-edition-engine-handlebars/source/_meta/_01-foot.mustache b/packages/development-edition-engine-react/source/_meta/_foot.hbs similarity index 100% rename from packages/development-edition-engine-handlebars/source/_meta/_01-foot.mustache rename to packages/development-edition-engine-react/source/_meta/_foot.hbs diff --git a/packages/edition-node/source/_meta/_01-foot.mustache b/packages/development-edition-engine-react/source/_meta/_foot.html similarity index 100% rename from packages/edition-node/source/_meta/_01-foot.mustache rename to packages/development-edition-engine-react/source/_meta/_foot.html diff --git a/packages/development-edition-engine-react/source/_meta/_01-foot.mustache b/packages/development-edition-engine-react/source/_meta/_foot.mustache similarity index 100% rename from packages/development-edition-engine-react/source/_meta/_01-foot.mustache rename to packages/development-edition-engine-react/source/_meta/_foot.mustache diff --git a/packages/development-edition-engine-handlebars/source/_meta/_00-head.mustache b/packages/development-edition-engine-react/source/_meta/_head.hbs similarity index 87% rename from packages/development-edition-engine-handlebars/source/_meta/_00-head.mustache rename to packages/development-edition-engine-react/source/_meta/_head.hbs index 45ce3bb7d..893481ae5 100644 --- a/packages/development-edition-engine-handlebars/source/_meta/_00-head.mustache +++ b/packages/development-edition-engine-react/source/_meta/_head.hbs @@ -1,8 +1,8 @@ - + {{ title }} - + @@ -14,4 +14,3 @@ - diff --git a/packages/development-edition-engine-react/source/_meta/_head.html b/packages/development-edition-engine-react/source/_meta/_head.html new file mode 100644 index 000000000..9e3094352 --- /dev/null +++ b/packages/development-edition-engine-react/source/_meta/_head.html @@ -0,0 +1,23 @@ + + + + {{ title }} + + + + + + + + {{{ patternLabHead }}} + + + diff --git a/packages/development-edition-engine-react/source/_meta/_head.mustache b/packages/development-edition-engine-react/source/_meta/_head.mustache new file mode 100644 index 000000000..5921e94cf --- /dev/null +++ b/packages/development-edition-engine-react/source/_meta/_head.mustache @@ -0,0 +1,17 @@ + + + + {{ title }} + + + + + + + + {{{ patternLabHead }}} + + + + + diff --git a/packages/development-edition-engine-react/source/_patterns/README.md b/packages/development-edition-engine-react/source/_patterns/README.md index 2f89266bf..8751c8669 100644 --- a/packages/development-edition-engine-react/source/_patterns/README.md +++ b/packages/development-edition-engine-react/source/_patterns/README.md @@ -1,5 +1,5 @@ This is the default location to place pattern files. -Pattern Lab builds patterns and the ui from the structure defined within. Read more about [pattern organization](http://patternlab.io/docs/pattern-organization.html). +Pattern Lab builds patterns and the ui from the structure defined within. Read more about [pattern organization](https://patternlab.io/docs/overview-of-patterns/). If you wish to rename this directory, make sure you update the `paths.source.patterns` property within `patternlab-config.json`. diff --git a/packages/development-edition-engine-react/source/_patterns/00-atoms/00-general/HelloWorld.jsx b/packages/development-edition-engine-react/source/_patterns/atoms/general/HelloWorld.jsx similarity index 100% rename from packages/development-edition-engine-react/source/_patterns/00-atoms/00-general/HelloWorld.jsx rename to packages/development-edition-engine-react/source/_patterns/atoms/general/HelloWorld.jsx diff --git a/packages/development-edition-engine-react/source/_patterns/01-molecules/00-general/HelloIncluder.jsx b/packages/development-edition-engine-react/source/_patterns/molecules/general/HelloIncluder.jsx similarity index 89% rename from packages/development-edition-engine-react/source/_patterns/01-molecules/00-general/HelloIncluder.jsx rename to packages/development-edition-engine-react/source/_patterns/molecules/general/HelloIncluder.jsx index 6b2f3c985..162681281 100644 --- a/packages/development-edition-engine-react/source/_patterns/01-molecules/00-general/HelloIncluder.jsx +++ b/packages/development-edition-engine-react/source/_patterns/molecules/general/HelloIncluder.jsx @@ -1,6 +1,6 @@ import React, { Component } from 'react'; -import HelloWorld from '../../00-atoms/00-general/HelloWorld'; +import HelloWorld from '../../atoms/general/HelloWorld'; // const HelloWorld = () => ( //
diff --git a/packages/development-edition-engine-twig/.gitignore b/packages/development-edition-engine-twig/.gitignore new file mode 100644 index 000000000..0679bd2b5 --- /dev/null +++ b/packages/development-edition-engine-twig/.gitignore @@ -0,0 +1,9 @@ +node_modules/ +.DS_Store +patternlab.json +.sass-cache/* +/sass-cache +Thumbs.db +.idea/ +public +dependencyGraph.json diff --git a/packages/development-edition-engine-twig/CHANGELOG.md b/packages/development-edition-engine-twig/CHANGELOG.md new file mode 100644 index 000000000..86702f2f3 --- /dev/null +++ b/packages/development-edition-engine-twig/CHANGELOG.md @@ -0,0 +1,310 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [6.1.0](https://github.com/pattern-lab/patternlab-node/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [6.0.3](https://github.com/pattern-lab/patternlab-node/compare/v6.0.2...v6.0.3) (2023-03-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [6.0.2](https://github.com/pattern-lab/patternlab-node/compare/v6.0.1...v6.0.2) (2023-02-26) + + +### Bug Fixes + +* **starterkit-twig-demo:** pages not rendering pattern-specific data from json ([#1490](https://github.com/pattern-lab/patternlab-node/issues/1490)) ([1c878df](https://github.com/pattern-lab/patternlab-node/commit/1c878dfa35d549f23e199b3e235ff79cb471ac86)), closes [#1486](https://github.com/pattern-lab/patternlab-node/issues/1486) + + + + + +## [6.0.1](https://github.com/pattern-lab/patternlab-node/compare/v6.0.0...v6.0.1) (2023-02-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [6.0.0](https://github.com/pattern-lab/patternlab-node/compare/v5.17.0...v6.0.0) (2023-01-31) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.17.0](https://github.com/pattern-lab/patternlab-node/compare/v5.16.4...v5.17.0) (2022-09-25) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.16.4](https://github.com/pattern-lab/patternlab-node/compare/v5.16.2...v5.16.4) (2022-09-23) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.16.2](https://github.com/pattern-lab/patternlab-node/compare/v5.16.1...v5.16.2) (2022-02-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.16.1](https://github.com/pattern-lab/patternlab-node/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.16.0](https://github.com/pattern-lab/patternlab-node/compare/v5.15.7...v5.16.0) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.7](https://github.com/pattern-lab/patternlab-node/compare/v5.15.6...v5.15.7) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.6](https://github.com/pattern-lab/patternlab-node/compare/v5.15.5...v5.15.6) (2021-12-07) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.5](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.5) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.4](https://github.com/pattern-lab/patternlab-node/compare/v5.15.3...v5.15.4) (2021-12-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.3](https://github.com/pattern-lab/patternlab-node/compare/v5.15.2...v5.15.3) (2021-11-21) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.15.2](https://github.com/pattern-lab/patternlab-node/compare/v5.15.1...v5.15.2) (2021-11-03) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +## [5.15.1](https://github.com/pattern-lab/patternlab-node/compare/v5.15.0...v5.15.1) (2021-10-16) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.15.0](https://github.com/pattern-lab/patternlab-node/compare/v5.14.3...v5.15.0) (2021-07-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +## [5.14.3](https://github.com/pattern-lab/patternlab-node/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +## [5.14.2](https://github.com/pattern-lab/patternlab-node/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.14.1](https://github.com/pattern-lab/patternlab-node/compare/v5.14.0...v5.14.1) (2021-02-19) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +# [5.14.0](https://github.com/pattern-lab/patternlab-node/compare/v5.13.3...v5.14.0) (2021-01-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +## [5.13.3](https://github.com/pattern-lab/patternlab-node/compare/v5.13.2...v5.13.3) (2020-12-17) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.13.2](https://github.com/pattern-lab/patternlab-node/compare/v5.13.1...v5.13.2) (2020-11-12) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +## [5.13.1](https://github.com/pattern-lab/patternlab-node/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +# [5.13.0](https://github.com/pattern-lab/patternlab-node/compare/v5.12.0...v5.13.0) (2020-08-26) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + + +# [5.12.0](https://github.com/pattern-lab/patternlab-node/compare/v5.11.1...v5.12.0) (2020-08-09) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.11.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.1) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.11.0](https://github.com/pattern-lab/patternlab-node/compare/v5.10.2...v5.11.0) (2020-06-28) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.10.2](https://github.com/pattern-lab/patternlab-node/compare/v5.10.1...v5.10.2) (2020-05-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.10.1](https://github.com/pattern-lab/patternlab-node/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.10.0](https://github.com/pattern-lab/patternlab-node/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** resolving broken links in new docs site [#1192](https://github.com/pattern-lab/patternlab-node/issues/1192) ([b4eb12e](https://github.com/pattern-lab/patternlab-node/commit/b4eb12e68ceb402964a7e303610e5b0c008876ba)) + + + + + +## [5.9.3](https://github.com/pattern-lab/patternlab-node/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.9.2](https://github.com/pattern-lab/patternlab-node/compare/v5.9.1...v5.9.2) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +## [5.9.1](https://github.com/pattern-lab/patternlab-node/compare/v5.9.0...v5.9.1) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.9.0](https://github.com/pattern-lab/patternlab-node/compare/v5.8.0...v5.9.0) (2020-04-24) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig + + + + + +# [5.8.0](https://github.com/pattern-lab/patternlab-node/compare/v5.7.2...v5.8.0) (2020-04-03) + +**Note:** Version bump only for package @pattern-lab/development-edition-engine-twig diff --git a/packages/development-edition-engine-twig/README.md b/packages/development-edition-engine-twig/README.md new file mode 100644 index 000000000..b3ffdea7f --- /dev/null +++ b/packages/development-edition-engine-twig/README.md @@ -0,0 +1,25 @@ +![Pattern Lab Logo](/patternlab.png "Pattern Lab Logo") + +# Pattern Lab Node - Development Edition Engine Twig + +_here be dragons_ + +This Development Edition is a variant of [Edition Node](https://github.com/pattern-lab/patternlab-node/tree/master/packages/edition-node) for convience purposes only, loaded with the Twig Engine. The goals of this Development Edition are two-fold: + +* Develop the [Twig Engine](https://github.com/pattern-lab/patternlab-node/tree/master/packages/engine-twig) +* Build and test against Twig pattern tree + +> Development Editions of Pattern Lab provide the ability to work on and commit changes to select packages within the overall Pattern Lab [ecosystem](https://patternlab.io/docs/overview-of-pattern-lab's-ecosystem/). This Edition is NOT stable. + + +## Working on Pattern Lab's UI Locally + +### Step 1: Install Dependencies +Run the following in the root of the Pattern Lab repo: + +``` +yarn run setup +``` + +### Step 2 +Finally, go back into this folder, `cd packages/development-edition-engine-twig`, and start up the local dev server which watches UIKit and the local Pattern Lab instance for changes, live reloads, etc by running `yarn dev` diff --git a/packages/development-edition-engine-twig/package.json b/packages/development-edition-engine-twig/package.json new file mode 100644 index 000000000..7b8010f68 --- /dev/null +++ b/packages/development-edition-engine-twig/package.json @@ -0,0 +1,44 @@ +{ + "name": "@pattern-lab/development-edition-engine-twig", + "private": true, + "version": "6.1.0", + "description": "The tree of components we use to test, develop and validate the twig engine (not engine-twig-php)", + "scripts": { + "postbootstrap": "patternlab install --starterkits @pattern-lab/starterkit-twig-demo", + "pl:build": "patternlab build --config ./patternlab-config.json", + "pl:debug": "node --inspect-brk=24984 node_modules/.bin/patternlab build --config ./patternlab-config.json", + "pl:help": "patternlab --help", + "pl:install": "patternlab install --config ./patternlab-config.json", + "pl:serve": "patternlab serve --config ./patternlab-config.json", + "pl:version": "patternlab --version", + "dev": "node ./node_modules/@pattern-lab/uikit-workshop/build-tools.js" + }, + "keywords": [ + "Pattern Lab", + "Atomic Web Design", + "Node", + "Twig", + "Edition" + ], + "author": "Ringo De Smet", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/pattern-lab/patternlab-node.git" + }, + "engines": { + "node": ">=16.20.0" + }, + "dependencies": { + "@pattern-lab/cli": "^6.1.0", + "@pattern-lab/core": "^6.1.0", + "@pattern-lab/engine-twig": "^6.1.0", + "@pattern-lab/starterkit-twig-demo": "^6.1.0", + "@pattern-lab/uikit-workshop": "^6.1.0" + }, + "workspaces": { + "nohoist": [ + "**/@pattern-lab/starterkit-twig-demo" + ] + } +} diff --git a/packages/development-edition-engine-twig/patternlab-config.json b/packages/development-edition-engine-twig/patternlab-config.json new file mode 100644 index 000000000..c50ccbcda --- /dev/null +++ b/packages/development-edition-engine-twig/patternlab-config.json @@ -0,0 +1,121 @@ +{ + "cacheBust": true, + "cleanPublic": true, + "defaultPattern": "all", + "defaultShowPatternInfo": false, + "ishControlsHide": { + "s": false, + "m": false, + "l": false, + "full": false, + "random": false, + "disco": false, + "hay": true, + "mqs": false, + "find": false, + "views-all": false, + "views-annotations": false, + "views-code": false, + "views-new": false, + "tools-all": false, + "tools-docs": false + }, + "ishViewportRange": { + "s": [ + 240, + 500 + ], + "m": [ + 500, + 800 + ], + "l": [ + 800, + 2600 + ] + }, + "logLevel": "info", + "outputFileSuffixes": { + "rendered": ".rendered", + "rawTemplate": "", + "markupOnly": ".markup-only" + }, + "paths": { + "source": { + "root": "source/", + "patterns": "source/_patterns/", + "data": "source/_data/", + "meta": "source/_meta/", + "annotations": "source/_annotations/", + "styleguide": "dist/", + "patternlabFiles": { + "general-header": "views/partials/general-header.mustache", + "general-footer": "views/partials/general-footer.mustache", + "patternSection": "views/partials/patternSection.mustache", + "patternSectionSubgroup": "views/partials/patternSectionSubgroup.mustache", + "viewall": "views/viewall.mustache" + }, + "js": "source/js", + "images": "source/images", + "fonts": "source/fonts", + "css": "source/css" + }, + "public": { + "root": "public/", + "patterns": "public/patterns/", + "data": "public/styleguide/data/", + "annotations": "public/annotations/", + "styleguide": "public/styleguide/", + "js": "public/js", + "images": "public/images", + "fonts": "public/fonts", + "css": "public/css" + } + }, + "patternExtension": "twig", + "patternStateCascade": [ + "inprogress", + "inreview", + "complete" + ], + "patternExportDirectory": "pattern_exports", + "patternExportPatternPartials": [], + "patternMergeVariantArrays": true, + "renderFlatPatternsOnViewAllPages": false, + "serverOptions": { + "wait": 1000 + }, + "starterkitSubDir": "dist", + "styleGuideExcludes": [], + "theme": { + "color": "dark", + "density": "compact", + "layout": "horizontal" + }, + "uikits": [ + { + "name": "uikit-workshop", + "package": "@pattern-lab/uikit-workshop", + "outputDir": "", + "enabled": true, + "excludedPatternStates": [], + "excludedTags": [] + } + ], + "engines": { + "twig": { + "package": "@pattern-lab/engine-twig", + "fileExtensions": [ + "twig" + ], + "namespaces": { + "atoms": "source/_patterns/atoms/", + "molecules": "source/_patterns/molecules/", + "organisms": "source/_patterns/organisms/", + "templates": "source/_patterns/templates/", + "pages": "source/_patterns/pages/", + "macros": "source/_patterns/macros/" + } + } + } +} diff --git a/packages/development-edition-engine-twig/source/.gitignore b/packages/development-edition-engine-twig/source/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/packages/development-edition-engine-twig/source/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/packages/docs/.eleventy.js b/packages/docs/.eleventy.js new file mode 100644 index 000000000..9e3b3a774 --- /dev/null +++ b/packages/docs/.eleventy.js @@ -0,0 +1,99 @@ +const rssPlugin = require('@11ty/eleventy-plugin-rss'); +const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight'); +const eleventyNavigationPlugin = require('@11ty/eleventy-navigation'); +const fs = require('fs'); + +// Import filters +const dateFilter = require('./src/filters/date-filter.js'); +const markdownFilter = require('./src/filters/markdown-filter.js'); +const w3DateFilter = require('./src/filters/w3-date-filter.js'); + +// Import transforms +const htmlMinTransform = require('./src/transforms/html-min-transform.js'); +const parseTransform = require('./src/transforms/parse-transform.js'); + +// Import data files +const site = require('./src/_data/site.json'); + +module.exports = function (config) { + // Filters + config.addFilter('dateFilter', dateFilter); + config.addFilter('markdownFilter', markdownFilter); + config.addFilter('w3DateFilter', w3DateFilter); + + // Layout aliases + config.addLayoutAlias('home', 'layouts/home.njk'); + + // Transforms + config.addTransform('htmlmin', htmlMinTransform); + config.addTransform('parse', parseTransform); + + // Passthrough copy + config.addPassthroughCopy('src/images'); + config.addPassthroughCopy('src/js'); + config.addPassthroughCopy('src/admin/config.yml'); + config.addPassthroughCopy('src/admin/previews.js'); + config.addPassthroughCopy({ + '../../node_modules/nunjucks/browser/nunjucks-slim.js': + 'node_modules/nunjucks/browser/nunjucks-slim.js', + }); + + const now = new Date(); + + // Custom collections + const livePosts = (post) => post.date <= now && !post.data.draft; + config.addCollection('posts', (collection) => { + return [ + ...collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts), + ].reverse(); + }); + + config.addCollection('demos', (collection) => { + return [...collection.getFilteredByGlob('./src/demos/*.md')].reverse(); + }); + + config.addCollection('postFeed', (collection) => { + return [...collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts)] + .reverse() + .slice(0, site.maxPostsPerPage); + }); + + config.addCollection('docs', (collection) => { + return [...collection.getFilteredByGlob('./src/docs/*.md')].reverse(); + }); + + config.addCollection('docsOrdered', (collection) => { + const docs = collection.getFilteredByGlob('src/docs/*.md').sort((a, b) => { + return Number(a.data.order) - Number(b.data.order); + }); + return docs; + }); + + // Plugins + config.addPlugin(rssPlugin); + config.addPlugin(syntaxHighlight); + config.addPlugin(eleventyNavigationPlugin); + + // 404 + config.setBrowserSyncConfig({ + callbacks: { + ready: function (err, browserSync) { + const content_404 = fs.readFileSync('dist/404.html'); + + browserSync.addMiddleware('*', (req, res) => { + // Provides the 404 content without redirect. + res.write(content_404); + res.end(); + }); + }, + }, + }); + + return { + dir: { + input: 'src', + output: 'dist', + }, + passthroughFileCopy: true, + }; +}; diff --git a/packages/docs/.gitignore b/packages/docs/.gitignore new file mode 100644 index 000000000..a54bbf4b4 --- /dev/null +++ b/packages/docs/.gitignore @@ -0,0 +1,17 @@ +*.log +npm-debug.* +*.scssc +*.log +*.swp +.DS_Store +.sass-cache +node_modules +dist + +# Specifics + +# Hide design tokens +src/scss/_tokens.scss + +# Hide compiled CSS +src/_includes/assets/* diff --git a/packages/docs/.prettierrc b/packages/docs/.prettierrc new file mode 100644 index 000000000..fc46c20b4 --- /dev/null +++ b/packages/docs/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 90, + "useTabs": false, + "tabWidth": 3, + "singleQuote": true, + "bracketSpacing": false +} diff --git a/packages/docs/.vscode/launch.json b/packages/docs/.vscode/launch.json new file mode 100644 index 000000000..2359da6e9 --- /dev/null +++ b/packages/docs/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/index.js" + } + ] +} \ No newline at end of file diff --git a/packages/docs/CHANGELOG.md b/packages/docs/CHANGELOG.md new file mode 100644 index 000000000..97fdd21e5 --- /dev/null +++ b/packages/docs/CHANGELOG.md @@ -0,0 +1,182 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [6.1.0](https://github.com/bradfrost/pl-website-eleventy/compare/v6.0.3...v6.1.0) (2023-12-21) + +**Note:** Version bump only for package @pattern-lab/website + + + + + +# [6.0.0](https://github.com/bradfrost/pl-website-eleventy/compare/v5.17.0...v6.0.0) (2023-01-31) + + +### Features + +* activate prettier for scss ([#1468](https://github.com/bradfrost/pl-website-eleventy/issues/1468)) ([fac6ad4](https://github.com/bradfrost/pl-website-eleventy/commit/fac6ad4be48c95eccfe890a280cad441ee84f677)) +* **docs:** added plugin ([#1469](https://github.com/bradfrost/pl-website-eleventy/issues/1469)) ([535c5f0](https://github.com/bradfrost/pl-website-eleventy/commit/535c5f0805936a25eeddde0e360cb6000c000b1b)) + + + + + +## [5.16.4](https://github.com/bradfrost/pl-website-eleventy/compare/v5.16.2...v5.16.4) (2022-09-23) + + +### Bug Fixes + +* code scanning alert ([#1442](https://github.com/bradfrost/pl-website-eleventy/issues/1442)) ([749a3e7](https://github.com/bradfrost/pl-website-eleventy/commit/749a3e722249846c522e3f7de6e73b5afa8531b1)) + + + + + +## [5.16.1](https://github.com/bradfrost/pl-website-eleventy/compare/v5.16.0...v5.16.1) (2022-01-29) + +**Note:** Version bump only for package @pattern-lab/website + + + + + +## [5.15.5](https://github.com/bradfrost/pl-website-eleventy/compare/v5.15.3...v5.15.5) (2021-12-06) + + +### Features + +* define initial viewport ([#1386](https://github.com/bradfrost/pl-website-eleventy/issues/1386)) ([6fa630e](https://github.com/bradfrost/pl-website-eleventy/commit/6fa630e2353ed68295550e59c31148269f3b7cd0)) + + + + + +## [5.15.4](https://github.com/bradfrost/pl-website-eleventy/compare/v5.15.3...v5.15.4) (2021-12-06) + + +### Features + +* define initial viewport ([#1386](https://github.com/bradfrost/pl-website-eleventy/issues/1386)) ([6fa630e](https://github.com/bradfrost/pl-website-eleventy/commit/6fa630e2353ed68295550e59c31148269f3b7cd0)) + + + + + +## [5.15.3](https://github.com/bradfrost/pl-website-eleventy/compare/v5.15.2...v5.15.3) (2021-11-21) + + +### Bug Fixes + +* **docs:** tiles z-index to not overlay the menu anymore ([#1370](https://github.com/bradfrost/pl-website-eleventy/issues/1370)) ([384dc89](https://github.com/bradfrost/pl-website-eleventy/commit/384dc8900ee5768f5a260fd00fe03d11ae047484)) + + + + + +# [5.15.0](https://github.com/bradfrost/pl-website-eleventy/compare/v5.14.3...v5.15.0) (2021-07-01) + + +### Features + +* **docs:** adding a sitemap.xml ([#1329](https://github.com/bradfrost/pl-website-eleventy/issues/1329)) ([0a7fd95](https://github.com/bradfrost/pl-website-eleventy/commit/0a7fd95d5f1c3ce690bbe89cc30580ff58d1ab9c)) +* **documentation:** added (sub)groups documentation again [#1262](https://github.com/bradfrost/pl-website-eleventy/issues/1262) ([#1334](https://github.com/bradfrost/pl-website-eleventy/issues/1334)) ([9fac269](https://github.com/bradfrost/pl-website-eleventy/commit/9fac2699d2f6c64c4544e8e4d8e18c1a1ce7e49f)) + + + + + + +## [5.14.3](https://github.com/bradfrost/pl-website-eleventy/compare/v5.14.2...v5.14.3) (2021-05-17) + +**Note:** Version bump only for package @pattern-lab/website + + + + + + +## [5.14.2](https://github.com/bradfrost/pl-website-eleventy/compare/v5.14.1...v5.14.2) (2021-03-28) + +**Note:** Version bump only for package @pattern-lab/website + + + + + + +## [5.13.1](https://github.com/bradfrost/pl-website-eleventy/compare/v5.13.0...v5.13.1) (2020-09-06) + +**Note:** Version bump only for package @pattern-lab/website + + + + + + +## [5.11.1](https://github.com/bradfrost/pl-website-eleventy/compare/v5.10.2...v5.11.1) (2020-06-28) + + +### Bug Fixes + +* **docs:** fixed css code for custom patternstates color ([8995241](https://github.com/bradfrost/pl-website-eleventy/commit/89952416162c01d1e3e05221ce58a7755544131c)), closes [#1216](https://github.com/bradfrost/pl-website-eleventy/issues/1216) +* **docs:** headlines styling breaks in edge cases [#1158](https://github.com/bradfrost/pl-website-eleventy/issues/1158) ([d8244a2](https://github.com/bradfrost/pl-website-eleventy/commit/d8244a2d307b0a81d0846491f8c5a12e0ae167a5)) + + + + + +# [5.11.0](https://github.com/bradfrost/pl-website-eleventy/compare/v5.10.2...v5.11.0) (2020-06-28) + + +### Bug Fixes + +* **docs:** fixed css code for custom patternstates color ([8995241](https://github.com/bradfrost/pl-website-eleventy/commit/89952416162c01d1e3e05221ce58a7755544131c)), closes [#1216](https://github.com/bradfrost/pl-website-eleventy/issues/1216) +* **docs:** headlines styling breaks in edge cases [#1158](https://github.com/bradfrost/pl-website-eleventy/issues/1158) ([d8244a2](https://github.com/bradfrost/pl-website-eleventy/commit/d8244a2d307b0a81d0846491f8c5a12e0ae167a5)) + + + + + +## [5.10.1](https://github.com/bradfrost/pl-website-eleventy/compare/v5.10.0...v5.10.1) (2020-05-09) + +**Note:** Version bump only for package @pattern-lab/website + + + + + +# [5.10.0](https://github.com/bradfrost/pl-website-eleventy/compare/v5.9.3...v5.10.0) (2020-05-09) + + +### Bug Fixes + +* **docs:** google lighthouse error - bg and text contrast ratio [#1197](https://github.com/bradfrost/pl-website-eleventy/issues/1197) ([f43978a](https://github.com/bradfrost/pl-website-eleventy/commit/f43978a3a121b661cfbf763ba72bcda2c36a5d3a)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([8dc020a](https://github.com/bradfrost/pl-website-eleventy/commit/8dc020a217b51cfafdd62ceca95fc42811a6c285)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([f557fdd](https://github.com/bradfrost/pl-website-eleventy/commit/f557fddeda640d88c7267d9d5fba8e8cc5e07929)) +* **docs:** resolving broken link (new URL) in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([0023a91](https://github.com/bradfrost/pl-website-eleventy/commit/0023a910126a635006c1ad468a412af0e93338fb)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([c9635ec](https://github.com/bradfrost/pl-website-eleventy/commit/c9635ec2d9eb700b23188d5c72b83b3d16e6deda)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([f56ad39](https://github.com/bradfrost/pl-website-eleventy/commit/f56ad3951ea0319a43f0b1aeabba0d3ad96c5553)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([cae9420](https://github.com/bradfrost/pl-website-eleventy/commit/cae94208c52e4068430e048e729f4ff97847715a)) +* **docs:** resolving broken links in new docs site [#1192](https://github.com/bradfrost/pl-website-eleventy/issues/1192) ([84138c3](https://github.com/bradfrost/pl-website-eleventy/commit/84138c36cdfe5b9a38b34e32b177a0416b077716)) +* Contribution guidelines should refer to yarn ([c30cc81](https://github.com/bradfrost/pl-website-eleventy/commit/c30cc81a3e155072774438304b73d58b6635876d)) + + + + + +## [5.9.3](https://github.com/bradfrost/pl-website-eleventy/compare/v5.9.2...v5.9.3) (2020-05-01) + +**Note:** Version bump only for package patternlab-website + + + + + +# [5.9.0](https://github.com/bradfrost/pl-website-eleventy/compare/v5.8.0...v5.9.0) (2020-04-24) + + +### Features + +* **docs:** yarnify ([5a47dc7](https://github.com/bradfrost/pl-website-eleventy/commit/5a47dc7b90dc5c43c12a51143b41943dcbd8564c)) diff --git a/packages/docs/LICENSE.txt b/packages/docs/LICENSE.txt new file mode 100644 index 000000000..312f7109c --- /dev/null +++ b/packages/docs/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 andy-bell.design and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/docs/README.md b/packages/docs/README.md new file mode 100644 index 000000000..7b191158a --- /dev/null +++ b/packages/docs/README.md @@ -0,0 +1,32 @@ +# Pattern Lab Website + +This is the website for patternlab.io. This site was build using the [Hylia starter kit](https://hylia.website/), which is a lightweight [Eleventy](https://11ty.io) starter kit. + +--- + +## How to work with this project + +1. Clone this repository +2. `cd` into the project directory and run `yarn` +3. Once all the dependencies are installed run `yarn start` +4. Open your browser at `http://localhost:8080` + +## Terminal commands + +### Serve the site locally + +```bash +yarn start +``` + +### Build a production version of the site + +```bash +yarn production +``` + +### Compile Sass + +```bash +yarn sass:process +``` diff --git a/packages/docs/package.json b/packages/docs/package.json new file mode 100644 index 000000000..84613c39f --- /dev/null +++ b/packages/docs/package.json @@ -0,0 +1,60 @@ +{ + "name": "@pattern-lab/website", + "version": "6.1.0", + "description": "The website for patternlab.io", + "main": "index.js", + "dependencies": { + "@11ty/eleventy": "^0.12.1", + "@11ty/eleventy-plugin-rss": "^1.1.2", + "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.3", + "@tbranyen/jsdom": "^13.0.0", + "concurrently": "^4.1.0", + "html-minifier": "^4.0.0", + "json-to-scss": "^1.6.2", + "nunjucks": "^3.2.3", + "sass": "^1.32.8", + "semver": "^6.3.0", + "slugify": "^1.5.0", + "stalfos": "github:hankchizljaw/stalfos#c8971d22726326cfc04089b2da4d51eeb1ebb0eb" + }, + "devDependencies": { + "@11ty/eleventy-navigation": "^0.3.2", + "@erquhart/rollup-plugin-node-builtins": "^2.1.5", + "bl": "^3.0.0", + "chokidar-cli": "^2.1.0", + "cross-env": "^5.2.0", + "make-dir-cli": "^2.0.0", + "prettier": "^2.8.1", + "rollup": "^1.16.1", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.0.3" + }, + "scripts": { + "sass:tokens": "npx json-to-scss src/_data/tokens.json src/scss/_tokens.scss", + "sass:process": "yarn sass:tokens && sass src/scss/style.scss dist/css/style.css --style=compressed", + "cms:precompile": "make-dir dist/admin && nunjucks-precompile src/_includes > dist/admin/templates.js -i \"\\.(njk|css|svg)$\"", + "cms:bundle": "rollup --config", + "start": "concurrently \"yarn sass:process --watch\" \"yarn cms:bundle --watch\" \"chokidar \\\"src/_includes/**\\\" -c \\\"yarn cms:precompile\\\"\" \"yarn serve\"", + "serve": "cross-env ELEVENTY_ENV=development npx eleventy --serve", + "production": "yarn sass:process && yarn cms:precompile && yarn cms:bundle && npx eleventy" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bradfrost/pl-website-eleventy.git" + }, + "keywords": [], + "author": "", + "license": "MIT", + "bugs": { + "url": "https://github.com/bradfrost/pl-website-eleventy/issues" + }, + "publishConfig": { + "access": "public" + }, + "homepage": "https://github.com/bradfrost/pl-website-eleventy/#readme", + "gitHead": "80f62be442223e09bafb30d0529cbd768e03f2ac", + "engines": { + "node": ">=16.20.0" + } +} diff --git a/packages/docs/php-docs/advanced-auto-regenerate.md b/packages/docs/php-docs/advanced-auto-regenerate.md new file mode 100644 index 000000000..fc6985825 --- /dev/null +++ b/packages/docs/php-docs/advanced-auto-regenerate.md @@ -0,0 +1,55 @@ +--- +title: Watching for Changes and Auto Regenerating Patterns +tags: + - docs +--- + +Pattern Lab can watch for changes to files in `./source/` and automatically rebuild the entire Pattern Lab website for you. Make your changes, save the file, and Pattern Lab takes care of the rest. + +## How to Start Watching for Changes + +To start watching for changes do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --watch` + +To stop watching files use `CTRL+C` in the same terminal window. + +### Only Watch for Changes to Pattern Lab Files + +If you use a task runner like Gulp or Grunt to compile Sass, JavaScript or images you may want Pattern Lab to only concern itself with its own files. To limit Pattern Lab to watch and move only its files do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --watch --patternsonly` + +Or, better yet, use this command within your Gulp or Grunt script. + +### Start the Web Server & Watch for Changes at the Same Time + +If you're relying on Pattern Lab's server to view your content you'll want to run the watch and server with the same command. Do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --server --with-watch` + +You can also start the server and watch only patterns: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --server --with-watch --patternsonly` + +To stop the server and watching files use `CTRL+C` in the same terminal window. + +### Start the Web Server, Watch for Changes, and Reload the Browser at the Same Time + +The ultimate solution for working with Pattern Lab if you're not using a task runner is Pattern Lab's [Auto-Reload Plugin](https://github.com/pattern-lab/plugin-php-reload). Do the following: + +1. In a terminal window navigate to the root of your project +2. Install the [Auto-Reload Plugin](https://github.com/pattern-lab/plugin-php-reload) using `composer require pattern-lab/plugin-reload` +3. Type `php core/console --server --with-watch` + +The Auto-Reload Plugin is automatically enabled when you install it. You can always [disable the plugin](https://github.com/pattern-lab/plugin-php-reload#disabling-the-plugin) if you need to. + +To stop the server, watching files, and auto-reload service use `CTRL+C` in the same terminal window. + +## What Pattern Lab Will Watch + +By default, the PHP version of Pattern Lab will watch all files in `./source` except those that match the "ignore" configuration options in `config/config.yml`. When using `--patternsonly` Pattern Lab will only watch those directories in `./source` that start with an underscore. For example, `_patterns`. To learn how to modify what is ignored check out "[Managing Assets for a Pattern](/docs/pattern-managing-assets.html)". diff --git a/packages/docs/php-docs/advanced-clean-public.md b/packages/docs/php-docs/advanced-clean-public.md new file mode 100644 index 000000000..408e3ed37 --- /dev/null +++ b/packages/docs/php-docs/advanced-clean-public.md @@ -0,0 +1,5 @@ +--- +title: Stopping public/ from Being "Cleaned" +tags: + - docs +--- diff --git a/packages/docs/php-docs/advanced-config-options.md b/packages/docs/php-docs/advanced-config-options.md new file mode 100644 index 000000000..e21791b71 --- /dev/null +++ b/packages/docs/php-docs/advanced-config-options.md @@ -0,0 +1,7 @@ +--- +title: Editing the Configuration Options +tags: + - docs +--- + +Pattern Lab comes with a simple configuration file that allows you to modify certain aspects of the system. The configuration file can be found in `./config/config.yml`. diff --git a/packages/docs/php-docs/advanced-exporting-patterns.md b/packages/docs/php-docs/advanced-exporting-patterns.md new file mode 100644 index 000000000..49f4857d1 --- /dev/null +++ b/packages/docs/php-docs/advanced-exporting-patterns.md @@ -0,0 +1,17 @@ +--- +title: Exporting Patterns +tags: + - docs +--- + +Pattern Lab can export all of your patterns for you sans Pattern Lab's CSS and JavaScript. To export your patterns do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --export` + +If you require your patterns to be exported without your global header and footer (_e.g. to export a clean molecule_) do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --export --clean` + +In both cases the patterns will be exported to `./export/patterns`. The export directory is one of the many directories that can be [configured and changed](/docs/editing-source-files.html). diff --git a/packages/docs/php-docs/advanced-page-follow.md b/packages/docs/php-docs/advanced-page-follow.md new file mode 100644 index 000000000..3e38bebfc --- /dev/null +++ b/packages/docs/php-docs/advanced-page-follow.md @@ -0,0 +1,7 @@ +--- +title: Multi browser & Multi device Testing with Page Follow +tags: + - docs +--- + +An auto-reload service was built into Pattern Lab 1. With Pattern Lab 2 this feature has been removed. This feature may return as a plugin in the same way that the [Auto-Reload service](/docs/advanced-reload-browser.html) did. diff --git a/packages/docs/php-docs/advanced-pattern-lab-nav.md b/packages/docs/php-docs/advanced-pattern-lab-nav.md new file mode 100644 index 000000000..2bd2c28c5 --- /dev/null +++ b/packages/docs/php-docs/advanced-pattern-lab-nav.md @@ -0,0 +1,29 @@ +--- +title: Modifying Pattern Lab's Navigation +tags: + - docs +--- + +When sharing Pattern Lab with a client it may be beneficial to turn-off certain elements in the default navigation. To turn-off navigation elements do the following: + +1. Open `./config/config.yml` +2. Add the keys for the elements you'd like to hide to the `ishControlsHide` configuration option +3. Re-generate your Pattern Lab site + +The following keys are supported and will hide their respective elements: + +``` +s +m +l +full +random +disco +hay +find +views-new +tools-all +tools-docs +``` + +`hay` is disabled by default. diff --git a/packages/docs/php-docs/advanced-reload-browser.md b/packages/docs/php-docs/advanced-reload-browser.md new file mode 100644 index 000000000..4da045d5f --- /dev/null +++ b/packages/docs/php-docs/advanced-reload-browser.md @@ -0,0 +1,14 @@ +--- +title: Auto Reloading the Browser Window When Changes Are Made +tags: + - docs +--- + +An auto-reload service was built into Pattern Lab 1. With Pattern Lab 2 this feature has been turned into the [Auto-Reload Plugin](https://github.com/pattern-lab/plugin-php-reload). To install this plugin do the following: + +1. In a terminal window navigate to the root of your project +2. Type `composer require pattern-lab/plugin-reload` + +The Auto-Reload Plugin is automatically enabled when you install it. You can always [disable the plugin](https://github.com/pattern-lab/plugin-php-reload#disabling-the-plugin) if you need to. + +This service is enabled when using the `--watch` or `--server --with-watch` commands. Learn more about [watching for changes](/docs/advanced-auto-regenerate.html). diff --git a/packages/docs/php-docs/advanced-starterkits.md b/packages/docs/php-docs/advanced-starterkits.md new file mode 100644 index 000000000..5a90e0bdf --- /dev/null +++ b/packages/docs/php-docs/advanced-starterkits.md @@ -0,0 +1,21 @@ +--- +title: Starterkits +tags: + - docs +--- + +StarterKits can be installed via the following commands: + +``` +php core/console --starterkit --install [starterkit-name] +``` + +where [starterkit-name] is the name of the Starterkit. + +so... a complete example: + +``` +php core/console --starterkit --install pattern-lab/starterkit-mustache-demo +``` + +It is recommended that you do not install this StarterKit as a dependency for your Pattern Lab project via Composer. diff --git a/packages/docs/php-docs/changes-1-to-2.md b/packages/docs/php-docs/changes-1-to-2.md new file mode 100644 index 000000000..9b54e30be --- /dev/null +++ b/packages/docs/php-docs/changes-1-to-2.md @@ -0,0 +1,46 @@ +--- +title: Pattern Lab 1 to Pattern Lab 2 Changes +tags: + - docs +--- + +With Pattern Lab 2 in development for almost two years many under-the-hood changes have been implemented. For the most part a Pattern Lab 1 project should work with minimal changes in Pattern Lab 2. Here is a non-exhaustive list of new features in Pattern Lab 2: + +* complete rebuilding of core +* support for Composer +* support for more template languages (_currently Mustache and Twig_) +* support for StarterKits allowing separation of a team's unique needs from Pattern Lab proper +* event notification system, getters, setters, and a clean install process to allow for plugins +* redesigned and rebuilt modal view +* redesigned and rebuilt styleguide view +* multi-source directory support +* support for YAML in global data, pattern-specific data, and pseudo-patterns +* can have multiple JSON/YAML files in `./_data/` +* support for JSON/YAML linting to find errors +* can set multiple classes using the style modifier +* can use link.[pattern-name] within data to link to other patterns +* pattern parameters support simple lists +* pattern parameters act more like mustache (_but not exactly!_) +* patternParameters can over listItem loop numbers +* global pattern header and footer is now in `./source/_meta` +* upgraded console utility +* patterns and pattern subgroups can be documented in the styleguide by using `[pattern-name].md` or `[pattern-subgroup].md` +* view all pages for pattern sub-types +* annotations can be defined using Markdown +* patterns can be exported minus Pattern Lab mark-up +* can hide individual patterns from "view all" view still available via the nav +* can set a pattern to be the default pattern when loading Pattern Lab +* can turn on modal view by default +* implemented server +* sayings can now be defined in the config +* install process that makes it easier to install various components + +These are the features of Pattern Lab 1 that have become plugins: + +* Automatic Browser Reload + +These are the features of Pattern Lab 1 that have been removed in Pattern Lab 2: + +* QR Code Generator +* Page Follow +* MQs diff --git a/packages/docs/php-docs/command-line.md b/packages/docs/php-docs/command-line.md new file mode 100644 index 000000000..b92f4947b --- /dev/null +++ b/packages/docs/php-docs/command-line.md @@ -0,0 +1,22 @@ +--- +title: Using The Command Line Options +tags: + - docs +--- + +To use Pattern Lab you must use the command line interface. To view the available commands when using Pattern Lab do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --help` + +To get the options for a particular command, for example the `--generate` command, you can type: + + php core/console --help --generate + +## A Special Note About Windows + +To access the command prompt on Windows you can [follow the directions from Microsoft](https://support.microsoft.com/en-us/windows/powershell-is-replacing-command-prompt-fdb690cf-876c-d866-2124-21b6fb29a45f). After getting to the command prompt type the following to make sure you have PHP installed: + + php -v + +If you get an error and know that you've installed PHP you may need to [update your path variable so Windows can find PHP](http://willj.co/2012/10/run-wamp-php-windows-7-command-line/). diff --git a/packages/docs/php-docs/generating-pattern-lab.md b/packages/docs/php-docs/generating-pattern-lab.md new file mode 100644 index 000000000..b9831d371 --- /dev/null +++ b/packages/docs/php-docs/generating-pattern-lab.md @@ -0,0 +1,14 @@ +--- +title: Generating Pattern Lab +tags: + - docs +--- + +Pattern Lab consists of an empty shell when you first install it. To populate the public-facing side of Pattern Lab with your content and patterns do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --generate` + +Your Pattern Lab install should now be populated and [available for viewing](/docs/viewing-patterns.html). As you [make changes to your patterns](/docs/editing-source-files.html) you'll need re-generate your site using step 2 above. + +Manually re-generating your site after each change or collection of changes can be cumbersome. Pattern Lab can [watch files in the `./source/` directory for changes and re-generate the site automatically](/docs/advanced-auto-regenerate.html). The Pattern Lab website can also be [automatically reloaded](/docs/advanced-reload-browser.html). diff --git a/packages/docs/php-docs/installation.md b/packages/docs/php-docs/installation.md new file mode 100644 index 000000000..23b3ec3c4 --- /dev/null +++ b/packages/docs/php-docs/installation.md @@ -0,0 +1,5 @@ +--- +title: Installing Pattern Lab +tags: + - docs +--- diff --git a/packages/docs/php-docs/pattern-managing-assets.md b/packages/docs/php-docs/pattern-managing-assets.md new file mode 100644 index 000000000..1f6927cde --- /dev/null +++ b/packages/docs/php-docs/pattern-managing-assets.md @@ -0,0 +1,41 @@ +--- +title: Managing Pattern Assets +tags: + - docs +--- + +Assets for patterns - including JavaScript, CSS, and images - should be stored and edited in the `./source/` directory. Pattern Lab will move these assets to the `./public/` directory for you when you generate your site or when you watch the `./source/` directory for changes. **You can name and organize your assets however you like.** If you would like to use `./source/stylesheets/` to store your styles instead of `./source/css/` you can do that. There is nothing to configure. The structure will be maintained when they're moved to the `./public/` directory. + +## Ignoring and Not Moving Assets Based on File Extension + +By default, Pattern Lab will not move assets with the following file extensions: + +- `.less` +- `.scss` +- `.DS_Store` + +To ignore more file extensions edit the `ie` configuration option in `./config/config.yml`. For example, to ignore `*.png` files your `ie` configuration option would look like: + + ie: + - DS_Store + - less + - scss + - png + +## Ignoring and Not Moving Assets Based on Directory + +By default, the PHP version of Pattern Lab will ignore **all** assets in directories that exactly match: + +- `scss` + +To ignore more directories just edit the `id` configuration option in `./config/config.yml`. For example, to ignore directories named `test/` your `id` configuration option would look like: + + id: + - scss + - test + +**Important:** Pattern Lab will only ignore exact matches of ignored directories. For example, if you had a directory named `cool_scss/` it, and the assets underneath it, _would_ be moved to `./public/` even though `scss` was in the name of the directory. + +## Adding Assets to the Pattern Header & Footer + +Static assets like Javascript and CSS **are not** added automagically to your patterns. You need to add them manually to the [shared pattern header and footer](/docs/pattern-header-footer.html). diff --git a/packages/docs/php-docs/pattern-states.md b/packages/docs/php-docs/pattern-states.md new file mode 100644 index 000000000..58dc72591 --- /dev/null +++ b/packages/docs/php-docs/pattern-states.md @@ -0,0 +1,45 @@ +--- +title: Using Pattern States +tags: + - docs +--- + +Pattern states provide your team and client a simple visual of the current state of patterns in Pattern Lab. Pattern states can track progress of a pattern from development, through client review, to completion or they can be used to give certain patterns specific classes. It's important to note that the state of a pattern can be influenced by its pattern partials. + +## The Default Pattern States + +Pattern Lab comes with the following default pattern states: + +- **inprogress**: pattern is in development or being worked upon. a red dot. +- **inreview**: pattern is ready for a client to look at and comment upon. a yellow dot. +- **complete**: pattern is ready to be moved to production. a green dot. + +Any pattern that includes a pattern partial that has a lower pattern state will inherit that state. For example, a pattern with the state of `inreview` that includes a pattern partial with the state of `inprogress` will have its state overridden and set to `inprogress`. It will not change to `inreview` until the pattern partial has a state of `inreview` or `complete`. + +## Giving Patterns a State + +Giving patterns a state is simply a matter of modifying the file name. If we wanted to give our `molecules-media-block` pattern a state of `inprogress` we'd change the file name from: + +``` +./source/_patterns/molecules/blocks/media-block.mustache +``` + +to: + +``` +./source/_patterns/molecules/blocks/media-block@inprogress.mustache +``` + +## Adding Customized States + +The three default states included with Pattern Lab might not be enough for everyone. To add customized states you should modify your own CSS files. **DO NOT** modify `states.css` in `public/styleguide/css/`. This is because `states.css` will be overwritten in future upgrades. + +You can use the following as your CSS template for new pattern states: + +```css +{% raw %}.newpatternstate::before { + color: #B10DC9 !important; +}{% endraw %} +``` + +Then add `@newpatternstate` to your patterns to have the new look show up. If you want to add it to the cascade of the default patterns you can modify `./config/config.yml`. Simply add your new pattern state to the `patternStates` list. diff --git a/packages/docs/php-docs/requirements.md b/packages/docs/php-docs/requirements.md new file mode 100644 index 000000000..d823eddc3 --- /dev/null +++ b/packages/docs/php-docs/requirements.md @@ -0,0 +1,22 @@ +--- +title: Requirements +tags: + - docs +--- + + + +The requirements for Pattern Lab 2 vary depending on what features you want to use. + +## Minimum Requirements + +To use the basic features of Pattern Lab to compile patterns, you must have **PHP 5.4+** installed. On Mac OS X Pattern Lab should work "out of the box." If you're on Windows you can [download PHP from PHP.net](https://windows.php.net/download/). Pattern Lab comes with its own built-in web server. + +Because Pattern Lab's output consists of HTML, CSS, and JavaScript there are **no requirements** for hosting your Pattern Lab site. Simply upload the `./public/` directory to your host and you should be good to go. + +## Highly Recommended: Composer + +Pattern Lab uses [Composer](https://getcomposer.org/) to manage project dependencies. While Pattern Lab can be downloaded as a Zip we highly recommend installing Composer so you can easily update your project in the future. Please follow the directions for [installing Composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) on the Composer website. We recommend you [install it globally](https://getcomposer.org/doc/00-intro.md#globally). + + + diff --git a/packages/docs/php-docs/upgrading.md b/packages/docs/php-docs/upgrading.md new file mode 100644 index 000000000..c0661f087 --- /dev/null +++ b/packages/docs/php-docs/upgrading.md @@ -0,0 +1,52 @@ +--- +title: Upgrading Pattern Lab +tags: + - docs +--- + + + +Pattern Lab 2 uses [Composer](https://getcomposer.org) to manage project dependencies. To upgrade an edition based on Pattern Lab 2 do the following: + +1. In a terminal window navigate to the root of your project +2. Type `composer update` + +During the upgrade process Pattern Lab 2 will move or add any files that are required for the new version to work. It will also update your configuration as appropriate. If you don't have Composer installed please [follow the directions for installing Composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx) that are available on the Composer website. We recommend you [install it globally](https://getcomposer.org/doc/00-intro.md#globally). + +## Upgrading Pattern Lab 1 to Pattern Lab 2 + +Pattern Lab 2 was a complete rewrite and reorganization of Pattern Lab 1. [Learn about the changes](/docs/changes-1-to-2.html). To upgrade do the following: + +1. [Download](https://patternlab.io/docs/installing-pattern-lab/) the PHP edition that matches your needs + +If you chose a Mustache-based edition do the following: + +1. Copy `./source` from your old project to your new edition +2. Copy `./source/_patterns/atoms/meta/_head.mustache` to `./source/_meta/_head.mustache` +3. Copy `./source/_patterns/atoms/meta/_foot.mustache` to `./source/_meta/_foot.mustache` (you can then delete `source/_patterns/atoms/meta/` directory) +4. In `./source/_meta/_head.mustache`, replace `{% raw %}{% pattern-lab-head %}{% endraw %}` with `{% raw %}{{{ patternLabHead }}}{% endraw %}` +5. In `./source/_meta/_foot.mustache` replace `{% raw %}{% pattern-lab-foot %}{% endraw %}` with `{% raw %}{{{ patternLabFoot }}}{% endraw %}` +6. Copy `./source/_data/annotations.js` to `./source/_annotations/annotations.js` +7. Remove the underscore in front of the JSON files in `source/data` (i.e. `data.json` not `_data.json`). + + + +If you chose another version do the above and convert the templates as appropriate. + +## Learning About Upgrades + +New releases and upgrades are announced in Pattern Lab's [PHP room on Gitter](https://gitter.im/pattern-lab/php) and on Twitter at [@patternlabio](https://twitter.com/patternlabio). + +You can also determine if your version of Pattern Lab 2 can be upgraded yourself by doing the following: + +1. In a terminal window navigate to the root of your project +2. Type `composer outdated` + +Two components of Pattern Lab 2 maintain CHANGELOGs as part of their "Releases" page on GitHub: + +* [pattern-lab/core](https://github.com/pattern-lab/patternlab-php-core/releases) +* [pattern-lab/styleguidekit-assets-default](https://github.com/pattern-lab/styleguidekit-assets-default/releases) + + + + diff --git a/packages/docs/php-docs/viewing-patterns.md b/packages/docs/php-docs/viewing-patterns.md new file mode 100644 index 000000000..b2307acf5 --- /dev/null +++ b/packages/docs/php-docs/viewing-patterns.md @@ -0,0 +1,12 @@ +--- +title: Viewing Patterns +tags: + - docs +--- + +Pattern Lab utilizes PHP's [built-in web server](https://www.php.net/manual/en/features.commandline.webserver.php) to let you browse your generated patterns. To start the server do the following: + +1. In a terminal window navigate to the root of your project +2. Type `php core/console --server` + +Your local Pattern Lab install should now be available for browsing at [http://localhost:8080](http://localhost:8080). diff --git a/packages/docs/rollup.config.js b/packages/docs/rollup.config.js new file mode 100644 index 000000000..4fc2d3bc6 --- /dev/null +++ b/packages/docs/rollup.config.js @@ -0,0 +1,14 @@ +const builtins = require('@erquhart/rollup-plugin-node-builtins'); +const commonjs = require('rollup-plugin-commonjs'); +const nodeResolve = require('rollup-plugin-node-resolve'); +const json = require('rollup-plugin-json'); + +export default { + input: 'src/admin/util', + output: { + file: 'dist/admin/util.js', + format: 'iife', + name: 'previewUtil', + }, + plugins: [builtins(), nodeResolve(), commonjs(), json()], +}; diff --git a/packages/docs/src/404.md b/packages/docs/src/404.md new file mode 100644 index 000000000..b69a2386a --- /dev/null +++ b/packages/docs/src/404.md @@ -0,0 +1,17 @@ +--- +title: '404 - not found' +layout: layouts/page.njk +permalink: 404.html +sitemapIgnore: true +--- + +We’re sorry, but that content can’t be found. Please go [back to home](/). + +{% comment %} +Read more: https://www.11ty.io/docs/quicktips/not-found/ + +This will work for both GitHub pages and Netlify: + +- https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/ +- https://www.netlify.com/docs/redirects/#custom-404 + {% endcomment %} diff --git a/packages/docs/src/_data/global.js b/packages/docs/src/_data/global.js new file mode 100644 index 000000000..3c823d73b --- /dev/null +++ b/packages/docs/src/_data/global.js @@ -0,0 +1,10 @@ +module.exports = { + random() { + const segment = () => { + // eslint-disable-next-line no-bitwise + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + }; + return `${segment()}-${segment()}-${segment()}`; + }, + now: Date.now(), +}; diff --git a/packages/docs/src/_data/helpers.js b/packages/docs/src/_data/helpers.js new file mode 100644 index 000000000..bd6f173d3 --- /dev/null +++ b/packages/docs/src/_data/helpers.js @@ -0,0 +1,10 @@ +module.exports = { + getNextHeadingLevel(currentLevel) { + return parseInt(currentLevel, 10) + 1; + }, + getReadingTime(text) { + const wordsPerMinute = 200; + const numberOfWords = text.split(/\s/g).length; + return Math.ceil(numberOfWords / wordsPerMinute); + }, +}; diff --git a/packages/docs/src/_data/navigation.json b/packages/docs/src/_data/navigation.json new file mode 100644 index 000000000..d309386b1 --- /dev/null +++ b/packages/docs/src/_data/navigation.json @@ -0,0 +1,66 @@ +{ + "items": [ + { + "label": "Getting Started", + "url": "/docs/installing-pattern-lab/" + }, + { + "label": "Documentation", + "url": "/docs/", + "subnavIsClosed": true, + "subnav": [ + { + "label": "Getting Started", + "category": "getting-started" + }, + { + "label": "Working with Patterns", + "category": "patterns" + }, + { + "label": "Working with Data", + "category": "data" + }, + { + "label": "Advanced", + "category": "advanced" + } + ] + }, + { + "label": "Demos", + "url": "/demos/" + }, + { + "label": "Support", + "url": "/support/" + }, + { + "label": "Resources", + "url": "/resources/" + }, + { + "label": "On Github", + "url": "https://github.com/pattern-lab/patternlab-node", + "external": true + } + ], + "footerNav": [ + { + "label": "Resources", + "url": "/resources/" + }, + { + "label": "Updates", + "url": "/updates/" + }, + { + "label": "Demos", + "url": "/demos/" + }, + { + "label": "On Github", + "url": "https://github.com/pattern-lab/patternlab-node" + } + ] +} diff --git a/packages/docs/src/_data/site.json b/packages/docs/src/_data/site.json new file mode 100644 index 000000000..555f61950 --- /dev/null +++ b/packages/docs/src/_data/site.json @@ -0,0 +1,13 @@ +{ + "showThemeCredit": true, + "name": "Pattern Lab", + "shortDesc": "Pattern Lab is a frontend workshop environment that helps you build, view, test, and showcase your design system's UI components.", + "url": "https://patternlab.io", + "authorEmail": "brad@bradfrost.com", + "authorHandle": "@bradfrost", + "authorName": "Brad Frost", + "enableThirdPartyComments": false, + "maxPostsPerPage": 5, + "paymentPointer": "$coil.xrptipbot.com/c1f8f05d-8d8c-4f37-b1ad-25677ae129da", + "faviconPath": "/images/favicon.ico" +} diff --git a/packages/docs/src/_data/styleguide.js b/packages/docs/src/_data/styleguide.js new file mode 100644 index 000000000..a3977f9b0 --- /dev/null +++ b/packages/docs/src/_data/styleguide.js @@ -0,0 +1,28 @@ +const tokens = require('./tokens.json'); + +module.exports = { + colors() { + let response = []; + + Object.keys(tokens.colors).forEach((key) => { + response.push({ + value: tokens.colors[key], + key, + }); + }); + + return response; + }, + sizes() { + let response = []; + + Object.keys(tokens['size-scale']).forEach((key) => { + response.push({ + value: tokens['size-scale'][key], + key, + }); + }); + + return response; + }, +}; diff --git a/packages/docs/src/_data/tokens.json b/packages/docs/src/_data/tokens.json new file mode 100644 index 000000000..b5bf4b3ae --- /dev/null +++ b/packages/docs/src/_data/tokens.json @@ -0,0 +1,26 @@ +{ + "size-scale": { + "base": "1rem", + "300": "0.8rem", + "500": "1.25rem", + "600": "1.56rem", + "700": "1.95rem", + "800": "2.44rem", + "900": "3.05rem", + "max": "4rem" + }, + "colors": { + "primary": "#173854", + "primary-shade": "#102538", + "primary-glare": "#22547c", + "highlight": "#fedb8b", + "light": "#ffffff", + "mid": "#cccccc", + "dark": "#333333", + "slate": "#404040" + }, + "fonts": { + "base": "\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'\"", + "serif": "\"'Lora', serif\"" + } +} diff --git a/packages/docs/src/_includes/components/footer-nav.njk b/packages/docs/src/_includes/components/footer-nav.njk new file mode 100644 index 000000000..54a448266 --- /dev/null +++ b/packages/docs/src/_includes/components/footer-nav.njk @@ -0,0 +1,10 @@ + diff --git a/packages/docs/src/_includes/components/footer.njk b/packages/docs/src/_includes/components/footer.njk new file mode 100644 index 000000000..7764312d2 --- /dev/null +++ b/packages/docs/src/_includes/components/footer.njk @@ -0,0 +1,10 @@ + diff --git a/packages/docs/src/_includes/components/header.njk b/packages/docs/src/_includes/components/header.njk new file mode 100644 index 000000000..5a5a508df --- /dev/null +++ b/packages/docs/src/_includes/components/header.njk @@ -0,0 +1,22 @@ +
+
+ {% include "components/logo.njk" %} + + + +
+ {% include "components/tree-nav.njk" %} + + + +
+
+ +
+ + diff --git a/packages/docs/src/_includes/components/hero.njk b/packages/docs/src/_includes/components/hero.njk new file mode 100644 index 000000000..7053c247c --- /dev/null +++ b/packages/docs/src/_includes/components/hero.njk @@ -0,0 +1,16 @@ +
+
+
+

Create atomic design systems with Pattern Lab

+ +

+ Pattern Lab is a frontend workshop environment that helps you build, view, test, and showcase your design system's UI components. +

+ +

+ Run the following command in your terminal and read the installation guide to get started: +

+
npm create pattern-lab
+
+
+
\ No newline at end of file diff --git a/packages/docs/src/_includes/components/icon-chevron-down.njk b/packages/docs/src/_includes/components/icon-chevron-down.njk new file mode 100644 index 000000000..37c8e757a --- /dev/null +++ b/packages/docs/src/_includes/components/icon-chevron-down.njk @@ -0,0 +1,4 @@ + +cheveron-down + + \ No newline at end of file diff --git a/packages/docs/src/_includes/components/logo.njk b/packages/docs/src/_includes/components/logo.njk new file mode 100644 index 000000000..fad8e3428 --- /dev/null +++ b/packages/docs/src/_includes/components/logo.njk @@ -0,0 +1,11 @@ + + + diff --git a/packages/docs/src/_includes/components/meta-info.njk b/packages/docs/src/_includes/components/meta-info.njk new file mode 100644 index 000000000..c7d6a3aa0 --- /dev/null +++ b/packages/docs/src/_includes/components/meta-info.njk @@ -0,0 +1,41 @@ +{% set pageTitle = title + ' - ' + site.name %} +{% set pageDesc = '' %} +{% set siteTitle = site.name %} +{% set currentUrl = site.url + page.url %} + +{% if metaTitle %} + {% set pageTitle = metaTitle %} +{% endif %} + +{% if metaDesc %} + {% set pageDesc = metaDesc %} +{% endif %} + +{{ pageTitle }} + + + + + + + +{% if site.authorHandle %} + +{% endif %} + +{% if metaDesc %} + + + +{% endif %} + +{% if socialImage %} + + + + +{% endif %} + +{% if site.paymentPointer %} + +{% endif %} diff --git a/packages/docs/src/_includes/components/page-header.njk b/packages/docs/src/_includes/components/page-header.njk new file mode 100644 index 000000000..8fbae6236 --- /dev/null +++ b/packages/docs/src/_includes/components/page-header.njk @@ -0,0 +1,13 @@ +
+ + {% if introKicker %} +

{{ introKicker }}

+ {% endif %} + +

{{ introHeading }}

+ + {% if introDescription %} +

{{ introDescription }}

+ {% endif %} + +
diff --git a/packages/docs/src/_includes/components/stacked-block.njk b/packages/docs/src/_includes/components/stacked-block.njk new file mode 100644 index 000000000..fb351e919 --- /dev/null +++ b/packages/docs/src/_includes/components/stacked-block.njk @@ -0,0 +1,6 @@ +
+

+ {{ title }} +

+

{{ description }}

+
diff --git a/packages/docs/src/_includes/components/tile.njk b/packages/docs/src/_includes/components/tile.njk new file mode 100644 index 000000000..c6274f2e6 --- /dev/null +++ b/packages/docs/src/_includes/components/tile.njk @@ -0,0 +1,9 @@ +
+
+

+ {{ title }} +

+
{{ description | safe }}
+
+
+
diff --git a/packages/docs/src/_includes/components/tree-nav.njk b/packages/docs/src/_includes/components/tree-nav.njk new file mode 100644 index 000000000..b2128fe34 --- /dev/null +++ b/packages/docs/src/_includes/components/tree-nav.njk @@ -0,0 +1,33 @@ + + + + diff --git a/packages/docs/src/_includes/components/tree-subnav.njk b/packages/docs/src/_includes/components/tree-subnav.njk new file mode 100644 index 000000000..ace03cb8c --- /dev/null +++ b/packages/docs/src/_includes/components/tree-subnav.njk @@ -0,0 +1,11 @@ +{% set navPages = collections.docs | eleventyNavigation %} +
    +{% for entry in navPages %} + {% if entry.key == subnavCategory %} +
  • + {{ entry.title }} +
  • + {% endif %} +{% endfor %} +
+ diff --git a/packages/docs/src/_includes/icons/arrow.svg b/packages/docs/src/_includes/icons/arrow.svg new file mode 100644 index 000000000..153b9eed7 --- /dev/null +++ b/packages/docs/src/_includes/icons/arrow.svg @@ -0,0 +1,13 @@ + diff --git a/packages/docs/src/_includes/layouts/archive.njk b/packages/docs/src/_includes/layouts/archive.njk new file mode 100644 index 000000000..d1b328ed8 --- /dev/null +++ b/packages/docs/src/_includes/layouts/archive.njk @@ -0,0 +1,17 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Post Archive' %} + +{# Intro content #} +{% set introHeading = title %} +{% set introSummary %}{{ content | safe }}{% endset %} + +{# Post list content #} +{% set postListHeading = 'All posts' %} +{% set postListItems = collections.posts %} + +{% block content %} +
+ {% include "partials/components/intro.njk" %} + {% include "partials/components/post-list.njk" %} +
+{% endblock %} diff --git a/packages/docs/src/_includes/layouts/base.njk b/packages/docs/src/_includes/layouts/base.njk new file mode 100644 index 000000000..6d21c8837 --- /dev/null +++ b/packages/docs/src/_includes/layouts/base.njk @@ -0,0 +1,37 @@ + + + + + + + + + + {% include "components/meta-info.njk" %} + + + {% block head %} + {% endblock %} + + +
+
+ {% include "components/header.njk" %} +
+ + +
+
+ {% block content %} + {% endblock content %} +
+ + {% include "components/footer.njk" %} + {% block foot %} + {% endblock %} +
+ +
+ + + diff --git a/packages/docs/src/_includes/layouts/blog.njk b/packages/docs/src/_includes/layouts/blog.njk new file mode 100644 index 000000000..bc7b10eef --- /dev/null +++ b/packages/docs/src/_includes/layouts/blog.njk @@ -0,0 +1,17 @@ +{% extends 'layouts/base.njk' %} + +{# Intro content #} +{% set introHeading = title %} +{% set introDescription = description %} + +{# Post list content #} +{% set postListItems = collections.posts %} + +{% block content %} +
+
+ {% include "components/page-header.njk" %} + {% include "partials/components/post-list.njk" %} +
+
+{% endblock %} diff --git a/packages/docs/src/_includes/layouts/demos.njk b/packages/docs/src/_includes/layouts/demos.njk new file mode 100644 index 000000000..f3746bbef --- /dev/null +++ b/packages/docs/src/_includes/layouts/demos.njk @@ -0,0 +1,23 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Post Archive' %} + +{# Intro content #} +{% set introHeading = title %} +{% set introSummary %}{{ content | safe }}{% endset %} + +{# Post list content #} +{% set demoListItems = collections.demos %} + +{% block content %} +
+ {% include "components/page-header.njk" %} + +

In the wild

+ {% set demoListCategory = 'example' %} + {% include "partials/components/demo-list.njk" %} + +

Starterkits

+ {% set demoListCategory = 'starterkit' %} + {% include "partials/components/demo-list.njk" %} +
+{% endblock %} \ No newline at end of file diff --git a/packages/docs/src/_includes/layouts/docs.njk b/packages/docs/src/_includes/layouts/docs.njk new file mode 100644 index 000000000..e29cc063e --- /dev/null +++ b/packages/docs/src/_includes/layouts/docs.njk @@ -0,0 +1,28 @@ +--- +permalink: docs/{{ title | slug }}/ +--- + +{% extends 'layouts/base.njk' %} +{% set pageType = 'Docs' %} + +{# Intro content #} +{% set introHeading = title %} +{% set introSummary %} + +{% endset %} + +{% block content %} +
+
+
+ {% include "components/page-header.njk" %} +
+ {{ content | safe }} +
+ +
+
+
+{% endblock %} + +{{ content | safe }} diff --git a/packages/docs/src/_includes/layouts/home.njk b/packages/docs/src/_includes/layouts/home.njk new file mode 100644 index 000000000..b63fdb0da --- /dev/null +++ b/packages/docs/src/_includes/layouts/home.njk @@ -0,0 +1,101 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Homepage' %} + +{% block content %} + + {% set additionalClasses = 'c-tile--orange' %} + {% set title = 'Pattern Lab is archived. ' %} + {% set link = 'https://github.com/pattern-lab' %} + {% set description = "Read the full announcement, and thank you." %} +
+ {% include "components/tile.njk" %} +
+ + {% include "components/hero.njk" %} + +
+
    +
  • + {% set additionalClasses = 'c-tile--green' %} + {% set title = 'Read the docs' %} + {% set link = '/docs/installing-pattern-lab/' %} + {% set description = "Learn how to get up and running with Pattern Lab, work with patterns, design with dynamic data, and use Pattern Lab's advanced features." %} + {% include "components/tile.njk" %} +
  • +
  • + {% set additionalClasses = 'c-tile--orange' %} + {% set title = 'Demos' %} + {% set link = '/demos/' %} + {% set description = "Demos of pattern starterkits for your project as well as a gallery of Pattern Lab projects in the wild" %} + {% include "components/tile.njk" %} +
  • +
  • + {% set additionalClasses = 'c-tile--purple' %} + {% set title = 'Resources' %} + {% set link = '/resources/' %} + {% set description = "Links to articles and resources around Pattern Lab and design systems" %} + {% include "components/tile.njk" %} +
  • +
+
+ +
+

Pattern Lab features

+

At its core, Pattern Lab is a Node-powered static site generator that stitches together UI components. But there's a whole lot more to it than that!

+
    +
  • + {% set title="Nested Patterns" %} + {% set description="Include UI patterns inside each other like Russian nesting dolls. Make a change to a pattern and immediately see those changes reflected anywhere it is included." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Design With Dynamic Data" %} + {% set description="Create living UI prototypes using dynamic data to ensure your components can handle the dynamic nature of your content." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Tool Agnostic" %} + {% set description="Pattern Lab doesn't impose any tools or libraries on you, which means you have full control over how author your project." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Language Agnostic" %} + {% set description="Use atomic design language, or don't! it's totally up to you how you name, structure, and organize your Pattern Lab project." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Pattern Documentation" %} + {% set description="Define and describe your UI patterns so your entire team can start speaking the same language to collaborate more effectively." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Viewport Resizer Tools" %} + {% set description="Pattern Lab includes viewport resizing tools to ensure your design system's components and pages are fully responsive." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Pattern Lineage" %} + {% set description="X-ray vision! Quickly view where patterns where components are used, speeding up design, development, and QA time." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Pattern Starter Kits" %} + {% set description="Start your Pattern Lab project with a blank slate, a few sample components, or a full-on demo project." %} + {% include "components/stacked-block.njk" %} +
  • +
  • + {% set title="Flexible and Extensible" %} + {% set description="Pattern Lab supports Handlebars and Twig templating engines. Also you can or build a plugin to extend Pattern Lab's capabilities even further." %} + {% include "components/stacked-block.njk" %} +
  • +
+ + {% set additionalClasses = 'c-tile--orange' %} + {% set title = 'Open source and community driven' %} + {% set link = '/support/' %} + {% set description = "Pattern Lab is (and will always be) an open source project. Check out the project on GitHub and join the Pattern Lab Gitter community for conversation and support." %} + {% include "components/tile.njk" %} + +
+ +{% endblock %} diff --git a/packages/docs/src/_includes/layouts/page-base.njk b/packages/docs/src/_includes/layouts/page-base.njk new file mode 100644 index 000000000..4a921e27f --- /dev/null +++ b/packages/docs/src/_includes/layouts/page-base.njk @@ -0,0 +1,24 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Resources' %} + +{# Intro content #} +{% set introHeading = title %} +{% set introSummary %} + +{% endset %} + +{% block content %} +
+
+
+ {% include "components/page-header.njk" %} +
+ {{ content | safe }} +
+ +
+
+
+{% endblock %} + +{{ content | safe }} diff --git a/packages/docs/src/_includes/layouts/page.njk b/packages/docs/src/_includes/layouts/page.njk new file mode 100644 index 000000000..0714fa10c --- /dev/null +++ b/packages/docs/src/_includes/layouts/page.njk @@ -0,0 +1,19 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Page' %} + +{# Intro content #} +{% set introHeading = title %} + +{% block content %} +
+
+
+ {% include "components/page-header.njk" %} + {{ content | safe }} +
+
+
+ +{% endblock %} + +{{ content | safe }} diff --git a/packages/docs/src/_includes/layouts/post.njk b/packages/docs/src/_includes/layouts/post.njk new file mode 100644 index 000000000..6a4702769 --- /dev/null +++ b/packages/docs/src/_includes/layouts/post.njk @@ -0,0 +1,25 @@ +{% extends 'layouts/base.njk' %} +{% set pageType = 'Post' %} + +{# Intro content #} +{% if date %} +{% set introKicker = date | dateFilter %} +{% endif %} +{% set introHeading = title %} + + +{% block content %} +
+
+
+ {% include "components/page-header.njk" %} + +
+ {{ content | safe }} +
+
+
+
+{% endblock %} + +{{ content | safe }} diff --git a/packages/docs/src/_includes/partials/components/demo-list.njk b/packages/docs/src/_includes/partials/components/demo-list.njk new file mode 100644 index 000000000..c351dde08 --- /dev/null +++ b/packages/docs/src/_includes/partials/components/demo-list.njk @@ -0,0 +1,37 @@ +{% if demoListItems.length %} + +
    + {% for item in demoListItems %} + + {% if item.data.category == demoListCategory %} +
  1. + + +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +

    + {{ item.data.title }} +

    +

    + {{ item.data.description}} +

    +
    + +
  2. + {% endif %} + + {% endfor %} +
+ +{% endif %} diff --git a/packages/docs/src/_includes/partials/components/intro.njk b/packages/docs/src/_includes/partials/components/intro.njk new file mode 100644 index 000000000..e5cc10c13 --- /dev/null +++ b/packages/docs/src/_includes/partials/components/intro.njk @@ -0,0 +1,8 @@ +
+
+

{{ introHeading }}

+ {% if introSummary %} +
{{ introSummary | safe }}
+ {% endif %} +
+
diff --git a/packages/docs/src/_includes/partials/components/nav.njk b/packages/docs/src/_includes/partials/components/nav.njk new file mode 100644 index 000000000..0b9cbcf6f --- /dev/null +++ b/packages/docs/src/_includes/partials/components/nav.njk @@ -0,0 +1,22 @@ +{% if navigation.items %} + +{% endif %} diff --git a/packages/docs/src/_includes/partials/components/pagination.njk b/packages/docs/src/_includes/partials/components/pagination.njk new file mode 100644 index 000000000..d78236a2a --- /dev/null +++ b/packages/docs/src/_includes/partials/components/pagination.njk @@ -0,0 +1,23 @@ +{% set paginationLinkTokens = 'leading-tight text-500 weight-mid box-inline-flex align-center pad-bottom-300' %} + +{% if paginationNextUrl or paginationPrevUrl %} +
+ +{% endif %} diff --git a/packages/docs/src/_includes/partials/components/post-list.njk b/packages/docs/src/_includes/partials/components/post-list.njk new file mode 100644 index 000000000..7a241e2e1 --- /dev/null +++ b/packages/docs/src/_includes/partials/components/post-list.njk @@ -0,0 +1,22 @@ + +{% if postListItems.length %} + +
    + {% for item in postListItems %} +
  1. + + +

    + + {{ item.data.title }} +

    +

    + {{ item.data.description}} +

    +
    + +
  2. + {% endfor %} +
+ +{% endif %} diff --git a/packages/docs/src/admin.njk b/packages/docs/src/admin.njk new file mode 100644 index 000000000..56f0d6566 --- /dev/null +++ b/packages/docs/src/admin.njk @@ -0,0 +1,23 @@ +--- +permalink: '/admin/index.html' +sitemapIgnore: true +--- + + + + + + Content Manager + + + + + + + + + + + + + diff --git a/packages/docs/src/admin/config.yml b/packages/docs/src/admin/config.yml new file mode 100644 index 000000000..15abea8bc --- /dev/null +++ b/packages/docs/src/admin/config.yml @@ -0,0 +1,243 @@ +backend: + name: git-gateway + branch: master +publish_mode: editorial_workflow +site_url: 'https://example.com' +media_folder: 'src/images' +public_folder: 'images' +collections: + - name: 'pages' + label: 'Pages' + files: + - name: 'home' + label: 'Homepage' + delete: false + file: 'src/index.md' + slug: '{{slug}}' + create: false + fields: + - { + label: 'Layout', + name: 'layout', + widget: 'hidden', + default: 'layouts/njk.njk', + } + - {label: 'Title', name: 'title', widget: 'string'} + - { + label: 'SEO Meta Title', + name: 'metaTitle', + widget: 'string', + required: false, + } + - { + label: 'SEO Meta Description', + name: 'metaDesc', + widget: 'string', + required: false, + } + - { + label: 'Post Feed Heading', + name: 'postsHeading', + widget: 'string', + default: 'Latest posts', + } + - { + label: 'Archive Link Text', + name: 'archiveButtonText', + widget: 'string', + default: 'See all posts', + } + - {label: 'Social Image', name: 'socialImage', widget: 'image', required: false} + - {label: 'Body', name: 'body', widget: 'markdown'} + - name: 'generic_pages' + label: 'Generic Pages' + folder: 'src/pages' + slug: '{{slug}}' + preview_path: 'pages/{{slug}}' + create: true + fields: + - {label: 'Layout', name: 'layout', widget: 'hidden', default: 'layouts/page.njk'} + - {label: 'Title', name: 'title', widget: 'string'} + - { + label: "Permalink Override (Pattern: '/your-slug/index.html')", + name: 'permalink', + widget: 'string', + required: false, + } + - {label: 'SEO Meta Title', name: 'metaTitle', widget: 'string', required: false} + - { + label: 'SEO Meta Description', + name: 'metaDesc', + widget: 'string', + required: false, + } + - {label: 'Social Image', name: 'socialImage', widget: 'image', required: false} + - {label: 'Body', name: 'body', widget: 'markdown'} + - name: 'posts' + label: 'Posts' + folder: 'src/posts' + slug: '{{slug}}' + preview_path: 'posts/{{slug}}' + create: true + fields: + - {label: 'Layout', name: 'layout', widget: 'hidden', default: 'layouts/post.njk'} + - {label: 'Title', name: 'title', widget: 'string'} + - {label: 'SEO Meta Title', name: 'metaTitle', widget: 'string', required: false} + - { + label: 'SEO Meta Description', + name: 'metaDesc', + widget: 'string', + required: false, + } + - {label: 'Social Image', name: 'socialImage', widget: 'image', required: false} + - {label: 'Publish Date', name: 'date', widget: 'datetime'} + - {label: 'Tags', name: 'tags', widget: 'list', allow_add: true} + - {label: 'Body', name: 'body', widget: 'markdown'} + - name: 'docs' + label: 'Docs' + folder: 'src/docs' + slug: '{{slug}}' + preview_path: 'docs/{{slug}}' + create: true + fields: + - {label: 'Layout', name: 'layout', widget: 'hidden', default: 'layouts/post.njk'} + - {label: 'Title', name: 'title', widget: 'string'} + - {label: 'Publish Date', name: 'date', widget: 'datetime'} + - {label: 'Tags', name: 'tags', widget: 'list', allow_add: true} + - {label: 'Body', name: 'body', widget: 'markdown'} + - label: 'Globals' + name: 'globals' + files: + - label: 'Site Data' + name: 'site_data' + delete: false + file: 'src/_data/site.json' + fields: + - {label: 'Site Name', name: 'name', widget: 'string'} + - {label: 'Site Url', name: 'url', widget: 'string'} + - {label: 'Author Name', name: 'authorName', widget: 'string'} + - {label: 'Author Email Address', name: 'authorEmail', widget: 'string'} + - { + label: 'Author Twitter Handle', + name: 'authorHandle', + widget: 'string', + required: false, + } + - {label: 'Footer Short Description', name: 'shortDesc', widget: 'string'} + - { + label: 'Maximum Posts Per Page', + name: 'maxPostsPerPage', + widget: 'number', + default: 5, + } + - { + label: 'Show Theme Credit', + name: 'showThemeCredit', + widget: 'boolean', + default: true, + } + - { + label: 'Enable Third Party Comments Area', + name: 'enableThirdPartyComments', + widget: 'boolean', + default: false, + } + - { + label: 'Payment Pointer (Web Monetization: https://bit.ly/2kTRI1b)', + name: 'paymentPointer', + widget: 'string', + } + - { + label: 'Favicon path (EG: /images/favicon.png)', + name: 'faviconPath', + widget: 'string', + } + - label: 'Navigation' + name: 'nav' + delete: false + file: 'src/_data/navigation.json' + fields: + - label: 'Items' + name: 'items' + widget: 'list' + fields: + - {label: 'Text', name: 'text', widget: 'string'} + - {label: 'Url', name: 'url', widget: 'string'} + - { + label: 'Is url to external site?', + name: 'external', + widget: 'boolean', + required: false, + } + - label: 'Theme Settings' + name: 'theme' + delete: false + file: 'src/_data/tokens.json' + fields: + - label: 'Size Scale' + name: 'size-scale' + widget: 'object' + fields: + - {label: 'Base Size', name: 'base', widget: 'string', default: '1rem'} + - {label: 'Ratio: 300', name: '300', widget: 'string', default: '0.8rem'} + - {label: 'Ratio: 500', name: '500', widget: 'string', default: '1.25rem'} + - {label: 'Ratio: 600', name: '600', widget: 'string', default: '1.56rem'} + - {label: 'Ratio: 700', name: '700', widget: 'string', default: '1.95rem'} + - {label: 'Ratio: 800', name: '800', widget: 'string', default: '2.44rem'} + - {label: 'Ratio: 900', name: '900', widget: 'string', default: '3.05rem'} + - {label: 'Max Size', name: 'max', widget: 'string', default: '4rem'} + - label: 'Colors' + name: 'colors' + widget: 'object' + fields: + - { + label: 'Primary', + name: 'primary', + widget: 'string', + default: 'hsl(208, 57%, 21%)', + } + - { + label: 'Primary Shade (darker)', + name: 'primary-shade', + widget: 'string', + default: 'hsl(208, 56%, 14%)', + } + - { + label: 'Primary Glare (lighter)', + name: 'primary-glare', + widget: 'string', + default: 'hsl(207, 57%, 31%)', + } + - { + label: 'Highlight', + name: 'highlight', + widget: 'string', + default: 'hsl(42, 98%, 77%)', + } + - { + label: 'Light', + name: 'light', + widget: 'string', + default: 'hsl(0, 0%, 100%)', + } + - {label: 'Mid', name: 'mid', widget: 'string', default: 'hsl(0, 0%, 80%)'} + - { + label: 'Dark', + name: 'dark', + widget: 'string', + default: 'hsl(0, 0%, 20%)', + } + - { + label: 'Slate', + name: 'slate', + widget: 'string', + default: 'hsl(0, 0%, 25%)', + } + - label: 'Fonts' + name: 'fonts' + widget: 'hidden' + default: + { + 'base': '"-apple-system, BlinkMacSystemFont, ''Segoe UI'', Roboto, Helvetica, Arial, sans-serif, ''Apple Color Emoji'', ''Segoe UI Emoji'', ''Segoe UI Symbol''"', + 'serif': '"''Lora'', serif"', + } diff --git a/packages/docs/src/admin/previews.js b/packages/docs/src/admin/previews.js new file mode 100644 index 000000000..46a94b655 --- /dev/null +++ b/packages/docs/src/admin/previews.js @@ -0,0 +1,92 @@ +const {w3DateFilter, markdownFilter, dateFilter, helpers} = previewUtil; + +const env = nunjucks.configure(); + +env.addFilter('w3DateFilter', w3DateFilter); +env.addFilter('markdownFilter', markdownFilter); +env.addFilter('dateFilter', dateFilter); + +const Preview = ({entry, path, context}) => { + const data = context(entry.get('data').toJS()); + const html = env.render(path, {...data, helpers}); + return
; +}; + +const Home = ({entry}) => ( + ({ + title, + content: markdownFilter(body), + postsHeading, + archiveButtonText, + collections: { + postFeed: [ + { + url: 'javascript:void(0)', + date: new Date(), + data: { + title: 'Sample Post', + }, + }, + ], + }, + })} + /> +); + +const Post = ({entry}) => ( + ({ + title, + date, + content: markdownFilter(body || ''), + })} + /> +); + +const Page = ({entry}) => ( + ({ + title, + content: markdownFilter(body || ''), + })} + /> +); + +const SiteData = ({entry}) => ( + ({ + site: { + name, + shortDesc, + showThemeCredit, + }, + })} + /> +); + +const Nav = ({entry}) => ( + ({ + navigation: { + items, + }, + })} + /> +); + +CMS.registerPreviewTemplate('home', Home); +CMS.registerPreviewTemplate('posts', Post); +CMS.registerPreviewTemplate('generic_pages', Page); +CMS.registerPreviewTemplate('site_data', SiteData); +CMS.registerPreviewTemplate('nav', Nav); diff --git a/packages/docs/src/admin/util.js b/packages/docs/src/admin/util.js new file mode 100644 index 000000000..53db2e8ec --- /dev/null +++ b/packages/docs/src/admin/util.js @@ -0,0 +1,6 @@ +import helpers from '../_data/helpers'; +import dateFilter from '../filters/date-filter'; +import markdownFilter from '../filters/markdown-filter'; +import w3DateFilter from '../filters/w3-date-filter'; + +export {helpers, dateFilter, markdownFilter, w3DateFilter}; diff --git a/packages/docs/src/archive.md b/packages/docs/src/archive.md new file mode 100644 index 000000000..e594fe388 --- /dev/null +++ b/packages/docs/src/archive.md @@ -0,0 +1,5 @@ +--- +title: 'Posts Archive' +layout: 'layouts/archive.njk' +sitemapIgnore: true +--- diff --git a/packages/docs/src/demos.md b/packages/docs/src/demos.md new file mode 100644 index 000000000..d07d9d32f --- /dev/null +++ b/packages/docs/src/demos.md @@ -0,0 +1,15 @@ +--- +layout: layouts/demos.njk +title: Pattern Lab Demos +category: getting-started +sitemapPriority: '0.9' +sitemapChangefreq: 'monthly' +--- + + + +Here’s a list of Pattern Lab’s UI starterkits that you can use to kickstart your UI design system project, as well as a list of Pattern Labs from around the web. + + + + diff --git a/packages/docs/src/demos/bolt-design-systems.md b/packages/docs/src/demos/bolt-design-systems.md new file mode 100644 index 000000000..107fd44fc --- /dev/null +++ b/packages/docs/src/demos/bolt-design-systems.md @@ -0,0 +1,12 @@ +--- +title: Bolt Design System +description: The Bolt Design System provides robust Twig and Web Component-powered UI components, reusable visual styles, and powerful tooling to help developers, designers, and content authors build, maintain, and scale best of class digital experiences. +url: https://boltdesignsystem.com/ +category: example +tags: + - demo-in-the-wild + - demo-content + - code +refLink: https://boltdesignsystem.com/pattern-lab/?p=pages-d8-homepage +sitemapIgnore: true +--- diff --git a/packages/docs/src/demos/handlebars-base-starterkit.md b/packages/docs/src/demos/handlebars-base-starterkit.md new file mode 100644 index 000000000..dccdb1107 --- /dev/null +++ b/packages/docs/src/demos/handlebars-base-starterkit.md @@ -0,0 +1,12 @@ +--- +title: Handlebars Base Starter Kit Preview +description: The StarterKit for Handlebars is meant to be used as a demonstration of a Handlebars-based project in Pattern Lab. +url: https://patternlab-handlebars-preview.netlify.com/?p=all +category: starterkit +tags: + - demo-hbs-starter-kits + - demo-content + - code +refLink: https://patternlab-handlebars-preview.netlify.app/?p=all +sitemapIgnore: true +--- diff --git a/packages/docs/src/demos/handlebars-demo-starterkit.md b/packages/docs/src/demos/handlebars-demo-starterkit.md new file mode 100644 index 000000000..6fc51cfa6 --- /dev/null +++ b/packages/docs/src/demos/handlebars-demo-starterkit.md @@ -0,0 +1,12 @@ +--- +title: Handlebars Demo Starter Kit +description: The Demo StarterKit for Handlebars is meant to be used as a demonstration of a Handlebars-based project in Pattern Lab. +url: https://www.npmjs.com/package/@pattern-lab/starterkit-handlebars-demo +category: starterkit +tags: + - demo-hbs-starter-kits + - demo-content + - code +refLink: https://patternlab-handlebars-preview.netlify.app/?p=all +sitemapIgnore: true +--- diff --git a/packages/docs/src/demos/handlebars-vanilla-starterkit.md b/packages/docs/src/demos/handlebars-vanilla-starterkit.md new file mode 100644 index 000000000..677c3cf29 --- /dev/null +++ b/packages/docs/src/demos/handlebars-vanilla-starterkit.md @@ -0,0 +1,12 @@ +--- +title: Handlebars Vanilla Starter Kit +description: The Vanilla StarterKit for Handlebars is meant to be used as a demonstration of a Handlebars-based project in Pattern Lab. +url: https://www.npmjs.com/package/@pattern-lab/starterkit-handlebars-vanilla +category: starterkit +tags: + - demo-hbs-starter-kits + - demo-content + - code +refLink: https://patternlab-handlebars-preview.netlify.app/?p=all +sitemapIgnore: true +--- diff --git a/packages/docs/src/docs/a-post-with-code-samples.md b/packages/docs/src/docs/a-post-with-code-samples.md new file mode 100644 index 000000000..dac628f4c --- /dev/null +++ b/packages/docs/src/docs/a-post-with-code-samples.md @@ -0,0 +1,69 @@ +--- +title: DOCS DOCS DOCS +tags: + - demo-content + - code + - blog +eleventyNavigation: + key: DOCS DOCS DOCS + order: 300 +sitemapPriority: '0.8' +sitemapIgnore: true +--- + +The best way to demo a code post is to display a real life post, so check out this one from [andy-bell.design](https://andy-bell.design/wrote/creating-a-full-bleed-css-utility/) about a full bleed CSS utility. + +--- + +Sometimes you want to break your components out of the constraints that they find themselves in. A common situation where this occurs is when you don’t have much control of the container that it exists in, such as a CMS main content area. + +This is even more the case with editing tools such as the [WordPress Gutenberg editor](https://wordpress.org/gutenberg/), where in theory, you could pull in a component from a design system and utilise it in the main content of your web page. In these situations, it can be pretty darn handy to have a little utility that makes the element 100% of the viewport’s width _and_ still maintain its flow within its parent container. + +This is when I normally pull the `.full-bleed` utility class out of my back pocket. + +## The `.full-bleed` utility + +It’s small, but hella mighty: + +```css +.full-bleed { + width: 100vw; + margin-left: 50%; + transform: translateX(-50%); +} +``` + +Here it is in a context where it makes a fancy `
+ diff --git a/packages/uikit-workshop/src/html/partials/controls.html b/packages/uikit-workshop/src/html/partials/controls.html deleted file mode 100644 index 533752058..000000000 --- a/packages/uikit-workshop/src/html/partials/controls.html +++ /dev/null @@ -1,87 +0,0 @@ - -
- - -
- -
    - {{^ ishControlsHide.s }} -
  • - -
  • - {{/ ishControlsHide.s }} - - {{^ ishControlsHide.m }} -
  • - -
  • - {{/ ishControlsHide.m }} - - {{^ ishControlsHide.l }} -
  • - -
  • - {{/ ishControlsHide.l }} - - {{^ ishControlsHide.full }} -
  • - -
  • - {{/ ishControlsHide.full }} - - {{^ ishControlsHide.random }} -
  • - -
  • - {{/ ishControlsHide.random }} - - {{^ ishControlsHide.disco }} -
  • - -
  • - {{/ ishControlsHide.disco }} - - {{^ ishControlsHide.hay }} -
  • - -
  • - {{/ ishControlsHide.hay }} -
- -{{^ ishControlsHide.tools-all }} -
- - -
    -
  • - - - -
  • -
  • - -
  • -
  • - -
  • - {{^ ishControlsHide.views-new }} -
  • - Open In New Tab -
  • - {{/ ishControlsHide.views-new }} - - {{^ ishControlsHide.tools-docs }} -
  • - Pattern Lab Docs -
  • - {{/ ishControlsHide.tools-docs }} -
-
-{{/ ishControlsHide.tools-all }} \ No newline at end of file diff --git a/packages/uikit-workshop/src/html/partials/header.html b/packages/uikit-workshop/src/html/partials/header.html deleted file mode 100644 index da990cf32..000000000 --- a/packages/uikit-workshop/src/html/partials/header.html +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/packages/uikit-workshop/src/html/partials/iframe-loader.html b/packages/uikit-workshop/src/html/partials/iframe-loader.html deleted file mode 100644 index 40086f8aa..000000000 --- a/packages/uikit-workshop/src/html/partials/iframe-loader.html +++ /dev/null @@ -1,15 +0,0 @@ - - -
-
-
Loading Pattern Lab
-
- - - - - -
-
-
diff --git a/packages/uikit-workshop/src/html/partials/iframe.html b/packages/uikit-workshop/src/html/partials/iframe.html deleted file mode 100644 index 0ae6a5752..000000000 --- a/packages/uikit-workshop/src/html/partials/iframe.html +++ /dev/null @@ -1,20 +0,0 @@ -
- -
- -
- - - -
- -
- -
- - -
- - -
- \ No newline at end of file diff --git a/packages/uikit-workshop/src/html/partials/modal.html b/packages/uikit-workshop/src/html/partials/modal.html deleted file mode 100644 index 724e6c667..000000000 --- a/packages/uikit-workshop/src/html/partials/modal.html +++ /dev/null @@ -1,20 +0,0 @@ -
-
-
-
-
- - - - -
-
-
-
-
-
diff --git a/packages/uikit-workshop/src/html/partials/pattern-nav.html b/packages/uikit-workshop/src/html/partials/pattern-nav.html deleted file mode 100644 index a3b17fae2..000000000 --- a/packages/uikit-workshop/src/html/partials/pattern-nav.html +++ /dev/null @@ -1,59 +0,0 @@ -{{# patternTypes }} -
  • - - - -
      - - {{# patternTypeItems }} -
    1. - - - -
        - - {{# patternSubtypeItems }} -
      1. - - - {{ patternName }} - - {{# patternState }} - - {{/ patternState }} - - - -
      2. - {{/ patternSubtypeItems }} - -
      - -
    2. - {{/ patternTypeItems }} - {{# patternItems }} -
    3. - - - {{ patternName }} - - {{# patternState }} - - {{/ patternState }} - - - -
    4. - {{/ patternItems }} - -
    - -
  • -{{/ patternTypes }} - -
  • - - All - -
  • - diff --git a/packages/uikit-workshop/src/icons/arrow-down.svg b/packages/uikit-workshop/src/icons/arrow-down.svg new file mode 100644 index 000000000..510ce6bdc --- /dev/null +++ b/packages/uikit-workshop/src/icons/arrow-down.svg @@ -0,0 +1,5 @@ + + +arrow_drop_down + + diff --git a/packages/uikit-workshop/src/icons/close.svg b/packages/uikit-workshop/src/icons/close.svg new file mode 100644 index 000000000..efa3715ff --- /dev/null +++ b/packages/uikit-workshop/src/icons/close.svg @@ -0,0 +1,5 @@ + + +close + + diff --git a/packages/uikit-workshop/src/icons/code-collapse.svg b/packages/uikit-workshop/src/icons/code-collapse.svg new file mode 100644 index 000000000..10e66e73a --- /dev/null +++ b/packages/uikit-workshop/src/icons/code-collapse.svg @@ -0,0 +1,6 @@ + +hide-code + + + + diff --git a/packages/uikit-workshop/src/icons/code-expand.svg b/packages/uikit-workshop/src/icons/code-expand.svg new file mode 100644 index 000000000..feb7446ce --- /dev/null +++ b/packages/uikit-workshop/src/icons/code-expand.svg @@ -0,0 +1,5 @@ + +show-code + + + \ No newline at end of file diff --git a/packages/uikit-workshop/src/icons/copy.svg b/packages/uikit-workshop/src/icons/copy.svg new file mode 100644 index 000000000..5354f8d85 --- /dev/null +++ b/packages/uikit-workshop/src/icons/copy.svg @@ -0,0 +1,4 @@ + +copy + + \ No newline at end of file diff --git a/packages/uikit-workshop/src/icons/desktop.svg b/packages/uikit-workshop/src/icons/desktop.svg new file mode 100644 index 000000000..48c9f6f11 --- /dev/null +++ b/packages/uikit-workshop/src/icons/desktop.svg @@ -0,0 +1,5 @@ + + +desktop_mac + + diff --git a/packages/uikit-workshop/src/icons/disco-ball.svg b/packages/uikit-workshop/src/icons/disco-ball.svg new file mode 100644 index 000000000..6ec7b3bfb --- /dev/null +++ b/packages/uikit-workshop/src/icons/disco-ball.svg @@ -0,0 +1,15 @@ + + + + Artboard + Created with Sketch. + + + + + + + + + + diff --git a/packages/uikit-workshop/src/icons/hay.svg b/packages/uikit-workshop/src/icons/hay.svg new file mode 100644 index 000000000..466695e0d --- /dev/null +++ b/packages/uikit-workshop/src/icons/hay.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uikit-workshop/src/icons/help.svg b/packages/uikit-workshop/src/icons/help.svg new file mode 100644 index 000000000..016e9271a --- /dev/null +++ b/packages/uikit-workshop/src/icons/help.svg @@ -0,0 +1,5 @@ + + +help_outline + + diff --git a/packages/uikit-workshop/src/icons/hide.svg b/packages/uikit-workshop/src/icons/hide.svg new file mode 100644 index 000000000..f9513c403 --- /dev/null +++ b/packages/uikit-workshop/src/icons/hide.svg @@ -0,0 +1,5 @@ + + +view-hide + + diff --git a/packages/uikit-workshop/src/icons/laptop.svg b/packages/uikit-workshop/src/icons/laptop.svg new file mode 100644 index 000000000..23da41cca --- /dev/null +++ b/packages/uikit-workshop/src/icons/laptop.svg @@ -0,0 +1,5 @@ + + +laptop_mac + + diff --git a/packages/uikit-workshop/src/icons/layout-h.svg b/packages/uikit-workshop/src/icons/layout-h.svg new file mode 100644 index 000000000..4878499d2 --- /dev/null +++ b/packages/uikit-workshop/src/icons/layout-h.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uikit-workshop/src/icons/layout-v.svg b/packages/uikit-workshop/src/icons/layout-v.svg new file mode 100644 index 000000000..9110dfa84 --- /dev/null +++ b/packages/uikit-workshop/src/icons/layout-v.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uikit-workshop/src/icons/menu.svg b/packages/uikit-workshop/src/icons/menu.svg new file mode 100644 index 000000000..98be1018e --- /dev/null +++ b/packages/uikit-workshop/src/icons/menu.svg @@ -0,0 +1,5 @@ + + +menu + + diff --git a/packages/uikit-workshop/src/icons/new-tab.svg b/packages/uikit-workshop/src/icons/new-tab.svg new file mode 100644 index 000000000..9c0db76d1 --- /dev/null +++ b/packages/uikit-workshop/src/icons/new-tab.svg @@ -0,0 +1,5 @@ + + +open_in_new + + diff --git a/packages/uikit-workshop/src/icons/phone.svg b/packages/uikit-workshop/src/icons/phone.svg new file mode 100644 index 000000000..82b40fe84 --- /dev/null +++ b/packages/uikit-workshop/src/icons/phone.svg @@ -0,0 +1,5 @@ + + +phone_iphone + + diff --git a/packages/uikit-workshop/src/icons/random.svg b/packages/uikit-workshop/src/icons/random.svg new file mode 100644 index 000000000..c42db187a --- /dev/null +++ b/packages/uikit-workshop/src/icons/random.svg @@ -0,0 +1,11 @@ + + + + casino + Created with Sketch. + + + + + + \ No newline at end of file diff --git a/packages/uikit-workshop/src/icons/settings.svg b/packages/uikit-workshop/src/icons/settings.svg new file mode 100644 index 000000000..49197cb34 --- /dev/null +++ b/packages/uikit-workshop/src/icons/settings.svg @@ -0,0 +1,5 @@ + + +settings + + diff --git a/packages/uikit-workshop/src/icons/show.svg b/packages/uikit-workshop/src/icons/show.svg new file mode 100644 index 000000000..3377c33bf --- /dev/null +++ b/packages/uikit-workshop/src/icons/show.svg @@ -0,0 +1,5 @@ + + +view-show + + diff --git a/packages/uikit-workshop/src/icons/tablet.svg b/packages/uikit-workshop/src/icons/tablet.svg new file mode 100644 index 000000000..d85d35301 --- /dev/null +++ b/packages/uikit-workshop/src/icons/tablet.svg @@ -0,0 +1,5 @@ + + +tablet_mac + + diff --git a/packages/uikit-workshop/src/icons/theme-dark.svg b/packages/uikit-workshop/src/icons/theme-dark.svg new file mode 100644 index 000000000..9589bfd5d --- /dev/null +++ b/packages/uikit-workshop/src/icons/theme-dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/uikit-workshop/src/icons/theme-light.svg b/packages/uikit-workshop/src/icons/theme-light.svg new file mode 100644 index 000000000..e8f54f0a9 --- /dev/null +++ b/packages/uikit-workshop/src/icons/theme-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uikit-workshop/src/images/pattern-lab-logo--on-dark.svg b/packages/uikit-workshop/src/images/pattern-lab-logo--on-dark.svg new file mode 100644 index 000000000..59cc46b0a --- /dev/null +++ b/packages/uikit-workshop/src/images/pattern-lab-logo--on-dark.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/uikit-workshop/src/images/pattern-lab-logo--on-light.svg b/packages/uikit-workshop/src/images/pattern-lab-logo--on-light.svg new file mode 100644 index 000000000..549f60c02 --- /dev/null +++ b/packages/uikit-workshop/src/images/pattern-lab-logo--on-light.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/uikit-workshop/src/sass/pattern-lab--iframe-loader.scss b/packages/uikit-workshop/src/sass/pattern-lab--iframe-loader.scss index b23c481bc..7f72c956b 100644 --- a/packages/uikit-workshop/src/sass/pattern-lab--iframe-loader.scss +++ b/packages/uikit-workshop/src/sass/pattern-lab--iframe-loader.scss @@ -1,17 +1,6 @@ @import 'scss/01-abstracts/variables'; @import 'scss/01-abstracts/mixins'; -@keyframes animateIn { - from { - transform: translate3d(-50%, -100%, 0px); - opacity: 0; - } - to { - opacity: 1; - transform: translate3d(-50%, calc(3rem - 50%), 0px); - } -} - @keyframes rotate { 0% { transform: rotate(0deg); @@ -21,21 +10,34 @@ } } +.pl-c-loader-wrapper { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.pl-c-loader-wrapper:not(:last-child) { + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease, transform 0.2s ease; +} + .pl-c-loader { z-index: 1000; position: absolute; - top: 0; + top: 50%; left: 50%; margin: auto; max-width: $pl-space * 25; width: calc(90vw - #{$pl-doublespace}); border-radius: $pl-border-radius; background: rgba($pl-color-black, 0.9); - transform: translate3d(-50%, -100%, 0px); + transform: translate3d(-50%, -50%, 0px); transition: opacity 0.3s ease, transform 0.3s ease; pointer-events: none; - opacity: 0; - animation: animateIn ease 0.3s forwards; + opacity: 1; } .pl-c-loader__content { diff --git a/packages/uikit-workshop/src/sass/pattern-lab.scss b/packages/uikit-workshop/src/sass/pattern-lab.scss index d38ba1515..ebd3d02a3 100755 --- a/packages/uikit-workshop/src/sass/pattern-lab.scss +++ b/packages/uikit-workshop/src/sass/pattern-lab.scss @@ -43,39 +43,84 @@ /*------------------------------------*\ #COMPONENTS \*------------------------------------*/ - -/** - * Pattern Lab Header - */ +@import '../scripts/components/pl-nav/index.scss'; @import '../scripts/components/pl-search/pl-search.scss'; -@import '../scripts/components/pl-layout/pl-layout.scss'; -@import 'scss/04-components/header'; -@import 'scss/04-components/logo'; -@import 'scss/04-components/navigation'; -@import 'scss/04-components/ish-sizing'; -@import 'scss/04-components/controls'; -@import 'scss/04-components/tools'; - -/** - * Viewport - */ -@import 'scss/04-components/viewport'; - -/** - * Pattern Styles - */ -@import 'scss/04-components/pattern'; +@import 'scss/04-components/annotations'; +@import 'scss/04-components/annotations-inside-modal'; +@import 'scss/04-components/breadcrumbs'; @import 'scss/04-components/pattern-category'; @import 'scss/04-components/pattern-info'; -@import 'scss/04-components/pattern-states'; @import 'scss/04-components/pattern-lineage'; -@import 'scss/04-components/breadcrumbs'; +@import 'scss/04-components/pattern-states'; +@import 'scss/04-components/pattern'; @import 'scss/04-components/tabs'; -@import 'scss/04-components/tools'; -@import 'scss/04-components/annotations'; -@import 'scss/04-components/modal'; @import 'scss/04-components/text-passage'; +.pl-c-code-copy-btn { + display: inline-block; + position: absolute; + top: 0.4rem; + right: 0.5rem; + padding: 0.2rem 0.4rem; + background-color: $pl-color-gray-07; + color: $pl-color-gray-87; + border: 1px solid $pl-color-gray-13; + border-radius: $pl-border-radius-med; + font-family: $pl-font; + font-size: $pl-font-size-norm; + text-transform: lowercase; + line-height: 1; + cursor: pointer; + z-index: 2; + transition: background-color $pl-animate-quick ease-out; + + &:hover, + &:focus { + background-color: $pl-color-gray-20; + } +} + +.pl-c-code-copy-btn__icon { + height: 1em; + width: 1em; +} + +.pl-c-code-copy-btn__icon--paste { + display: none; + + .is-copied & { + display: inline-block; + } +} + +.pl-c-code-copy-btn__icon--copy { + display: inline-block; + + .is-copied & { + display: none; + } +} + +.pl-c-body { + overflow: hidden; +} + +.pl-c-main { + // Preventing cropping pattern parts #1174 - absolutely positioned pattern parts at the vertical end of the "page" would get cropped elsewhere + min-height: 100vh; + + max-width: 100vw; + padding-left: 0.5rem; + padding-right: 0.5rem; + + // Clearing all remaining floats + &::after { + clear: both; + content: ''; + display: table; + } +} + /*------------------------------------*\ #THEMES \*------------------------------------*/ diff --git a/packages/uikit-workshop/src/sass/scss/01-abstracts/_mixins.scss b/packages/uikit-workshop/src/sass/scss/01-abstracts/_mixins.scss index c06101c06..14dfc5a6d 100644 --- a/packages/uikit-workshop/src/sass/scss/01-abstracts/_mixins.scss +++ b/packages/uikit-workshop/src/sass/scss/01-abstracts/_mixins.scss @@ -27,8 +27,8 @@ * Header Link Style */ @mixin linkStyle() { - background-color: $pl-color-black; - color: $pl-color-gray-50; + @include noSelect; + color: inherit; text-decoration: none; line-height: 1; padding: 0.7rem 0.5rem; @@ -37,38 +37,15 @@ transition: background-color $pl-animate-quick ease-out, color $pl-animate-quick ease-out; cursor: pointer; - outline-offset: -3px; - outline-width: 2px; - &:hover { - color: $pl-color-white; - background-color: $pl-color-gray-87; - } - - &.pl-is-active, - &:active { - color: $pl-color-white; - background-color: $pl-color-gray-87; - outline: 1px dotted $pl-color-gray-50; - outline-offset: -1px; + &:hover, + &.pl-is-active:hover { + background-color: rgba(0, 0, 0, 0.1); } /** * Header link styles inside light theme */ - .pl-c-body--theme-light & { - background-color: $pl-color-white; - color: $pl-color-gray-70; - - &:hover { - background-color: $pl-color-gray-07; - } - - &:active, - &:focus { - background-color: $pl-color-gray-13; - } - } /** * Header link styles inside cozy theme @@ -93,16 +70,16 @@ @mixin accordionPanel() { overflow: hidden; max-height: 0; - transition: max-height $pl-animate-quick ease-out; + transition: all $pl-animate-quick ease-out; /** * Active styles for when the accordion panel is open * 1. WIP -- part of broader UI refactor */ &.pl-is-active { - max-height: calc(100vh - #{$offset-top} - 1rem); + max-height: calc(95vh - #{$offset-top} - 1rem); max-height: calc( - var(--pl-viewport-height, calc(100vh - #{$offset-top})) - 1rem + var(--pl-viewport-height, calc(95vh - #{$offset-top})) - 1rem ); /* [1] */ overflow: auto; -webkit-overflow-scrolling: touch; @@ -115,3 +92,56 @@ -ms-user-select: none; /* IE 10+ */ user-select: none; /* Likely future */ } + +@mixin buttonStyles() { + color: inherit; + text-decoration: none; + background: transparent; + border: 0; + appearance: none; + display: flex; + align-items: center; + width: 100%; + margin: 0; + flex-direction: row-reverse; + justify-content: flex-end; + cursor: pointer; + position: relative; + min-width: 30px; + + &::after { + content: ''; + display: block; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + pointer-events: none; + opacity: 0; + transition: opacity 0.1s ease; + background-color: currentColor; + } + + // &:focus, + &:hover { + &::after { + opacity: 0.1; + } + } + + &:active:hover { + &::after { + opacity: 0.2; + } + } + + &:focus { + outline: 1px dotted; + outline-offset: -1px; + + &::after { + opacity: 0.1; + } + } +} diff --git a/packages/uikit-workshop/src/sass/scss/01-abstracts/_variables.scss b/packages/uikit-workshop/src/sass/scss/01-abstracts/_variables.scss index 364b3aab4..726c96110 100644 --- a/packages/uikit-workshop/src/sass/scss/01-abstracts/_variables.scss +++ b/packages/uikit-workshop/src/sass/scss/01-abstracts/_variables.scss @@ -14,6 +14,7 @@ $pl-color-gray-07: #eee; $pl-color-gray-13: #ddd; $pl-color-gray-20: #ccc; $pl-color-gray-50: #808080; +$pl-color-gray-55: #737373; $pl-color-gray-70: #4d4c4c; $pl-color-gray-87: #222; $pl-color-black: #000; @@ -23,13 +24,14 @@ $pl-color-trans-white-25: rgba(255, 255, 255, 0.25); $pl-color-state-info: #02a4d5; $pl-color-state-complete: #03790f; $pl-color-state-inreview: #c7a118; +$pl-color-state-inprogress: #b00b02; $pl-color-state-deprecated: #b00b02; // Font Family -$pl-font: 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif; +$pl-font: 'Open Sans', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif !default; // Font sizes -$pl-font-size-sm: 0.7rem; +$pl-font-size-sm: 0.9rem; $pl-font-size-sm-2: 0.85rem; $pl-font-size-norm: 1rem; $pl-font-size-large: 1.2rem; @@ -38,7 +40,7 @@ $pl-font-size-large: 1.2rem; $pl-space: 1rem; $pl-doublespace: $pl-space * 2; $pl-pad: 1rem; -$pl-pad-half: $pl-pad/2; +$pl-pad-half: $pl-pad * 0.5; $offset-top: 2rem; // Breakpoints @@ -54,5 +56,4 @@ $pl-animate-normal: 0.3s; $pl-border-radius: 3px; $pl-border-radius-med: 6px; - -$pl-sidebar-width: 14rem; //Define sidebar width for calculating dimensions \ No newline at end of file +$pl-sidebar-width: 16rem; //Define sidebar width for calculating dimensions diff --git a/packages/uikit-workshop/src/sass/scss/02-base/_body.scss b/packages/uikit-workshop/src/sass/scss/02-base/_body.scss index 90bc557f0..c39879cd6 100644 --- a/packages/uikit-workshop/src/sass/scss/02-base/_body.scss +++ b/packages/uikit-workshop/src/sass/scss/02-base/_body.scss @@ -9,11 +9,33 @@ */ .pl-c-html { min-height: 100%; + display: flex; + height: 100%; // fix for IE 11 } .pl-c-body { margin: 0; padding: 0; + width: 100%; -webkit-text-size-adjust: 100%; display: flex; // Required for IE 11 to display overall PL layout correctly } + +.pl-c-body--theme-dark, +:root { + --theme-bg: #161b3c; + --theme-primary: #464a6d; + --theme-secondary: #161f50; + --theme-text: white; + --theme-text-rgb: 255, 255, 255; + --theme-border: rgba(255, 255, 255, 0.2); +} + +.pl-c-body--theme-light { + --theme-bg: white; + --theme-secondary: white; + --theme-text: #262829; + --theme-text-rgb: 38, 40, 41; + --theme-primary: white; + --theme-border: #ddd; +} diff --git a/packages/uikit-workshop/src/sass/scss/02-base/_reset.scss b/packages/uikit-workshop/src/sass/scss/02-base/_reset.scss index 735a18995..3c9ffa270 100644 --- a/packages/uikit-workshop/src/sass/scss/02-base/_reset.scss +++ b/packages/uikit-workshop/src/sass/scss/02-base/_reset.scss @@ -16,7 +16,7 @@ box-sizing: border-box; } -button { +button[class|='pl-c'] { font-size: inherit; background-color: transparent; } diff --git a/packages/uikit-workshop/src/sass/scss/03-vendor/_prism.scss b/packages/uikit-workshop/src/sass/scss/03-vendor/_prism.scss index 6ab0ba455..ea440b16b 100644 --- a/packages/uikit-workshop/src/sass/scss/03-vendor/_prism.scss +++ b/packages/uikit-workshop/src/sass/scss/03-vendor/_prism.scss @@ -1,184 +1,211 @@ -/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+handlebars+php+php-extras+twig&plugins=line-numbers+autolinker */ +/* https://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+handlebars+php+php-extras+twig&plugins=line-numbers+autolinker */ /** * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) + * Based on dabblet (https://dabblet.com) * @author Lea Verou */ +.pl-c-tabs__panel { + pre[class*='language-'] { + background-image: linear-gradient( + to right, + $pl-color-white, + rgba($pl-color-white, 0) + ), + linear-gradient(to left, $pl-color-white, rgba($pl-color-white, 0)), + linear-gradient(to right, #eaf0f6, rgba($pl-color-gray-07, 0)), + linear-gradient(to left, #eaf0f6, rgba($pl-color-gray-07, 0)), + linear-gradient(to bottom, $pl-color-white, rgba($pl-color-white, 0)), + linear-gradient(to top, $pl-color-white, rgba($pl-color-white, 0)), + linear-gradient(to bottom, #eaf0f6, rgba($pl-color-gray-07, 0)), + linear-gradient(to top, #eaf0f6, rgba($pl-color-gray-07, 0)); + background-color: $pl-color-white; + background-attachment: local, local, scroll, scroll, local, local, scroll, + scroll; + background-position: 0 0, 100% 0, 0 0, 100% 0, 0 0, 0 100%, 0 0, 0 100%; + background-size: 4em 100%, 4em 100%, 1em 100%, 1em 100%, 100% 4em, 100% 4em, + 100% 1em, 100% 1em; + background-repeat: no-repeat; + -ms-overflow-style: -ms-autohiding-scrollbar; + -webkit-overflow-scrolling: touch; + overflow: auto; + max-height: 100%; + } -code[class*='language-'], -pre[class*='language-'] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - line-height: 1.5; - word-wrap: normal; // fixes issue in Safari where code blocks can't scroll due to the code breaking into multiple lines unexpectedly - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*='language-']::-moz-selection, -pre[class*='language-'] ::-moz-selection, -code[class*='language-']::-moz-selection, -code[class*='language-'] ::-moz-selection { - text-shadow: none; - background-color: #b3d4fc; -} - -pre[class*='language-']::selection, -pre[class*='language-'] ::selection, -code[class*='language-']::selection, -code[class*='language-'] ::selection { - text-shadow: none; - background-color: #b3d4fc; -} - -@media print { code[class*='language-'], pre[class*='language-'] { + color: black; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + line-height: 1.5; + word-wrap: normal; // fixes issue in Safari where code blocks can't scroll due to the code breaking into multiple lines unexpectedly + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } + + pre[class*='language-']::-moz-selection, + pre[class*='language-'] ::-moz-selection, + code[class*='language-']::-moz-selection, + code[class*='language-'] ::-moz-selection { text-shadow: none; + background-color: #b3d4fc; } -} -/* Code blocks */ -pre[class*='language-'] { - padding: 1em; - margin: 0.5em 0; - overflow: auto; -} + pre[class*='language-']::selection, + pre[class*='language-'] ::selection, + code[class*='language-']::selection, + code[class*='language-'] ::selection { + text-shadow: none; + background-color: #b3d4fc; + } -:not(pre) > code[class*='language-'], -pre[class*='language-'] { - background-color: #f5f2f0; -} + @media print { + code[class*='language-'], + pre[class*='language-'] { + text-shadow: none; + } + } -/* Inline code */ -:not(pre) > code[class*='language-'] { - padding: 0.1em; - border-radius: 0.3em; -} + /* Code blocks */ + pre[class*='language-'] { + padding: 1em; + margin: 0.5em 0; + overflow: scroll; + } -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} + :not(pre) > code[class*='language-'], + pre[class*='language-'] { + background-color: #f5f2f0; + } -.token.punctuation { - color: #999; -} + /* Inline code */ + :not(pre) > code[class*='language-'] { + padding: 0.1em; + border-radius: 0.3em; + } -.namespace { - opacity: 0.7; -} + .token.comment, + .token.prolog, + .token.doctype, + .token.cdata { + color: slategray; + } -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol, -.token.deleted { - color: #905; -} + .token.punctuation { + color: #999; + } -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin, -.token.inserted { - color: #690; -} + .namespace { + opacity: 0.7; + } -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #a67f59; - background-color: hsla(0, 0%, 100%, 0.5); -} + .token.property, + .token.tag, + .token.boolean, + .token.number, + .token.constant, + .token.symbol, + .token.deleted { + color: #905; + } -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} + .token.selector, + .token.attr-name, + .token.string, + .token.char, + .token.builtin, + .token.inserted { + color: #690; + } -.token.function { - color: #dd4a68; -} + .token.operator, + .token.entity, + .token.url, + .language-css .token.string, + .style .token.string { + color: #a67f59; + background-color: hsla(0, 0%, 100%, 0.5); + } -.token.regex, -.token.important, -.token.variable { - color: #e90; -} + .token.atrule, + .token.attr-value, + .token.keyword { + color: #07a; + } -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} + .token.function { + color: #dd4a68; + } -.token.entity { - cursor: help; -} + .token.regex, + .token.important, + .token.variable { + color: #e90; + } -pre.line-numbers { - position: relative; - padding-left: 3.8em; - counter-reset: linenumber; -} + .token.important, + .token.bold { + font-weight: bold; + } + .token.italic { + font-style: italic; + } -pre.line-numbers > code { - position: relative; -} + .token.entity { + cursor: help; + } -.line-numbers .line-numbers-rows { - position: absolute; - pointer-events: none; - top: 0; - font-size: 100%; - left: -3.8em; - width: 3em; /* works for line-numbers below 1000 lines */ - letter-spacing: -1px; - border-right: 1px solid #999; - - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} + pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; + } -.line-numbers-rows > span { - pointer-events: none; - display: block; - counter-increment: linenumber; -} + pre.line-numbers > code { + position: relative; + } -.line-numbers-rows > span:before { - content: counter(linenumber); - color: #999; - display: block; - padding-right: 0.8em; - text-align: right; -} -.token a { - color: inherit; + .line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span::before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } + .token a { + color: inherit; + } } diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_annotations-inside-modal.scss b/packages/uikit-workshop/src/sass/scss/04-components/_annotations-inside-modal.scss new file mode 100644 index 000000000..f5f319c28 --- /dev/null +++ b/packages/uikit-workshop/src/sass/scss/04-components/_annotations-inside-modal.scss @@ -0,0 +1,75 @@ +@charset "UTF-8"; + +/*------------------------------------*\ + #ANNOTATIONS INSIDE MODAL +\*------------------------------------*/ + +/** + * Annotations area + * 1) Appears inside of modal + */ +.pl-c-annotations { + margin: 1rem 0; +} + +/** + * Annotations Title + * Says the word "Annotations" + */ +.pl-c-annotations__title { + font-size: 1.2rem !important; + margin: 0 0 0.5rem; +} + +/** + * Annotations list + * 1) Ordered list of annotations + * 2) Presented with parent selector to force styles + * over pl-c-text-passage + */ +.pl-c-annotations .pl-c-annotations__list { + counter-reset: the-count; + padding: 0; + margin: 0; + list-style: none; +} + +/** + * Annotations list item + * 1) Displays each item as a number + */ +.pl-c-annotations__item { + position: relative; + padding-left: 1.5rem; + margin-bottom: 1rem; + border-radius: $pl-border-radius-med; + transition: background-color $pl-animate-quick ease; + + &::before { + content: counter(the-count); + counter-increment: the-count; + font-size: 85%; + display: flex; + align-items: center; + justify-content: center; + width: 14px; + height: 14px; + border-radius: 50%; + padding: 2px; + text-align: center; + background-color: $pl-color-gray-50; + color: $pl-color-white; + position: absolute; + top: 4px; + left: 0; + } + + &.pl-is-active { + outline: 1px dotted $pl-color-gray-50; + outline-offset: -1px; + } +} + +.pl-c-annotations .pl-c-annotations__item-title { + margin-bottom: 0; +} diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_annotations.scss b/packages/uikit-workshop/src/sass/scss/04-components/_annotations.scss index 57c32f781..0939ab8d4 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_annotations.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_annotations.scss @@ -36,12 +36,12 @@ /** * Annotation tooltip * 1) Appears inside the iframe over any element that has an - * anootation attached to it. - * 2) Annotation tip gets dynamically set to `display: none` via - * JavaScript + * annotation attached to it. */ .pl-c-annotation-tip { - display: flex; /* 2 */ + &:not([hidden]) { + display: flex; + } align-items: center; justify-content: center; width: 24px !important; @@ -55,77 +55,3 @@ position: absolute; z-index: 100; } - -/*------------------------------------*\ - #ANNOTATIONS INSIDE MODAL -\*------------------------------------*/ - -/** - * Annotations area - * 1) Appears inside of modal - */ -.pl-c-annotations { - margin: 1rem 0; -} - -/** - * Annotations Title - * Says the word "Annotations" - */ -.pl-c-annotations__title { - font-size: 1.2rem !important; - margin: 0 0 0.5rem; -} - -/** - * Annotations list - * 1) Ordered list of annotations - * 2) Presented with parent selector to force styles - * over pl-c-text-passage - */ -.pl-c-annotations .pl-c-annotations__list { - counter-reset: the-count; - padding: 0; - margin: 0; - list-style: none; -} - -/** - * Annotations list item - * 1) Displays each item as a number - */ -.pl-c-annotations__item { - position: relative; - padding-left: 1.5rem; - margin-bottom: 1rem; - border-radius: $pl-border-radius-med; - transition: background-color $pl-animate-quick ease; - - &:before { - content: counter(the-count); - counter-increment: the-count; - font-size: 85%; - display: flex; - align-items: center; - justify-content: center; - width: 14px; - height: 14px; - border-radius: 50%; - padding: 2px; - text-align: center; - background-color: $pl-color-gray-50; - color: $pl-color-white; - position: absolute; - top: 4px; - left: 0; - } - - &.pl-is-active { - outline: 1px dotted $pl-color-gray-50; - outline-offset: -1px; - } -} - -.pl-c-annotations .pl-c-annotations__item-title { - margin-bottom: 0; -} diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_breadcrumbs.scss b/packages/uikit-workshop/src/sass/scss/04-components/_breadcrumbs.scss index ae1cb8f19..bf5cf134a 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_breadcrumbs.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_breadcrumbs.scss @@ -12,7 +12,7 @@ margin-bottom: 0.5rem; display: flex; font-size: $pl-font-size-sm; - color: $pl-color-gray-50; + color: inherit; text-transform: capitalize; } @@ -20,7 +20,8 @@ * Breadcrumb Item */ .pl-c-breadcrumb__item { - &:after { + color: inherit; + &::after { content: '\25b6'; opacity: 0.4; font-size: 6px; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_controls.scss b/packages/uikit-workshop/src/sass/scss/04-components/_controls.scss deleted file mode 100644 index 6a6a9e479..000000000 --- a/packages/uikit-workshop/src/sass/scss/04-components/_controls.scss +++ /dev/null @@ -1,29 +0,0 @@ -/*------------------------------------*\ - #CONTROLS -\*------------------------------------*/ - -/** - * 1) Controls contains viewport resizer and tools dropdown - * 2) Right-align inside of header - */ -.pl-c-controls { - margin-left: auto; /* 2 */ - display: flex; - flex-wrap: nowrap; - - // IE 11 layout bug - @media all and (min-width: $pl-bp-med) { - .pl-c-body--theme-sidebar & { - display: block; - } - } -} - -/** -* Control list -*/ -.pl-c-controls__list { - @include listReset(); - display: flex; - flex-wrap: nowrap; -} diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_header.scss b/packages/uikit-workshop/src/sass/scss/04-components/_header.scss deleted file mode 100644 index 2616b678f..000000000 --- a/packages/uikit-workshop/src/sass/scss/04-components/_header.scss +++ /dev/null @@ -1,43 +0,0 @@ -/*------------------------------------*\ - #HEADER -\*------------------------------------*/ - -/** -* 1) Pattern Lab's header is fixed across the top of the viewport and -* contains the primary pattern navigation, viewport resizing items, -* and tools. -* 2) Display nav and controls horizontally -*/ -.pl-c-header { - position: fixed; - position: sticky; - top: 0; - left: 0; - z-index: 4; - display: flex; /* 2 */ - width: 100%; - background-color: $pl-color-black; - color: $pl-color-gray-50; - font-family: $pl-font; - font-size: $pl-font-size-sm; - min-height: 30px; // magic number -- needed for initial skeleton screen styles used in the critical CSS - - @supports(padding: max(0px)) { - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); - } -} - -/** - * Nav toggle button - * 1) Styles for the general nav toggle button, which - * only appears on small screens - */ -.pl-c-header__nav-toggle { - @include linkStyle(); - border: 0; - - @media all and (min-width: $pl-bp-med) { - display: none; - } -} diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_navigation.scss b/packages/uikit-workshop/src/sass/scss/04-components/_navigation.scss deleted file mode 100644 index ee71746b4..000000000 --- a/packages/uikit-workshop/src/sass/scss/04-components/_navigation.scss +++ /dev/null @@ -1,254 +0,0 @@ -/*------------------------------------*\ - #NAVIGATION -\*------------------------------------*/ - -/** - * Navigation container - * 1) Collapse height on small screens. Menu trigger button - * activates nav - */ -.pl-c-nav { - @include accordionPanel; - background-color: inherit; // allows the nav's children inherit from the parent header - position: absolute; - left: 0; // IE 11 layout broken - top: 100%; - width: 100%; - display: flex; - flex-direction: column; - transition: max-height $pl-animate-quick ease-out; - - // if nav was opened on smaller screen and screen is resized, it'll be cut off otherwise - @media all and (min-width: $pl-bp-med) { - overflow: visible; - max-height: none; - } - - /** - * Active navigaiton - * 1) Slide - * 2) Set the height to the vierport height minus the height - * of the header - */ - &.pl-is-active { - box-shadow: 0 1px 1px $pl-color-black; - - .pl-c-body--theme-light & { - box-shadow: 0 1px 1px darken($pl-color-gray-20, 15%); - } - - .pl-c-body--theme-sidebar & { - @media all and (min-width: $pl-bp-med) { - box-shadow: none; - } - } - - // if nav was opened on smaller screen and screen is resized, it'll be cut off otherwise - @media all and (min-width: $pl-bp-med) { - overflow: visible; - max-height: none; - } - } - - @media all and (min-width: $pl-bp-med) { - flex-direction: row; - position: relative; - top: auto; - width: auto; - box-shadow: none; - } -} - -/** - * Nav list - * 1) appears as an
      - * 2) display as a horizontal list on larger screens - * 3) On small screens, move the nav list after the typeahead form field - */ -.pl-c-nav__list { - z-index: 1; - margin: 0; - padding: 0; - list-style: none; - flex-shrink: 0; // helps prevent top-level nav items from occasionally wrapping to multiple lines - order: 2; - background-color: inherit; // allows the nav's children inherit from the parent header - - @media all and (min-width: $pl-bp-med) { - display: flex; /* 2 */ - order: 1; - - // workaround to Firefox-specific flexbox quirk - .pl-c-body--theme-sidebar & { - display: block; - } - } -} - -/** - * Nav list item - */ -.pl-c-nav__item { - background-color: inherit; // allows the nav's children inherit from the parent header - transform: translateZ(0); // helps with more consistent rendering in Safari - cursor: pointer; - position: relative; - display: flex; - flex-direction: column; - justify-content: center; // vertically align nav items - - .pl-c-body--theme-sidebar & { - display: block; - } -} - -/** - * Last sublist item - */ -.pl-c-nav__sublist > .pl-c-nav__item:last-child { - @media all and (min-width: $pl-bp-med) { - overflow: hidden; - border-bottom-left-radius: $pl-border-radius-med; - border-bottom-right-radius: $pl-border-radius-med; - } -} - -/** - * Nav link - */ -.pl-c-nav__link { - @include linkStyle; - display: flex; - align-items: center; - margin: 0; // remove default button margin in Safari - - // makes link layout / size more consistent in the sidebar layout, especially when display: flex styles are removed for more consistent IE 11 rendering - .pl-c-body--theme-sidebar & { - width: 100%; - } -} - -/** - * Nav sublink - * 1) Visually differentiate sub-item links from - * the other links. Creates better hierarchy. - */ -.pl-c-nav__link--sublink { - text-transform: none; - padding-left: $pl-space / 2; -} - -/** - * Nav link - */ -.pl-c-nav__link--dropdown { - -webkit-appearance: none; // remove default button styling - flex-grow: 1; // fill up extra space in parent nav item, if available - /** - * Dropdown caret after accordion handle - */ - &:after { - content: '\25bc'; - color: $pl-color-trans-white-25; - display: inline-block; - font-size: 7px; - position: relative; - top: 1px; - right: -2px; - transition: all $pl-animate-quick ease-out; - } - - &:hover, - &:focus { - &:after { - color: $pl-color-gray-50; - } - } - - /** - * Active dropdown - */ - &.pl-is-active { - color: $pl-color-white; - background-color: $pl-color-gray-87; - - /** - * Caret rotation and positioning in active dropdown - */ - &:after { - color: $pl-color-gray-50; - transform: rotate(180deg); - } - } -} - -/** - * Nav sublist - * 1) On larger screens, display as dropdowns that - * hang over the header - */ -.pl-c-nav__sublist { - background-color: inherit; // allows the nav's children inherit from the parent header - @include listReset(); - - @media all and (min-width: $pl-bp-med) { - position: absolute; - top: 100%; /* 1 */ - left: 0; - min-width: 10rem; - border-bottom-left-radius: $pl-border-radius-med; - border-bottom-right-radius: $pl-border-radius-med; - } -} - -/** - * Dropdown sublist - */ -.pl-c-nav__sublist--dropdown, -.pl-c-nav__subsublist--dropdown { - @include listReset(); - @include accordionPanel(); - visibility: hidden; -} - -/** - * Dropdown sublist - * 1) Set the height to the viewport height minus the height of the header - */ -.pl-c-nav__sublist--dropdown.pl-is-active, -.pl-c-nav__subsublist--dropdown.pl-is-active { - margin-left: $pl-space / 2; - visibility: visible; - max-height: none; - - @media all and (min-width: $pl-bp-med) { - height: auto; - max-height: calc(100vh - #{$offset-top} - 1rem); /* 1 */ - } - - .pl-c-body--theme-sidebar & { - max-height: none; - } -} - -.pl-c-nav__sublist--dropdown.pl-is-active { - @media all and (min-width: $pl-bp-med) { - margin-left: 0; - border-width: 1px; - border-style: solid; - border-color: $pl-color-black; - - .pl-c-body--theme-light & { - border-color: $pl-color-gray-20; - } - } -} - -/** - * Sub-navigation - * 1) Third-level links are stylistically different - * than first and second nav links. - */ -.pl-c-nav__subsublist { - @include listReset(); -} diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss index abe9d6142..fbca575bb 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-category.scss @@ -10,11 +10,15 @@ */ .pl-c-category { margin-top: 6rem; - font: $pl-font !important; + font-family: $pl-font !important; &:first-of-type { margin-top: 2rem; } + + & + & { + margin-top: 2rem; + } } /** @@ -25,6 +29,10 @@ color: $pl-color-gray-87 !important; margin: 0 0 0.2rem; text-transform: capitalize; + + &:hover { + color: $pl-color-gray-70 !important; + } } /** @@ -32,6 +40,7 @@ */ .pl-c-category__title-link { transition: color $pl-animate-quick ease-out; + color: inherit; } /** diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-info.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-info.scss index 606ad8055..e0ca2aa26 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-info.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-info.scss @@ -10,29 +10,39 @@ .pl-c-pattern-info { flex-grow: 1; // fills space available when placed in the parent flex container display: flex; - flex-direction: row; - flex-flow: row wrap; - width: 100%; - overflow: auto; - -webkit-overflow-scrolling: touch; + flex-direction: column; /** * Pattern info inside the "view all" template */ .pl-c-pattern & { - max-height: 20rem; - min-height: 18rem; + max-height: 30rem; overflow: scroll; - @include hideScrollBar(); - display: flex; + display: block; -webkit-overflow-scrolling: touch; @media all and (min-width: $pl-bp-large) { max-height: none; height: 18rem; + display: flex; + flex-direction: row; overflow: visible; } } + + /** + * Pattern info inside modal + */ + .pl-c-drawer & { + overflow: auto; + -webkit-overflow-scrolling: touch; + flex-grow: 1; + + @media all and (min-width: $pl-bp-large) { + position: static; + flex-direction: row; + } + } } /** @@ -41,19 +51,56 @@ * Right side contains pattern code */ .pl-c-pattern-info__panel { - flex-basis: 40%; // fills up 100% if only one panel exists. using 40% vs 50% due to quirky behavior in IE 11 - padding-top: 1rem; - padding-right: 1rem; - padding-bottom: 0; - padding-left: 1rem; - margin-bottom: 1rem; - flex-grow: 1; - max-width: 100%; - min-width: 300px; // so panels stack automatically - display: inline-flex; + padding: 0.5rem; + flex-shrink: 0; // prevent panel from collapsing in height (especially on smaller screens like iPhone) + display: flex; flex-direction: column; - overflow: auto; - -webkit-overflow-scrolling: touch; + + pl-drawer & { + padding: 1rem; + } + + @media all and (min-width: $pl-bp-large) { + flex-basis: 50%; + flex-grow: 1; + padding: 1.5rem; + } +} + +/** + * Pattern Info Panel + * 1) Left panel that contains pattern title, lineage, description, annotations + */ +.pl-c-pattern-info__panel--info { + @media all and (min-width: $pl-bp-large) { + overflow: auto; + -webkit-overflow-scrolling: touch; + } + + @media all and (min-width: $pl-bp-xl) { + min-width: 50%; + } +} + +/** + * Pattern Code Panel + * 1) Right panel that displays the pattern's code (found in _tabs.scss) + * 2) Using a sibling selector because the pattern info isn't always present. + * The sibling selector allows the code panel to occupy the full width of + * the modal + * 1) Cap the height of the code panel in the modal + */ +.pl-c-pattern-info__panel--info + .pl-c-pattern-info__panel--code, +.pl-c-pattern-info__panel--code:first-child { + flex-grow: 1; + flex-shrink: 0; // so the code panel doesn't get chopped off accidently + min-width: 50%; +} + +.pl-c-pattern-info__panel--info + .pl-c-pattern-info__panel--code { + @media all and (max-width: $pl-bp-large) { + padding-top: 0; + } } /** @@ -68,7 +115,7 @@ */ .pl-c-pattern-info__title { font-size: 1.4rem !important; - font-weight: normal; + font-weight: bold; margin-top: 0; margin-bottom: 0; color: inherit; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-lineage.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-lineage.scss index a3e12f881..4587bc090 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-lineage.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-lineage.scss @@ -6,19 +6,19 @@ * Pattern Lineage info */ .pl-c-lineage { - font-size: $pl-font-size-sm-2; + font-size: $pl-font-size-norm; line-height: 1.7; margin-top: 0; } /** - * Lineage link + * Lineage link */ .pl-c-lineage__link { font-style: italic; - color: $pl-color-gray-50; + color: inherit; // light vs dark text text-decoration: underline; - display: inline-flex; + display: inline; align-items: center; transition: opacity $pl-animate-quick ease; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-states.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-states.scss index 42dcacb9e..d4b1f5f79 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern-states.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern-states.scss @@ -7,17 +7,12 @@ * in the dropdown navigation. */ .pl-c-pattern-state { - display: inline-block; - width: 5px; - height: 5px; - margin-left: 10px; - position: relative; - top: 5px; - left: 0; + width: 0.5em; + height: 0.5em; + margin-left: 0.5em; border-radius: 50%; + display: inline-block; background-color: $pl-color-state-info; - line-height: 4px; - text-indent: 10px; &--complete { background-color: $pl-color-state-complete; @@ -27,6 +22,10 @@ background-color: $pl-color-state-inreview; } + &--inprogress { + background-color: $pl-color-state-inprogress; + } + &--deprecated { background-color: $pl-color-state-deprecated; } @@ -35,6 +34,6 @@ /** * Complete state */ -.complete:before { +.complete::before { color: #03790f !important; } diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_pattern.scss b/packages/uikit-workshop/src/sass/scss/04-components/_pattern.scss index 2fb724e2f..e478185f9 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_pattern.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_pattern.scss @@ -24,7 +24,11 @@ padding: 0.5rem 0 0; line-height: 1.3; font-size: 90%; - color: $pl-color-gray-50; + color: $pl-color-gray-55; + + display: flex; + flex-wrap: wrap; + justify-content: space-between; &:empty { padding: 0; @@ -50,9 +54,9 @@ */ .pl-c-pattern__title-link { display: inline-flex; /* 1 */ - align-items: flex-start; /* 1 */ + align-items: center; /* 1 */ padding: $pl-pad 0 0.3rem; - color: $pl-color-gray-50 !important; + color: $pl-color-gray-55 !important; text-decoration: none; cursor: pointer; @@ -67,24 +71,21 @@ * 1) This is the button that twirls down extra pattern info */ .pl-c-pattern__extra-toggle { - font-size: 9px; - position: absolute; - bottom: -1px; - right: 0; - z-index: 1; - padding: 0.65em 0.65em 0.5em; - line-height: 1; - color: $pl-color-gray-50; + font-size: 0.8rem; + margin-bottom: -1px; + padding: 0.4rem 0.5rem; + padding-right: 1.75rem; + color: $pl-color-gray-55; background-color: transparent; + cursor: pointer; font-weight: normal; - border: 1px solid $pl-color-gray-13; - border-top-left-radius: $pl-border-radius-med; - border-top-right-radius: $pl-border-radius-med; - transition: background-color $pl-animate-quick ease-out; - - .pl-c-pattern__toggle-icon { - display: inline-block; - } + transition: all $pl-animate-quick ease-out; + font-family: $pl-font; + border-color: #ddd; + border-width: 1px; // fix for different browser defaults + border-style: solid; // fix for different browser defaults (ex. Safari) + display: flex; + align-items: center; &:hover, &:focus, @@ -95,16 +96,60 @@ &:focus { outline: 1px dotted $pl-color-gray-70; + outline-offset: -1px; } &.pl-is-active { border-bottom-color: $pl-color-gray-02; + } +} + +.pl-c-pattern__toggle-icon { + height: 0.9rem; + width: 0.9rem; + display: inline-block; + vertical-align: middle; + position: absolute; + right: 0.625rem; + transition: opacity 0.1s linear; +} + +.pl-c-pattern__toggle-icon--expand { + z-index: 1; + + .pl-is-active & { + opacity: 0; + } +} + +.pl-c-pattern__toggle-icon--collapse { + opacity: 0; + z-index: 2; + height: 1rem; + width: 1rem; + + .pl-is-active & { + opacity: 1; + } +} + +.pl-c-pattern__extra-toggle-text ~ svg { + margin-left: 0.25rem; +} + +.pl-c-pattern__extra-toggle-text--collapse { + display: none; + + .pl-is-active & { + display: inline-block; + } +} + +.pl-c-pattern__extra-toggle-text--expand { + display: inline-block; - .pl-c-pattern__toggle-icon { - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); - } + .pl-is-active & { + display: none; } } @@ -126,6 +171,6 @@ border: 1px solid $pl-color-gray-13; border-radius: $pl-border-radius-med; border-top-right-radius: 0; - max-height: 150rem; + max-height: 9999px; } } diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_tabs.scss b/packages/uikit-workshop/src/sass/scss/04-components/_tabs.scss index d1458283f..c1f7ee4e7 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_tabs.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_tabs.scss @@ -16,7 +16,7 @@ position: relative; display: flex; flex-direction: column; - overflow: hidden; + max-height: 100%; flex-grow: 1; } @@ -42,7 +42,7 @@ padding: 0.2rem 0.4rem; border: 1px solid transparent; border-radius: $pl-border-radius-med; - color: $pl-color-gray-50; + color: $pl-color-gray-55; background-color: $pl-color-white; cursor: pointer; text-decoration: none; @@ -65,14 +65,41 @@ } } +.pl-c-tabs__header { + position: sticky; + z-index: 1; // fix for Safari for iOS sticky header appearing to be below the scrollable content + top: 0px; + border-top: 1px solid #ddd; + margin-left: calc(-0.5rem - 1px); + margin-right: calc(-0.5rem - 1px); + padding-left: 0.5rem; + padding-right: 0.5rem; + border: 1px solid #ddd; + margin-bottom: 0.5rem; + margin-top: -1px; + background-color: inherit; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + /** * Tab Content * 1) Tab content contains the tab panels */ .pl-c-tabs__content { - overflow: auto; + flex-grow: 1; + flex-shrink: 1; + display: flex; + flex-basis: auto; -webkit-overflow-scrolling: touch; - padding-top: 0.5rem; + overflow-y: auto; // workaround to firefox background gradient overflow bug + + /** + * Tab content inside modal + */ + .pl-c-drawer & { + border: 0; + } } /** @@ -82,7 +109,8 @@ */ .pl-c-tabs__panel { display: none; - // min-height: 12rem; + width: 100%; + max-height: 100%; &.pl-is-active-tab { display: block; @@ -100,6 +128,8 @@ padding: 0; border: 0; display: block; + width: 100%; + min-height: 100%; } code[class*='language-'] { diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_text-passage.scss b/packages/uikit-workshop/src/sass/scss/04-components/_text-passage.scss index 208332563..0fa03d73d 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_text-passage.scss +++ b/packages/uikit-workshop/src/sass/scss/04-components/_text-passage.scss @@ -13,13 +13,17 @@ p { margin-top: 0; margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } } /** * Link within the text passage */ a { - color: $pl-color-gray-50; + color: $pl-color-gray-55; text-decoration: underline; transition: opacity $pl-animate-quick ease; @@ -132,4 +136,29 @@ li { margin-bottom: 0.5rem; } + + table { + width: 100%; + max-width: 100%; + border-collapse: collapse; + overflow-x: auto; + margin: 0.75rem auto; + } + + tr:nth-of-type(odd) { + background: $pl-color-gray-07; + } + + th { + background: $pl-color-gray-13; + color: black; + font-weight: bold; + } + + td, + th { + padding: 10px; + border: 1px solid $pl-color-gray-20; + text-align: left; + } } diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_tools.scss b/packages/uikit-workshop/src/sass/scss/04-components/_tools.scss deleted file mode 100644 index cc9d9b657..000000000 --- a/packages/uikit-workshop/src/sass/scss/04-components/_tools.scss +++ /dev/null @@ -1,71 +0,0 @@ -/*------------------------------------*\ - #TOOLS -\*------------------------------------*/ - -/** - * The tools dropdown contains more utilities such as show/hide - * pattern info and pattern search, and also links to open in a - * new window and view the documentation - */ -.pl-c-tools { - position: relative; - display: flex; -} - -/** - * Tools menu button - * 1) This is the button that contains the toggle and - * triggers the tools dropdown list - */ -.pl-c-tools__toggle { - @include linkStyle(); - margin: 0; - padding-top: 0.6rem; - padding-bottom: 0.5rem; - display: inline-flex; - align-items: center; - justify-content: center; - position: relative; - min-width: 30px; -} - -/** - * Tools Toggle SVG icon - * 1) Cog icon - * 2) Set the width and height of the icon to be the same height of font - */ -.pl-c-tools__toggle-icon { - transition: inherit; // inherit transition styles from parent toggle -} - -/** - * Tools dropdown list - */ -.pl-c-tools__list { - @include listReset(); - @include accordionPanel(); - position: absolute; - top: 100%; - right: 0; - z-index: 10; // make sure context dropdown z-index is higher than nav dropdown z-index - width: 10rem; - border-bottom-left-radius: $pl-border-radius-med; - border-bottom-right-radius: $pl-border-radius-med; -} - -/** - * Tools dropdown actions - * 1) Links and buttons inside of the tools dropdown - */ -.pl-c-tools__action { - @include linkStyle(); - display: flex; - align-items: center; - width: 100%; - margin: 0; -} - -// Make sure the text and icon align to the opposite ends -.pl-c-tools__action-icon { - margin-left: auto; -} diff --git a/packages/uikit-workshop/src/sass/scss/05-themes/_light-theme.scss b/packages/uikit-workshop/src/sass/scss/05-themes/_light-theme.scss index 038ae4390..541f67a9a 100644 --- a/packages/uikit-workshop/src/sass/scss/05-themes/_light-theme.scss +++ b/packages/uikit-workshop/src/sass/scss/05-themes/_light-theme.scss @@ -38,25 +38,10 @@ * Nav link dropdown */ .pl-c-nav__link--dropdown { - color: $pl-color-gray-70; - background-color: $pl-color-white; + color: inherit; - &:after { - color: $pl-color-gray-20; - } - } - - /** - * All Nav links inside of subnav dropdown - */ - - /** - * Last sublist item - */ - .pl-c-nav__sublist > .pl-c-nav__item:last-child .pl-c-nav__link { - @media all and (min-width: $pl-bp-med) { - border-bottom-left-radius: $pl-border-radius-med; - border-bottom-right-radius: $pl-border-radius-med; + &::after { + color: inherit; } } @@ -79,7 +64,6 @@ background-color: $pl-color-gray-13 !important; } - /** * Typeahead input */ @@ -101,20 +85,11 @@ } } - /** - * Modal inside a light theme - */ - .pl-c-modal { - background-color: $pl-color-white; - color: $pl-color-gray-70; - border-top: 1px solid $pl-color-gray-20; - } - /** * Modal close button * 1) Closes the modal popup */ - .pl-c-modal__close-btn, + .pl-c-drawer__close-btn, .pl-c-tools__action { background-color: $pl-color-white; diff --git a/packages/uikit-workshop/src/sass/scss/05-themes/_sidebar-theme.scss b/packages/uikit-workshop/src/sass/scss/05-themes/_sidebar-theme.scss index c271ad06a..1a4c129c7 100644 --- a/packages/uikit-workshop/src/sass/scss/05-themes/_sidebar-theme.scss +++ b/packages/uikit-workshop/src/sass/scss/05-themes/_sidebar-theme.scss @@ -8,106 +8,53 @@ */ .pl-c-body--theme-sidebar { /** - * Header - * 1) Set width to sidebar width defined above - * 2) Make header 100% of the viewport height - * 3) Stack header items on top of each other - * 4) void bottom border for light theme - */ + * Header + * 1) Set width to sidebar width defined above + * 2) Make header 100% of the viewport height + * 3) Stack header items on top of each other + * 4) void bottom border for light theme + */ .pl-c-header { width: $pl-sidebar-width; /* 1 */ height: 100vh; /* 2 */ + padding-top: 0.5rem; + padding-bottom: 0.5rem; flex-direction: column; /* 3 */ border-bottom: 0; /* 4 */ - padding: 1rem; - overflow: auto; - -webkit-overflow-scrolling: touch; justify-content: space-between; + --nav-item-height: 2.5rem; } /** - * Header within light theme - */ - &.pl-c-body--theme-light { - .pl-c-header { - border-right: 1px solid $pl-color-gray-20; - } - } - - /** - * Logo - */ - .pl-c-logo { - max-width: 7rem; - margin: 0 auto 1rem; - } - - /** - * Nav sub sub list - */ + * Nav sub sub list + */ .pl-c-nav { - display: block; + flex-grow: 1; flex-direction: column; + flex-flow: column-reverse; } /** - * Nav list - * 1) Stack main categories on top of each other - * 2) Put typeahead search above nav list - */ + * Nav list + * 1) Stack main categories on top of each other + * 2) Put typeahead search above nav list + */ .pl-c-nav__list { flex-direction: column; /* 1 */ order: 2; /* 2 */ } /** - * Nav sublist - */ + * Nav sublist + */ .pl-c-nav__sublist { position: relative; border-radius: 0; } /** - * Nav sublist - */ - .pl-c-nav__sublist .pl-c-nav__link { - padding-left: 1rem; - } - - /** - * Nav sublist - */ - .pl-c-nav__sublist--dropdown.pl-is-active { - border: 0; - border-left: 1px solid $pl-color-gray-70; - } - - /** - * Nav sublist inside the light theme - */ - &.pl-c-body--theme-light { - .pl-c-nav__sublist--dropdown.pl-is-active { - border-left-color: $pl-color-gray-07; - } - } - - /** - * Dropdown sublist - * 1) Undo fixed height - */ - - /** - * Nav sub sub list - */ - .pl-c-nav__subsublist { - border-left: 1px solid $pl-color-gray-70; - margin-left: 1rem; - } - - /** - * Nav sublist inside the light theme - */ + * Nav sublist inside the light theme + */ &.pl-c-body--theme-light { .pl-c-nav__subsublist { border-left-color: $pl-color-gray-07; @@ -115,17 +62,17 @@ } /** - * All Nav links inside of subnav dropdown - */ + * All Nav links inside of subnav dropdown + */ .pl-c-nav__sublist .pl-c-nav__link { border-left: 0; border-right: 0; } /** - * Last sublist item - * 1) Undo bottom border radius when in sidebar - */ + * Last sublist item + * 1) Undo bottom border radius when in sidebar + */ .pl-c-nav__sublist > .pl-c-nav__item:last-child .pl-c-nav__link { @media all and (min-width: $pl-bp-med) { border-bottom-left-radius: 0; /* 1 */ @@ -135,30 +82,26 @@ } /** - * Nav controls - * 1) Push off of navigation in flex container so - * they appear at the bottom - */ + * Nav controls + * 1) Push off of navigation in flex container so + * they appear at the bottom + */ .pl-c-controls { display: block; // Display flex + flex direction column gives a similar result, but this fixes a bunch of rendering quirks in IE 11 justify-self: flex-end; margin-left: 0; } - .pl-c-viewport-size { - display: none; - } - /** - * Tools toggle button - */ + * Tools toggle button + */ .pl-c-tools__toggle { display: none; } /** - * Tools list - */ + * Tools list + */ .pl-c-tools__list { max-height: none; overflow: visible; @@ -175,9 +118,14 @@ * so it fits in remaining available space * TODO: revisit to find ways to resize */ - .pl-c-modal { + .pl-c-drawer { right: 0; /* 1 */ width: auto; } + + .pl-is-active + .pl-c-nav__subsublist, + .pl-is-active + .pl-js-acc-panel { + max-height: none; + } } } diff --git a/packages/uikit-workshop/src/sass/scss/core.scss b/packages/uikit-workshop/src/sass/scss/core.scss index 50ce042c1..edf3c3fbc 100644 --- a/packages/uikit-workshop/src/sass/scss/core.scss +++ b/packages/uikit-workshop/src/sass/scss/core.scss @@ -1,2 +1,2 @@ @import './01-abstracts/variables'; -@import './01-abstracts/mixins'; \ No newline at end of file +@import './01-abstracts/mixins'; diff --git a/packages/uikit-workshop/src/scripts/actions/app.js b/packages/uikit-workshop/src/scripts/actions/app.js index fa453303a..c3e335a22 100644 --- a/packages/uikit-workshop/src/scripts/actions/app.js +++ b/packages/uikit-workshop/src/scripts/actions/app.js @@ -1,7 +1,34 @@ export const UPDATE_THEME_MODE = 'UPDATE_THEME_MODE'; export const UPDATE_LAYOUT_MODE = 'UPDATE_LAYOUT_MODE'; +export const UPDATE_DRAWER_ANIMATION_STATE = 'UPDATE_DRAWER_ANIMATION_STATE'; +export const UPDATE_DRAWER_STATE = 'UPDATE_DRAWER_STATE'; +export const UPDATE_VIEWPORT_PX = 'UPDATE_VIEWPORT_PX'; +export const UPDATE_VIEWPORT_EM = 'UPDATE_VIEWPORT_EM'; +export const UPDATE_DRAWER_HEIGHT = 'UPDATE_DRAWER_HEIGHT'; +export const UPDATE_CURRENT_URL = 'UPDATE_CURRENT_URL'; +export const UPDATE_CURRENT_PATTERN = 'UPDATE_CURRENT_PATTERN'; +export const IS_VIEWALL_PAGE = 'IS_VIEWALL_PAGE'; -export const updateLayoutMode = layoutMode => (dispatch, getState) => { +export const updateCurrentPattern = + (currentPattern) => (dispatch, getState) => { + if (getState().app.currentPattern !== currentPattern) { + dispatch({ + type: UPDATE_CURRENT_PATTERN, + currentPattern, + }); + } + }; + +export const updateCurrentUrl = (currentUrl) => (dispatch, getState) => { + if (getState().app.currentUrl !== currentUrl) { + dispatch({ + type: UPDATE_CURRENT_URL, + currentUrl, + }); + } +}; + +export const updateLayoutMode = (layoutMode) => (dispatch, getState) => { if (getState().app.layoutMode !== layoutMode) { dispatch({ type: UPDATE_LAYOUT_MODE, @@ -10,7 +37,25 @@ export const updateLayoutMode = layoutMode => (dispatch, getState) => { } }; -export const updateThemeMode = themeMode => (dispatch, getState) => { +export const updateViewportPx = (viewportPx) => (dispatch, getState) => { + if (getState().app.viewportPx !== viewportPx) { + dispatch({ + type: UPDATE_VIEWPORT_PX, + viewportPx, + }); + } +}; + +export const updateViewportEm = (viewportEm) => (dispatch, getState) => { + if (getState().app.viewportEm !== viewportEm) { + dispatch({ + type: UPDATE_VIEWPORT_EM, + viewportEm, + }); + } +}; + +export const updateThemeMode = (themeMode) => (dispatch, getState) => { if (getState().app.themeMode !== themeMode) { dispatch({ type: UPDATE_THEME_MODE, @@ -18,3 +63,40 @@ export const updateThemeMode = themeMode => (dispatch, getState) => { }); } }; + +export const updateDrawerState = (opened) => (dispatch, getState) => { + if (getState().app.drawerOpened !== opened) { + dispatch({ + type: UPDATE_DRAWER_STATE, + opened, + }); + } +}; + +export const updateDrawerAnimationState = + (drawerIsAnimating) => (dispatch, getState) => { + if (getState().app.drawerIsAnimating !== drawerIsAnimating) { + dispatch({ + type: UPDATE_DRAWER_ANIMATION_STATE, + drawerIsAnimating, + }); + } + }; + +export const updateDrawerHeight = (height) => (dispatch, getState) => { + if (getState().app.drawerHeight !== height) { + dispatch({ + type: UPDATE_DRAWER_HEIGHT, + height, + }); + } +}; + +export const isViewallPage = (isViewall) => (dispatch, getState) => { + if (getState().app.isViewallPage !== isViewall) { + dispatch({ + type: IS_VIEWALL_PAGE, + isViewall, + }); + } +}; diff --git a/packages/uikit-workshop/src/scripts/components/base-component.js b/packages/uikit-workshop/src/scripts/components/base-component.js index 1e1594993..bce76c746 100644 --- a/packages/uikit-workshop/src/scripts/components/base-component.js +++ b/packages/uikit-workshop/src/scripts/components/base-component.js @@ -1,24 +1,23 @@ -import { withComponent, shadow } from 'skatejs'; -import withPreact from '@skatejs/renderer-preact'; +/* eslint-disable no-unused-vars */ +import { withComponent, shadow, name } from 'skatejs'; import { store } from '../store.js'; -import { extend, supportsShadowDom } from '../utils/index.js'; -import { h } from 'preact'; +import withLitHtml from './with-lit-html'; +import { LitElement } from 'lit-element'; +import { SkatePreactElement } from './base-skate-preact-element'; -export class BaseComponent extends withComponent(withPreact()) { - get renderRoot() { - if (this.useShadow === true && supportsShadowDom) { - return super.renderRoot || shadow(this); - } else { - return this; - } +export class BaseComponent extends SkatePreactElement { + constructor() { + super(); } - disconnectedCallback() { - this.__storeUnsubscribe(); - - if (super.disconnectedCallback) { - super.disconnectedCallback(); - } + get renderRoot() { + return this; + // @todo: re-enable Shadow DOM conditionally after further testing + making sure PL components have inline styles needed + // if (this.useShadow === true && supportsShadowDom) { + // return super.renderRoot || shadow(this); + // } else { + // return this; + // } } connectedCallback() { @@ -31,8 +30,18 @@ export class BaseComponent extends withComponent(withPreact()) { } } + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + this.__storeUnsubscribe && this.__storeUnsubscribe(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + _stateChanged(state) { - throw new Error('_stateChanged() not implemented', this); + // throw new Error('_stateChanged() not implemented', this); + this.triggerUpdate(); } /** @@ -44,20 +53,7 @@ export class BaseComponent extends withComponent(withPreact()) { * updated */ setState(state, callback) { - if (!this._prevState) { - this._prevState = this.state; - } - - this.state = extend( - extend({}, this.state), - typeof state === 'function' ? state(this.state, this.props) : state - ); - - if (callback) { - this._renderCallbacks.push(callback); - } - - this.triggerUpdate(); + this.state = Object.assign({}, this.state, state); } _renderStyles(stylesheets) { @@ -71,3 +67,47 @@ export class BaseComponent extends withComponent(withPreact()) { } } } + +export class BaseLitComponent extends LitElement { + createRenderRoot() { + return this; + } + + constructor() { + super(); + } + + disconnectedCallback() { + this.__storeUnsubscribe(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + connectedCallback() { + this.__storeUnsubscribe = store.subscribe(() => + this._stateChanged(store.getState()) + ); + this._stateChanged(store.getState()); + if (super.connectedCallback) { + super.connectedCallback(); + } + } + + _stateChanged(state) { + this.requestUpdate(); + } + + /** + * Update component state and schedule a re-render. + * @param {object} state A dict of state properties to be shallowly merged + * into the current state, or a function that will produce such a dict. The + * function is called with the current state and props. + * @param {() => void} callback A function to be called once component state is + * updated + */ + setState(state, callback) { + this.state = Object.assign({}, this.state, state); + } +} diff --git a/packages/uikit-workshop/src/scripts/components/base-skate-element.js b/packages/uikit-workshop/src/scripts/components/base-skate-element.js new file mode 100644 index 000000000..47bca23b8 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/base-skate-element.js @@ -0,0 +1,315 @@ +import { dashCase, empty, keys } from 'skatejs/dist/esnext/util'; + +const _extends = + Object.assign || + function (target) { + for (let i = 1; i < arguments.length; i++) { + const source = arguments[i]; + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + +export function normalizeAttributeDefinition(name, prop) { + const { attribute } = prop; + const obj = + typeof attribute === 'object' + ? _extends({}, attribute) + : { + source: attribute, + target: attribute, + }; + if (obj.source === true) { + obj.source = dashCase(name); + } + if (obj.target === true) { + obj.target = dashCase(name); + } + return obj; +} + +function identity(v) { + return v; +} + +export function normalizePropertyDefinition(name, prop) { + const { coerce, default: def, deserialize, serialize } = prop; + return { + attribute: normalizeAttributeDefinition(name, prop), + coerce: coerce || identity, + default: def, + deserialize: deserialize || identity, + serialize: serialize || identity, + }; +} + +const defaultTypesMap = new Map(); + +function defineProps(constructor) { + if (constructor.hasOwnProperty('_propsNormalized')) { + return; + } + const { props } = constructor; + keys(props).forEach((name) => { + let func = props[name] || props.any; + if (defaultTypesMap.has(func)) { + func = defaultTypesMap.get(func); + } + if (typeof func !== 'function') { + func = prop(func); + } + func({ constructor }, name); + }); +} + +function delay(fn) { + if (window.Promise) { + Promise.resolve().then(fn); + } else { + setTimeout(fn); + } +} + +export function prop(definition) { + const propertyDefinition = definition || {}; + + // Allows decorators, or imperative definitions. + const func = function ({ constructor }, name) { + const normalized = normalizePropertyDefinition(name, propertyDefinition); + + // Ensure that we can cache properties. We have to do this so the _props object literal doesn't modify parent + // classes or share the instance anywhere where it's not intended to be shared explicitly in userland code. + if (!constructor.hasOwnProperty('_propsNormalized')) { + constructor._propsNormalized = {}; + } + + // Cache the value so we can reference when syncing the attribute to the property. + constructor._propsNormalized[name] = normalized; + const { + attribute: { source, target }, + } = normalized; + + if (source) { + constructor._observedAttributes.push(source); + constructor._attributeToPropertyMap[source] = name; + if (source !== target) { + constructor._attributeToAttributeMap[source] = target; + } + } + + Object.defineProperty(constructor.prototype, name, { + configurable: true, + get() { + const val = this._props[name]; + return val == null ? normalized.default : val; + }, + set(val) { + const { + attribute: { target }, + serialize, + } = normalized; + if (target) { + const serializedVal = serialize ? serialize(val) : val; + if (serializedVal == null) { + this.removeAttribute(target); + } else { + this.setAttribute(target, serializedVal); + } + } + this._props[name] = normalized.coerce(val); + this.triggerUpdate(); + }, + }); + }; + + // Allows easy extension of pre-defined props { ...prop(), ...{} }. + Object.keys(propertyDefinition).forEach( + (key) => (func[key] = propertyDefinition[key]) + ); + + return func; +} + +export class SkateElement extends HTMLElement { + constructor(...args) { + let _temp; + return ( + (_temp = super(...args)), + (this._prevProps = {}), + (this._prevState = {}), + (this._props = {}), + (this._state = {}), + _temp + ); + } + + static get observedAttributes() { + // We have to define props here because observedAttributes are retrieved + // only once when the custom element is defined. If we did this only in + // the constructor, then props would not link to attributes. + defineProps(this); + return this._observedAttributes.concat(super.observedAttributes || []); + } + + static get props() { + return this._props; + } + + static set props(props) { + this._props = props; + } + + get props() { + return keys(this.constructor.props).reduce((prev, curr) => { + prev[curr] = this[curr]; + return prev; + }, {}); + } + + set props(props) { + const ctorProps = this.constructor.props; + keys(props).forEach((k) => k in ctorProps && (this[k] = props[k])); + } + + get state() { + return this._state; + } + + set state(state) { + this._state = state; + this.triggerUpdate(); + } + + attributeChangedCallback(name, oldValue, newValue) { + const { + _attributeToAttributeMap, + _attributeToPropertyMap, + _propsNormalized, + } = this.constructor; + + if (super.attributeChangedCallback) { + super.attributeChangedCallback(name, oldValue, newValue); + } + + const propertyName = _attributeToPropertyMap[name]; + if (propertyName) { + const propertyDefinition = _propsNormalized[propertyName]; + if (propertyDefinition) { + const { default: defaultValue, deserialize } = propertyDefinition; + const propertyValue = deserialize ? deserialize(newValue) : newValue; + this._props[propertyName] = + propertyValue == null ? defaultValue : propertyValue; + this.triggerUpdate(); + } + } + + const targetAttributeName = _attributeToAttributeMap[name]; + if (targetAttributeName) { + if (newValue == null) { + this.removeAttribute(targetAttributeName); + } else { + this.setAttribute(targetAttributeName, newValue); + } + } + } + + connectedCallback() { + if (super.connectedCallback) { + super.connectedCallback(); + } + this.triggerUpdate(); + } + + shouldUpdate() { + return true; + } + + triggerUpdate() { + if (this._updating) { + return; + } + this._updating = true; + delay(() => { + const { _prevProps, _prevState } = this; + if (this.updating) { + this.updating(_prevProps, _prevState); + } + if (this.updated && this.shouldUpdate(_prevProps, _prevState)) { + this.updated(_prevProps, _prevState); + } + this._prevProps = this.props; + this._prevState = this.state; + this._updating = false; + }); + } +} + +SkateElement._attributeToAttributeMap = {}; +SkateElement._attributeToPropertyMap = {}; +SkateElement._observedAttributes = []; +SkateElement._props = {}; + +const { parse, stringify } = JSON; +const attribute = Object.freeze({ source: true }); +const zeroOrNumber = (val) => (empty(val) ? 0 : Number(val)); + +const any = prop({ + attribute, +}); + +const array = prop({ + attribute, + coerce: (val) => (Array.isArray(val) ? val : empty(val) ? null : [val]), + default: Object.freeze([]), + deserialize: parse, + serialize: stringify, +}); + +const boolean = prop({ + attribute, + coerce: Boolean, + default: false, + deserialize: (val) => !empty(val), + serialize: (val) => (val ? '' : null), +}); + +const number = prop({ + attribute, + default: 0, + coerce: zeroOrNumber, + deserialize: zeroOrNumber, + serialize: (val) => (empty(val) ? null : String(Number(val))), +}); + +const object = prop({ + attribute, + default: Object.freeze({}), + deserialize: parse, + serialize: stringify, +}); + +const string = prop({ + attribute, + default: '', + coerce: String, + serialize: (val) => (empty(val) ? null : String(val)), +}); + +defaultTypesMap.set(Array, array); +defaultTypesMap.set(Boolean, boolean); +defaultTypesMap.set(Number, number); +defaultTypesMap.set(Object, object); +defaultTypesMap.set(String, string); + +export const props = { + any, + array, + boolean, + number, + object, + string, +}; diff --git a/packages/uikit-workshop/src/scripts/components/base-skate-preact-element.js b/packages/uikit-workshop/src/scripts/components/base-skate-preact-element.js new file mode 100644 index 000000000..e92dfa06a --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/base-skate-preact-element.js @@ -0,0 +1,63 @@ +const _extends = + Object.assign || + function (target) { + for (let i = 1; i < arguments.length; i++) { + const source = arguments[i]; + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + +import { SkateElement } from './base-skate-element'; + +/** @jsx h */ + +import { h, render } from 'preact'; + +export class SkatePreactElement extends SkateElement { + get props() { + // We override props so that we can satisfy most use + // cases for children by using a slot. + return _extends({}, super.props, { children: h('slot', null) }); + } + + renderer(root, call) { + this._renderRoot = root; + render(call(), root); + } + + disconnectedCallback() { + this.disconnecting && this.disconnecting(); + super.disconnectedCallback && super.disconnectedCallback(); + this.disconnected && this.disconnected(); + // Render null to unmount. See https://github.com/skatejs/skatejs/pull/1432#discussion_r183381359 + render(null, this._renderRoot); + + this.__storeUnsubscribe && this.__storeUnsubscribe(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + connectedCallback() { + this.connecting && this.connecting(); + super.connectedCallback && super.connectedCallback(); + this.connected && this.connected(); + } + + get renderRoot() { + return super.renderRoot || shadow(this); + } + + updated(prevProps, prevState) { + super.updated && super.updated(prevProps, prevState); + this.rendering && this.rendering(); + this.renderer(this.renderRoot, () => this.render && this.render(this)); + this.rendered && this.rendered(); + } +} diff --git a/packages/uikit-workshop/src/scripts/components/copy-to-clipboard.js b/packages/uikit-workshop/src/scripts/components/copy-to-clipboard.js index 3cc09ed68..60cb46a8b 100644 --- a/packages/uikit-workshop/src/scripts/components/copy-to-clipboard.js +++ b/packages/uikit-workshop/src/scripts/components/copy-to-clipboard.js @@ -5,10 +5,21 @@ import Clipboard from 'clipboard'; const clipboard = new Clipboard('.pl-js-code-copy-btn'); -clipboard.on('success', function(e) { +clipboard.on('success', function (e) { const copyButton = document.querySelectorAll('.pl-js-code-copy-btn'); for (let i = 0; i < copyButton.length; i++) { - copyButton[i].innerText = 'Copy'; + copyButton[i].querySelector('.pl-c-code-copy-btn__icon-text').innerText = + 'Copy'; } - e.trigger.textContent = 'Copied'; + e.trigger.classList.add('is-copied'); + e.trigger.querySelector('.pl-c-code-copy-btn__icon-text').textContent = + 'Copied'; + + setTimeout(() => { + e.trigger.classList.remove('is-copied'); + e.trigger.querySelector('.pl-c-code-copy-btn__icon-text').textContent = + 'Copy'; + e.clearSelection(); + e.trigger.blur(); + }, 2000); }); diff --git a/packages/uikit-workshop/src/scripts/components/modal-styleguide.js b/packages/uikit-workshop/src/scripts/components/modal-styleguide.js index a7a8e8254..665628c5f 100644 --- a/packages/uikit-workshop/src/scripts/components/modal-styleguide.js +++ b/packages/uikit-workshop/src/scripts/components/modal-styleguide.js @@ -1,9 +1,11 @@ +/* eslint-disable no-param-reassign, no-unused-vars */ /** * "Modal" (aka Panel UI) for the Styleguide Layer - for both annotations and code/info */ import { panelsUtil } from './panels-util'; -import './copy-to-clipboard'; +import './pl-copy-to-clipboard/pl-copy-to-clipboard'; +import { iframeMsgDataExtraction } from '../utils'; export const modalStyleguide = { // set up some defaults @@ -18,12 +20,13 @@ export const modalStyleguide = { */ onReady() { // go through the panel toggles and add click event to the pattern extra toggle button - const els = document.querySelectorAll('.pl-js-pattern-extra-toggle'); - for (let i = 0; i < els.length; ++i) { - els[i].onclick = function(e) { - const patternPartial = this.getAttribute('data-patternpartial'); + const toggles = document.querySelectorAll('.pl-js-pattern-extra-toggle'); + + for (let i = 0; i < toggles.length; i++) { + toggles[i].addEventListener('click', (e) => { + const patternPartial = toggles[i].getAttribute('data-patternpartial'); modalStyleguide.toggle(patternPartial); - }; + }); } }, @@ -62,15 +65,17 @@ export const modalStyleguide = { content = panelsUtil.addClickEvents(content, patternPartial); // make sure the modal viewer and other options are off just in case - modalStyleguide.close(patternPartial); + // modalStyleguide.close(patternPartial); // note it's turned on in the viewer modalStyleguide.active[patternPartial] = true; // make sure there's no content div = document.getElementById('pl-pattern-extra-' + patternPartial); - if (div.childNodes.length > 0) { - div.removeChild(div.childNodes[0]); + if (div && div.childNodes) { + if (div.childNodes.length > 0) { + div.removeChild(div.childNodes[0]); + } } // add the content @@ -79,9 +84,13 @@ export const modalStyleguide = { .appendChild(content); // show the modal - document - .getElementById('pl-pattern-extra-toggle-' + patternPartial) - .classList.add('pl-is-active'); + const toggle = document.getElementById( + 'pl-pattern-extra-toggle-' + patternPartial + ); + if (toggle) { + toggle.classList.add('pl-is-active'); + } + document .getElementById('pl-pattern-extra-' + patternPartial) .classList.add('pl-is-active'); @@ -96,12 +105,18 @@ export const modalStyleguide = { modalStyleguide.active[patternPartial] = false; // hide the modal, look at info-panel.js - document - .getElementById('pl-pattern-extra-toggle-' + patternPartial) - .classList.remove('pl-is-active'); - document - .getElementById('pl-pattern-extra-' + patternPartial) - .classList.remove('pl-is-active'); + const toggle = document.getElementById( + 'pl-pattern-extra-toggle-' + patternPartial + ); + if (toggle) { + toggle.classList.remove('pl-is-active'); + } + + if (document.getElementById('pl-pattern-extra-' + patternPartial)) { + document + .getElementById('pl-pattern-extra-' + patternPartial) + .classList.remove('pl-is-active'); + } }, /** @@ -153,7 +168,7 @@ export const modalStyleguide = { patternPartialSelector + '.pl-c-annotation-tip' ); for (let i = 0; i < elsToHide.length; i++) { - elsToHide[i].style.display = 'none'; + elsToHide[i].hidden = true; } }, @@ -181,24 +196,11 @@ export const modalStyleguide = { /** * toggle the comment pop-up based on a user clicking on the pattern * based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage - * @param {Object} event info + * + * @param {MessageEvent} e A message received by a target object. */ - receiveIframeMessage(event) { - // does the origin sending the message match the current host? if not dev/null the request - if ( - window.location.protocol !== 'file:' && - event.origin !== window.location.protocol + '//' + window.location.host - ) { - return; - } - - let data = {}; - try { - data = - typeof event.data !== 'string' ? event.data : JSON.parse(event.data); - } catch (e) { - // @todo: how do we want to handle exceptions here? - } + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); // see if it got a path to replace if (data.event !== undefined && data.event === 'patternLab.patternQuery') { @@ -240,7 +242,7 @@ export const modalStyleguide = { .getComputedStyle(elsToHighlight[j], null) .getPropertyValue('max-height') === '0px' ) { - span.style.display = 'none'; + span.hidden = true; } const annotationTip = document.querySelector( @@ -252,13 +254,13 @@ export const modalStyleguide = { elsToHighlight[j].firstChild ); } else { - annotationTip.style.display = 'inline-flex'; + annotationTip.hidden = false; } - elsToHighlight[j].onclick = (function(el) { - return function(e) { - e.preventDefault(); - e.stopPropagation(); + elsToHighlight[j].onclick = (function (el) { + return function (event) { + event.preventDefault(); + event.stopPropagation(); const obj = JSON.stringify({ event: 'patternLab.annotationNumberClicked', displayNumber: el.displayNumber, diff --git a/packages/uikit-workshop/src/scripts/components/modal-viewer.js b/packages/uikit-workshop/src/scripts/components/modal-viewer.js index c099711c8..ca919894b 100644 --- a/packages/uikit-workshop/src/scripts/components/modal-viewer.js +++ b/packages/uikit-workshop/src/scripts/components/modal-viewer.js @@ -1,13 +1,20 @@ +/* eslint-disable no-unused-vars */ /** * "Modal" (aka Panel UI) for the Viewer Layer - for both annotations and code/info */ -import $ from 'jquery'; -import { urlHandler, DataSaver, Dispatcher } from '../utils'; +import { scrollTo } from 'scroll-js'; +import { urlHandler, Dispatcher, iframeMsgDataExtraction } from '../utils'; import { panelsViewer } from './panels-viewer'; +import { store } from '../store.js'; +// These are the actions needed by this element. +import { updateDrawerState, isViewallPage } from '../actions/app.js'; export const modalViewer = { // set up some defaults + delayCheckingModalViewer: false, + iframeElement: document.querySelector('.pl-js-iframe'), + iframeCustomElement: document.querySelector('pl-iframe'), active: false, switchText: true, template: 'info', @@ -21,54 +28,27 @@ export const modalViewer = { * initialize the modal window */ onReady() { + window.addEventListener('message', modalViewer.receiveIframeMessage, false); // make sure the listener for checkpanels is set-up Dispatcher.addListener('insertPanels', modalViewer.insert); - // add the info/code panel onclick handler - $('.pl-js-pattern-info-toggle').click(function(e) { - modalViewer.toggle(); - }); - - // make sure the close button handles the click - $('.pl-js-modal-close-btn').on('click', function(e) { - // hide any open annotations - const obj = JSON.stringify({ - event: 'patternLab.annotationsHighlightHide', - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, modalViewer.targetOrigin); - - // hide the viewer - modalViewer.close(); - }); + modalViewer.__storeUnsubscribe = store.subscribe(() => + modalViewer._stateChanged(store.getState()) + ); + modalViewer._stateChanged(store.getState()); - // see if the modal is already active, if so update attributes as appropriate - if (DataSaver.findValue('modalActive') === 'true') { - modalViewer.active = true; - $('.pl-js-pattern-info-toggle').html('Hide Pattern Info'); - } - - // make sure the modal viewer is not viewable, it's always hidden by default. the pageLoad event determines when it actually opens - modalViewer.hide(); - - // review the query strings in case there is something the modal viewer is supposed to handle by default + // check query strings to handle auto-opening behavior const queryStringVars = urlHandler.getRequestVars(); // show the modal if code view is called via query string if ( queryStringVars.view !== undefined && - (queryStringVars.view === 'code' || queryStringVars.view === 'c') - ) { - modalViewer.queryPattern(); - } - - // show the modal if the old annotations view is called via query string - if ( - queryStringVars.view !== undefined && - (queryStringVars.view === 'annotations' || queryStringVars.view === 'a') + (queryStringVars.view === 'code' || + queryStringVars.view === 'c' || + queryStringVars.view === 'annotations' || + queryStringVars.view === 'a') ) { - modalViewer.queryPattern(); + store.dispatch(updateDrawerState(true)); } }, @@ -76,16 +56,10 @@ export const modalViewer = { * toggle the modal window open and closed */ toggle() { - if (modalViewer.active === false) { - modalViewer.queryPattern(); + if (modalViewer.active) { + store.dispatch(updateDrawerState(false)); } else { - const obj = JSON.stringify({ - event: 'patternLab.annotationsHighlightHide', - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, modalViewer.targetOrigin); - modalViewer.close(); + store.dispatch(updateDrawerState(true)); } }, @@ -93,50 +67,70 @@ export const modalViewer = { * open the modal window */ open() { - // make sure the modal viewer and other options are off just in case - modalViewer.close(); - - // note it's turned on in the viewer - DataSaver.updateValue('modalActive', 'true'); - modalViewer.active = true; + modalViewer.queryPattern(); - // show the modal - modalViewer.show(); + // Show annotations if data is available and modal is open + if (modalViewer.patternData) { + if ( + modalViewer.patternData.annotations && + modalViewer.patternData.annotations.length > 0 + ) { + const obj = JSON.stringify({ + event: 'patternLab.annotationsHighlightShow', + annotations: modalViewer.patternData.annotations, + }); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.iframeElement.contentWindow.postMessage( + obj, + modalViewer.targetOrigin + ); + } else { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.open(); + } else { + console.log('modelViewer open cannot find the iframeElement...'); + } + } + } + } }, /** * close the modal window */ close() { - // note that the modal viewer is no longer active - DataSaver.updateValue('modalActive', 'false'); - modalViewer.active = false; - - //Remove active class to modal - $('.pl-js-modal').removeClass('pl-is-active'); - $('.pl-js-modal').removeAttr('style'); // remove inline height CSS - - // WIP: refactoring viewport panel to use CSS vars to resize - // $('html').css('--pl-viewport-height', window.innerHeight - 32 + 'px'); - - // update the wording - $('.pl-js-pattern-info-toggle').html('Show Pattern Info'); - // tell the styleguide to close const obj = JSON.stringify({ event: 'patternLab.patternModalClose', }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, modalViewer.targetOrigin); - }, - /** - * hide the modal window - */ - hide() { - $('.pl-js-modal').removeClass('pl-is-active'); - $('.pl-js-modal').removeAttr('style'); // remove inline height CSS + if (modalViewer.iframeElement) { + if (modalViewer.iframeElement.contentWindow) { + modalViewer.iframeElement.contentWindow.postMessage( + obj, + modalViewer.targetOrigin + ); + + const obj2 = JSON.stringify({ + event: 'patternLab.annotationsHighlightHide', + }); + modalViewer.iframeElement.contentWindow.postMessage( + obj2, + modalViewer.targetOrigin + ); + } else { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.close(); + } else { + console.log('modelViewer close cannot find the iframeElement...'); + } + } + } }, /** @@ -154,21 +148,48 @@ export const modalViewer = { patternPartial, modalContent: templateRendered.outerHTML, }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, modalViewer.targetOrigin); + if (modalViewer.iframeElement.contentWindow) { + modalViewer.iframeElement.contentWindow.postMessage( + obj, + modalViewer.targetOrigin + ); + } else { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.insert(templateRendered, patternPartial, iframePassback); + } else { + console.log('modelViewer insert cannot find the iframeElement...'); + } + } } else { - // insert the panels and open the viewer - $('.pl-js-modal-content').html(templateRendered); - modalViewer.open(); - } + const contentContainer = document.querySelector('.pl-js-drawer-content'); - // update the wording unless this is a default viewall opening - if (switchText === true) { - $('.pl-js-pattern-info-toggle').html('Hide Pattern Info'); + // Clear out any existing children before appending the new panel content + if (contentContainer.firstChild !== null) { + while (contentContainer.firstChild !== null) { + contentContainer.removeChild(contentContainer.firstChild); + } + } + + contentContainer.appendChild(templateRendered); + modalViewer.addClickEvents(contentContainer); } }, + addClickEvents(contentContainer = document) { + contentContainer.querySelectorAll('.pl-js-lineage-link').forEach((link) => { + link.addEventListener('click', (e) => { + const patternPartial = e.target.getAttribute('data-patternpartial'); + + if (patternPartial && modalViewer.iframeCustomElement) { + e.preventDefault(); + modalViewer.iframeCustomElement.navigateTo(patternPartial); + } + }); + }); + }, + /** * refresh the modal if a new pattern is loaded and the modal is active * @param {Object} the patternData sent back from the query @@ -176,10 +197,7 @@ export const modalViewer = { * @param {Boolean} if the text in the dropdown should be switched */ refresh(patternData, iframePassback, switchText) { - // if this is a styleguide view close the modal - if (iframePassback) { - modalViewer.hide(); - } + modalViewer.patternData = patternData; // gather the data that will fill the modal window panelsViewer.gatherPanels(patternData, iframePassback, switchText); @@ -190,7 +208,7 @@ export const modalViewer = { * @param {Integer} where the modal window should be slide to */ slide(pos) { - $('.pl-js-modal').toggleClass('pl-is-active'); + modalViewer.toggle(); }, /** @@ -204,73 +222,89 @@ export const modalViewer = { els[i].classList.remove('pl-is-active'); } + const patternInfoElem = document.querySelector('.pl-js-pattern-info'); + // const scroll = new Scroll(patternInfoElem); + // add active class to called element and scroll to it for (let i = 0; i < els.length; ++i) { if (i + 1 === pos) { els[i].classList.add('pl-is-active'); - $('.pl-js-pattern-info').animate( - { - scrollTop: els[i].offsetTop - 10, - }, - 600 - ); + + scrollTo(patternInfoElem, { + top: els[i].offsetTop - 14, + behavior: 'smooth', + }).then(function () { + // console.log('finished scrolling'); + }); } } }, - /** - * Show modal - */ - show() { - $('.pl-js-modal').addClass('pl-is-active'); - }, - /** * ask the pattern for info so we can open the modal window and populate it * @param {Boolean} if the dropdown text should be changed */ queryPattern(switchText) { - // note that the modal is active and set switchText - if (switchText === undefined || switchText) { - switchText = true; - DataSaver.updateValue('modalActive', 'true'); - modalViewer.active = true; - } - // send a message to the pattern const obj = JSON.stringify({ event: 'patternLab.patternQuery', switchText, }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, modalViewer.targetOrigin); + + // only emit this when the iframe element exists. + // @todo: refactor to better handle async UI rendering + if (modalViewer.iframeElement) { + if (modalViewer.iframeElement.contentWindow) { + modalViewer.iframeElement.contentWindow.postMessage( + obj, + modalViewer.targetOrigin + ); + } else { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.queryPattern(switchText); + } else { + console.log('queryPattern cannot find the iframeElement...'); + } + } + } else { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + + if (modalViewer.iframeElement.contentWindow) { + modalViewer.iframeElement.contentWindow.postMessage( + obj, + modalViewer.targetOrigin + ); + } + } }, /** * toggle the comment pop-up based on a user clicking on the pattern * based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage - * @param {Object} event info + * + * @param {MessageEvent} e A message received by a target object. */ - receiveIframeMessage(event) { - // does the origin sending the message match the current host? if not dev/null the request - if ( - window.location.protocol !== 'file:' && - event.origin !== window.location.protocol + '//' + window.location.host - ) { - return; - } + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); - let data = {}; + if (data.event !== undefined && data.event === 'patternLab.pageLoad') { + // @todo: refactor to better handle async iframe loading + // extra check to make sure the PL drawer will always render even if the iframe gets async loaded / rendered. + if (modalViewer.delayCheckingModalViewer) { + modalViewer._handleInitialModalViewerState(); + } - try { - data = - typeof event.data !== 'string' ? event.data : JSON.parse(event.data); - } catch (e) { - // @todo: how do we want to handle exceptions here? - } + if ( + data.patternpartial.indexOf('viewall-') === 0 || + data.patternpartial.indexOf('all') === 0 + ) { + store.dispatch(isViewallPage(true)); + } else { + store.dispatch(isViewallPage(false)); + } - if (data.event !== undefined && data.event === 'patternLab.pageLoad') { if ( modalViewer.active === false && data.patternpartial !== undefined && @@ -286,12 +320,18 @@ export const modalViewer = { data.event !== undefined && data.event === 'patternLab.patternQueryInfo' ) { - // refresh the modal if a new pattern is loaded and the modal is active - modalViewer.refresh( - data.patternData, - data.iframePassback, - data.switchText - ); + if ( + !modalViewer.panelRendered || + modalViewer.previouslyRenderedPattern !== + data.patternData.patternPartial + ) { + // refresh the modal contents, but only when necessary (ex. when the page changes) -- prevents extra, unnecessary re-renders of content. + modalViewer.refresh( + data.patternData, + data.iframePassback, + data.switchText + ); + } } else if ( data.event !== undefined && data.event === 'patternLab.annotationNumberClicked' @@ -300,11 +340,35 @@ export const modalViewer = { modalViewer.slideToAnnotation(data.displayNumber); } }, -}; -// when the document is ready make sure the modal is ready -$(document).ready(function() { - modalViewer.onReady(); -}); + _handleInitialModalViewerState() { + // try to re-locate the iframe element if this UI logic ran too early and the iframe component wasn't yet rendered + if (!modalViewer.iframeElement) { + modalViewer.iframeElement = document.querySelector('.pl-js-iframe'); + } + + // only try to auto-open / auto-close the drawer UI if the iframe element exists + // @todo: refactor to better handle async UI rendering + if (modalViewer.iframeElement) { + modalViewer.delayCheckingModalViewer = false; + if (modalViewer.active) { + modalViewer.open(); + } else { + modalViewer.close(); + } + } else { + modalViewer.delayCheckingModalViewer = true; + } + }, + + _stateChanged(state) { + if (modalViewer.active !== state.app.drawerOpened) { + modalViewer.active = state.app.drawerOpened; + if (modalViewer.iframeElement) { + modalViewer._handleInitialModalViewerState(); + } + } + }, +}; -window.addEventListener('message', modalViewer.receiveIframeMessage, false); +modalViewer.onReady(); diff --git a/packages/uikit-workshop/src/scripts/components/panels-util.js b/packages/uikit-workshop/src/scripts/components/panels-util.js index 8a9c6d0ac..a485e3c97 100644 --- a/packages/uikit-workshop/src/scripts/components/panels-util.js +++ b/packages/uikit-workshop/src/scripts/components/panels-util.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ /** * Panels Util - for both styleguide and viewer */ @@ -11,7 +12,7 @@ export const panelsUtil = { addClickEvents(templateRendered, patternPartial) { const els = templateRendered.querySelectorAll('.pl-js-tab-link'); for (let i = 0; i < els.length; ++i) { - els[i].onclick = function(e) { + els[i].onclick = function (e) { e.preventDefault(); const partial = this.getAttribute('data-patternpartial'); @@ -31,22 +32,24 @@ export const panelsUtil = { show(patternPartial, panelID) { const activeTabClass = 'pl-is-active-tab'; + // tabPanelabout to become active + const activeTabPanel = document.querySelector( + `#pl-${patternPartial}-${panelID}-panel` + ); + + const parentTabs = activeTabPanel.closest('.pl-js-tabs'); + // turn off all of the active tabs - const allTabLinks = document.querySelectorAll(`.pl-js-tab-link`); + const allTabLinks = parentTabs.querySelectorAll(`.pl-js-tab-link`); // hide all of the panels - const allTabPanels = document.querySelectorAll(`.pl-js-tab-panel`); + const allTabPanels = parentTabs.querySelectorAll(`.pl-js-tab-panel`); // tabLink about to become active - const activeTabLink = document.querySelector( + const activeTabLink = parentTabs.querySelector( `#pl-${patternPartial}-${panelID}-tab` ); - // tabPanelabout to become active - const activeTabPanel = document.querySelector( - `#pl-${patternPartial}-${panelID}-panel` - ); - for (let i = 0; i < allTabLinks.length; ++i) { allTabLinks[i].classList.remove(activeTabClass); } diff --git a/packages/uikit-workshop/src/scripts/components/panels-viewer.js b/packages/uikit-workshop/src/scripts/components/panels-viewer.js index 273d17a5c..f97cb4a79 100644 --- a/packages/uikit-workshop/src/scripts/components/panels-viewer.js +++ b/packages/uikit-workshop/src/scripts/components/panels-viewer.js @@ -1,14 +1,30 @@ /** * Panel Builder - supports building the panels to be included in the modal or styleguide */ +/* eslint-disable no-param-reassign, no-unused-vars */ -import $ from 'jquery'; -import Hogan from 'hogan.js'; -import Prism from 'prismjs'; +import Handlebars from 'handlebars/dist/handlebars'; +import pretty from 'pretty'; +import { html, render } from 'lit-html'; +import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; import { Panels } from './panels'; import { panelsUtil } from './panels-util'; import { urlHandler, Dispatcher } from '../utils'; -import './copy-to-clipboard'; +import './pl-copy-to-clipboard/pl-copy-to-clipboard'; +import { PrismLanguages as Prism } from './prism-languages'; +import Normalizer from 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.js'; + +const normalizeWhitespace = new Normalizer({ + 'remove-trailing': true, + 'remove-indent': true, + 'left-trim': true, + 'right-trim': true, + 'break-lines': 100, + indent: 2, + 'remove-initial-line-feed': true, + 'tabs-to-spaces': 2, + 'spaces-to-tabs': 2, +}); export const panelsViewer = { // set up some defaults @@ -54,7 +70,7 @@ export const panelsViewer = { Dispatcher.addListener('checkPanels', panelsViewer.checkPanels); // set-up defaults - let template, templateCompiled, templateRendered; + let template, templateCompiled, templateRendered, templateFormatted; // get the base panels const panels = Panels.get(); @@ -71,6 +87,10 @@ export const panelsViewer = { } // if httpRequestReplace has not been set, use the extension. this is likely for the raw template + if (panel.httpRequestReplace === undefined) { + panel.httpRequestReplace = ''; + } + if (panel.httpRequestReplace === '') { panel.httpRequestReplace = panel.httpRequestReplace + '.' + patternData.patternExtension; @@ -86,19 +106,57 @@ export const panelsViewer = { const e = new XMLHttpRequest(); // @todo: look deeper into how we can refactor this particular code block /* eslint-disable */ - e.onload = (function(i, panels, patternData, iframeRequest) { - return function() { - const prismedContent = Prism.highlight( - this.responseText, - Prism.languages.html + e.onload = (function (i, panels, patternData, iframeRequest) { + return function () { + // since non-existant files (such as .scss from plugin-tab) still return a 200, we need to instead inspect the contents + // we look for responseText that starts with the doctype + let rText = this.responseText; + if (rText.startsWith('')) { + rText = ''; + } + + // use pretty to format HTML + if (panels[i].name === 'HTML') { + templateFormatted = pretty(rText, { ocd: true }); + } else { + templateFormatted = rText; + } + + const templateHighlighted = Prism.highlight( + templateFormatted, + Prism.languages[panels[i].name.toLowerCase()] || + Prism.languages['markup'] + // Prism.languages[panels[i].name.toLowerCase()], ); - template = document.getElementById(panels[i].templateID); - templateCompiled = Hogan.compile(template.innerHTML); - templateRendered = templateCompiled.render({ - language: 'html', - code: prismedContent, - }); - panels[i].content = templateRendered; + + const codeTemplate = (code, language) => + html` +
      ${unsafeHTML(
      +                    code
      +                  )}
      + `; + + const result = document.createDocumentFragment(); + const fallBackResult = document.createDocumentFragment(); + + render(codeTemplate(templateHighlighted, 'html'), result); + render(codeTemplate(templateFormatted, 'html'), fallBackResult); + + if (result.children) { + panels[i].content = result.children[0].outerHTML; + } else if (fallBackResult.children) { + panels[i].content = fallBackResult.children[0].outerHTML; + } else { + panels[i].content = + '
      ' +
      +                  templateFormatted
      +                    .replace(//g, '>') +
      +                  '
      '; + } + Dispatcher.trigger('checkPanels', [ panels, patternData, @@ -117,9 +175,16 @@ export const panelsViewer = { } else { // vanilla render of pattern data template = document.getElementById(panel.templateID); - templateCompiled = Hogan.compile(template.innerHTML); - templateRendered = templateCompiled.render(patternData); - panels[i].content = templateRendered; + templateCompiled = Handlebars.compile(template.innerHTML); + templateRendered = templateCompiled(patternData); + const normalizedCode = + normalizeWhitespace.normalize(templateRendered); + normalizedCode.replace(/[\r\n]+/g, '\n\n'); + const highlightedCode = Prism.highlight( + normalizedCode, + Prism.languages.html + ); + panels[i].content = highlightedCode; Dispatcher.trigger('checkPanels', [ panels, patternData, @@ -207,7 +272,7 @@ export const panelsViewer = { } } - // add *Exists attributes for Hogan templates + // add *Exists attributes for Handlebars templates // figure out if the description exists patternData.patternDescExists = patternData.patternDesc.length > 0 || @@ -239,8 +304,8 @@ export const panelsViewer = { // render all of the panels in the base panel template const template = document.querySelector('.pl-js-panel-template-base'); - const templateCompiled = Hogan.compile(template.innerHTML); - templateRendered = templateCompiled.render(patternData); + const templateCompiled = Handlebars.compile(template.innerHTML); + templateRendered = templateCompiled(patternData); // make sure templateRendered is modified to be an HTML element const div = document.createElement('div'); @@ -273,18 +338,6 @@ export const panelsViewer = { } } - // find lineage links in the rendered content and add postmessage handlers in case it's in the modal - $('.pl-js-lineage-link', templateRendered).on('click', function(e) { - e.preventDefault(); - const obj = JSON.stringify({ - event: 'patternLab.updatePath', - path: urlHandler.getFileName($(this).attr('data-patternpartial')), - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, panelsViewer.targetOrigin); - }); - // gather panels from plugins Dispatcher.trigger('insertPanels', [ templateRendered, @@ -307,19 +360,3 @@ export const panelsViewer = { * 5) Add mouseup event to the body so that when drag is released, the modal * stops resizing and modal cover doesn't display anymore. */ -$('.pl-js-modal-resizer').mousedown(function(event) { - /* 1 */ - - $('.pl-js-modal-cover').css('display', 'block'); /* 2 */ - - $('.pl-js-modal-cover').mousemove(function(e) { - /* 3 */ - const panelHeight = window.innerHeight - e.clientY + 32; /* 4 */ - $('.pl-js-modal').css('height', panelHeight + 'px'); /* 4 */ - }); -}); - -$('body').mouseup(function() { - $('.pl-js-modal').unbind('mousemove'); /* 5 */ - $('.pl-js-modal-cover').css('display', 'none'); /* 5 */ -}); diff --git a/packages/uikit-workshop/src/scripts/components/panels.js b/packages/uikit-workshop/src/scripts/components/panels.js index 1b37959aa..52666e571 100644 --- a/packages/uikit-workshop/src/scripts/components/panels.js +++ b/packages/uikit-workshop/src/scripts/components/panels.js @@ -4,7 +4,7 @@ * note: config is coming from the default viewer and is passed through from PL's config */ -import { PrismLanguages } from './prism-languages'; +import { PrismLanguages as Prism } from './prism-languages'; import { Dispatcher } from '../utils'; export const Panels = { @@ -15,7 +15,7 @@ export const Panels = { }, get() { - return JSON.parse(JSON.stringify(this.panels)); + return JSON.parse(JSON.stringify(Panels.panels)); }, add(panel) { @@ -46,45 +46,63 @@ export const Panels = { }, }; -const fileSuffixPattern = - window.config.outputFileSuffixes !== undefined && - window.config.outputFileSuffixes.rawTemplate !== undefined - ? window.config.outputFileSuffixes.rawTemplate - : ''; -const fileSuffixMarkup = - window.config.outputFileSuffixes !== undefined && - window.config.outputFileSuffixes.markupOnly !== undefined - ? window.config.outputFileSuffixes.markupOnly - : '.markup-only'; +function init() { + // does the origin sending the message match the current host? if not dev/null the request -// add the default panels -// Panels.add({ 'id': 'pl-panel-info', 'name': 'info', 'default': true, 'templateID': 'pl-panel-template-info', 'httpRequest': false, 'prismHighlight': false, 'keyCombo': '' }); -// TODO: sort out pl-panel-html -Panels.add({ - id: 'pl-panel-pattern', - name: window.config.patternExtension.toUpperCase(), - default: true, - templateID: 'pl-panel-template-code', - httpRequest: true, - httpRequestReplace: fileSuffixPattern, - httpRequestCompleted: false, - prismHighlight: true, - language: PrismLanguages.get(window.config.patternExtension), - keyCombo: 'ctrl+shift+u', -}); + const fileSuffixPattern = + window.config.outputFileSuffixes !== undefined && + window.config.outputFileSuffixes.rawTemplate !== undefined + ? window.config.outputFileSuffixes.rawTemplate + : ''; -Panels.add({ - id: 'pl-panel-html', - name: 'HTML', - default: false, - templateID: 'pl-panel-template-code', - httpRequest: true, - httpRequestReplace: fileSuffixMarkup + '.html', - httpRequestCompleted: false, - prismHighlight: true, - language: 'markup', - keyCombo: 'ctrl+shift+y', -}); + const fileSuffixMarkup = + window.config.outputFileSuffixes !== undefined && + window.config.outputFileSuffixes.markupOnly !== undefined + ? window.config.outputFileSuffixes.markupOnly + : '.markup-only'; + + // add the default panels + // Panels.add({ 'id': 'pl-panel-info', 'name': 'info', 'default': true, 'templateID': 'pl-panel-template-info', 'httpRequest': false, 'prismHighlight': false, 'keyCombo': '' }); + const languages = Object.keys(Prism.languages); + // TODO: sort out pl-panel-html + Panels.add({ + id: 'pl-panel-pattern', + name: window.config.patternExtension.toUpperCase(), + default: + !window.config.defaultPatternInfoPanelCode || + window.config.defaultPatternInfoPanelCode === + window.config.patternExtension, + templateID: 'pl-panel-template-code', + httpRequest: true, + httpRequestReplace: fileSuffixPattern, + httpRequestCompleted: false, + prismHighlight: true, + language: languages[window.config.patternExtension], + keyCombo: 'ctrl+shift+u', + }); + + Panels.add({ + id: 'pl-panel-html', + name: 'HTML', + default: + window.config.defaultPatternInfoPanelCode && + window.config.defaultPatternInfoPanelCode === 'html', + templateID: 'pl-panel-template-code', + httpRequest: true, + httpRequestReplace: fileSuffixMarkup + '.html', + httpRequestCompleted: false, + prismHighlight: true, + language: 'markup', + keyCombo: 'ctrl+shift+y', + }); + + if (!window.patternlab) { + window.patternlab = {}; + } + window.patternlab.panels = Panels; +} // gather panels from plugins Dispatcher.trigger('setupPanels'); + +init(); diff --git a/packages/uikit-workshop/src/scripts/components/pl-copy-to-clipboard/pl-copy-to-clipboard.js b/packages/uikit-workshop/src/scripts/components/pl-copy-to-clipboard/pl-copy-to-clipboard.js new file mode 100755 index 000000000..60cb46a8b --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-copy-to-clipboard/pl-copy-to-clipboard.js @@ -0,0 +1,25 @@ +/** + * Copy to clipboard functionality for code snippet examples + */ + +import Clipboard from 'clipboard'; + +const clipboard = new Clipboard('.pl-js-code-copy-btn'); +clipboard.on('success', function (e) { + const copyButton = document.querySelectorAll('.pl-js-code-copy-btn'); + for (let i = 0; i < copyButton.length; i++) { + copyButton[i].querySelector('.pl-c-code-copy-btn__icon-text').innerText = + 'Copy'; + } + e.trigger.classList.add('is-copied'); + e.trigger.querySelector('.pl-c-code-copy-btn__icon-text').textContent = + 'Copied'; + + setTimeout(() => { + e.trigger.classList.remove('is-copied'); + e.trigger.querySelector('.pl-c-code-copy-btn__icon-text').textContent = + 'Copy'; + e.clearSelection(); + e.trigger.blur(); + }, 2000); +}); diff --git a/packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.js b/packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.js deleted file mode 100644 index 7fa8b8e91..000000000 --- a/packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.js +++ /dev/null @@ -1,88 +0,0 @@ -import { define, props } from 'skatejs'; -import { h } from 'preact'; -import Hogan from 'hogan.js'; -const classNames = require('classnames'); - -import { store } from '../../store.js'; // connect to redux -import { BaseComponent } from '../base-component.js'; - -import iFrameResize from 'iframe-resizer/js/iframeResizer.js'; -iFrameResize({ - checkOrigin: false, - scrolling: false, - heightCalculationMethod: 'documentElementOffset', // most accurate calculation in testing available options - initCallback() { - document.querySelector('.pl-js-iframe').classList.add('is-ready'); // toggles class that removes initial min-height styling - }, -}); - -@define -class Layout extends BaseComponent { - static is = 'pl-layout'; - - constructor(self) { - self = super(self); - try { - /* load pattern nav */ - const template = document.querySelector('.pl-js-pattern-nav-template'); - const templateCompiled = Hogan.compile(template.innerHTML); - const templateRendered = templateCompiled.render(window.navItems); - this.renderRoot.querySelector( - '.pl-js-pattern-nav-target' - ).innerHTML = templateRendered; - - /* load ish controls */ - const controlsTemplate = document.querySelector( - '.pl-js-ish-controls-template' - ); - const controlsTemplateCompiled = Hogan.compile( - controlsTemplate.innerHTML - ); - const controlsTemplateRendered = controlsTemplateCompiled.render( - window.ishControls - ); - this.renderRoot.querySelector( - '.pl-js-controls' - ).innerHTML = controlsTemplateRendered; - } catch (e) { - const message = - '

      Please generate your site before trying to view it.

      '; - this.renderRoot.querySelector( - '.pl-js-pattern-nav-target' - ).innerHTML = message; - } - return self; - } - - static props = { - layoutMode: props.string, - themeMode: props.string, - }; - - connected() { - const state = store.getState(); - this.layoutMode = state.app.layoutMode; - this.themeMode = state.app.themeMode; - } - - get renderRoot() { - return this; - } - - _stateChanged(state) { - this.layoutMode = state.app.layoutMode; - this.themeMode = state.app.themeMode; - - const classes = classNames({ - [`pl-c-body--theme-${this.themeMode}`]: this.themeMode !== undefined, - [`pl-c-body--theme-${ - this.layoutMode === 'vertical' ? 'sidebar' : 'horizontal' - }`]: - this.layoutMode !== undefined, - }); - - this.className = classes; - } -} - -export { Layout }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/get-parents.js b/packages/uikit-workshop/src/scripts/components/pl-nav/get-parents.js new file mode 100644 index 000000000..8b9ac4b61 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/get-parents.js @@ -0,0 +1,18 @@ +export const getParents = (elem, selector) => { + // Set up a parent array + const parents = []; + + // Push each parent element to the array + for (; elem && elem !== document; elem = elem.parentNode) { + if (selector) { + if (elem.matches(selector)) { + parents.push(elem); + } + continue; + } + parents.push(elem); + } + + // Return our parent array + return parents; +}; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/index.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/index.scss new file mode 100644 index 000000000..ef1048381 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/index.scss @@ -0,0 +1,9 @@ +/*------------------------------------*\ + #NAVIGATION +\*------------------------------------*/ + +@import './nav.scss'; +@import './nav-link.scss'; +@import './nav-list.scss'; +@import './nav-dropdown.scss'; +@import './nav-accordion.scss'; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-accordion.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-accordion.scss new file mode 100644 index 000000000..e70a4d989 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-accordion.scss @@ -0,0 +1,26 @@ +@import '../../../sass/scss/core.scss'; + +.pl-c-nav__accordion { + background-color: inherit; // allows the nav's children inherit from the parent header + @include listReset(); + @include accordionPanel(); + display: flex; + flex-flow: row wrap; + opacity: 0; + visibility: hidden; +} + +.is-open ~ .pl-c-nav__accordion { + visibility: visible; + max-height: none; + transform: translateY(0); + opacity: 1; + + .pl-c-body--theme-horizontal & { + overflow: auto; + + @media all and (min-width: $pl-bp-med) { + max-height: calc(100vh - #{$offset-top} - 2rem); /* 1 */ + } + } +} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-dropdown.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-dropdown.scss new file mode 100644 index 000000000..0c461649b --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-dropdown.scss @@ -0,0 +1,42 @@ +@import '../../../sass/scss/core.scss'; + +/** + * Nav Dropdown + * 1) On larger screens, display as dropdowns that + * hangs over the header + */ +.pl-c-nav__dropdown { + @media all and (min-width: $pl-bp-med) { + position: absolute; + top: 100%; /* 1 */ + left: 0; + min-width: 14rem; + border-radius: $pl-border-radius-med; + border-style: solid; + border-width: 1px; + box-shadow: 0 2px 5px rgba($pl-color-black, 0.1); + transition: all 0.2s ease; + transform: translateY(-12px); + z-index: 1; + transition: all $pl-animate-quick ease-out; + + .pl-c-body--theme-sidebar & { + position: relative; + } + } + + .pl-c-body--theme-light & { + border-color: rgba($pl-color-black, 0.2); + } + + .pl-c-body--theme-dark & { + border-color: rgba($pl-color-white, 0.2); + } + + .pl-c-body--theme-sidebar & { + border-width: 0; + transform: none; + box-shadow: none; + border-radius: 0; + } +} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.js b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.js new file mode 100644 index 000000000..27d4b22cc --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.js @@ -0,0 +1,47 @@ +// this line is required for rendering even if it is note used in the code +import { h, Fragment } from 'preact'; +const classNames = require('classnames'); + +export const NavLink = (props) => { + const classes = classNames('pl-c-nav__link', { + [`pl-c-nav__link--level-${props.level}`]: props.level !== undefined, + 'pl-c-nav__link--icon-only': props.iconOnly, + 'pl-c-nav__link--title': props.isTitle, + }); + + const Tag = props.href ? 'a' : 'button'; + + return ( + + {props.iconPos === 'before' && props.iconName && ( + `, + }} + /> + )} + + {props.children} + {props.status && ( + + )} + + {props.iconPos !== 'before' && props.iconName && ( + `, + }} + /> + )} + + ); +}; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.scss new file mode 100644 index 000000000..4950b1b8d --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-link.scss @@ -0,0 +1,194 @@ +@import '../../../sass/scss/core.scss'; + +/** + * Nav link + */ +.pl-c-nav__link { + @include linkStyle; + border: 0; + text-align: left; + text-decoration: none; + cursor: pointer; + outline: 0; + color: inherit; + display: flex; + align-items: center; + margin: 0; // remove default button margin in Safari + color: inherit; + flex-grow: 1; + flex-shrink: 1; + padding: 0.6rem 0.6rem; + flex-basis: calc(100% - 2.5rem); + position: relative; + height: var(--nav-item-height, auto); + + &::after { + content: ''; + pointer-events: none; + opacity: 0; + background-color: currentColor; + transition: opacity $pl-animate-quick ease-out; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + display: block; + } + + &:hover::after { + opacity: 0.1; + } + + &:focus::after { + opacity: 0.1; + } + + &:focus { + outline-offset: -1px; + outline: 1px dotted; + } + + &--level-0 { + .pl-c-body--theme-sidebar & { + padding-left: 1.45rem; + } + + @media all and (max-width: $pl-bp-med) { + padding-left: 1.45rem; + } + } + + &--level-1 { + padding-left: $pl-space + ($pl-space * 0.5); + font-size: 0.85rem; + } + + &--level-2 { + font-size: 0.825rem; + padding-left: $pl-space * 2 + ($pl-space * 0.25); + } + + // top level nav links (categories) + &--title { + font-size: 0.8rem; + color: $pl-color-gray-20; + color: var(--theme-text, $pl-color-gray-20); + + > .pl-c-nav__link-icon { + font-size: inherit; + } + + .pl-c-body--theme-light & { + color: $pl-color-black; + color: var(--theme-text); + } + } + + &.is-active:not(.pl-c-nav__link--title) { + box-shadow: inset 4px 0 0 #6c79d9; + + // move the "active" border style to the bottom on ONLY the top level links (ex. "All") + @media all and (min-width: $pl-bp-med) { + &.pl-c-nav__link--level-0 { + .pl-c-body--theme-horizontal & { + box-shadow: inset 0 -4px 0 #6c79d9; + } + } + } + } +} + +.pl-c-nav__link-text { + flex-grow: 1; + pointer-events: none; + display: flex; + align-items: center; +} + +.pl-c-nav__link-icon { + margin-top: -0.5rem; + margin-bottom: -0.5rem; + pointer-events: none; + color: currentColor; + display: inline; + transition: all $pl-animate-quick ease-out; + transform: rotate(-90deg); + flex-grow: 0; + line-height: 0; + font-size: 1.3rem; // temp solution till new pl-button used in Navigation +} + +.pl-c-nav__link.is-open > .pl-c-nav__link-icon, +.pl-c-nav__link.is-open ~ .pl-c-nav__link > .pl-c-nav__link-icon { + transform: rotate(0); +} + +// workaround to disable focus on links inside open panels within a closed dropdown +.pl-c-nav__link:first-child:not(.is-open) ~ .pl-c-nav__list--panel { + .pl-c-nav__link { + visibility: hidden; + } +} + +// workaround to disable focus on links inside open panels within a closed dropdown +.is-open ~ .pl-c-nav__list--panel { + .pl-c-nav__link { + visibility: visible; + } +} + +.pl-c-nav__link--icon-only { + position: relative; + width: 2.5rem !important; + height: 2.5rem !important; + padding: 0 !important; + display: inline-flex; + justify-content: center; + font-size: 0; + flex-basis: 2.5rem; + right: 0; + border: 2px solid transparent !important; + justify-content: center; + align-items: center; + color: currentColor; + + // border to indicate which nav links have two specific actions + &::before { + opacity: 0.1; + right: 2.4rem; + width: 1px; + left: auto; + transform: translateY(-50%); + } + + &::after { + opacity: 0; + width: 2.5rem; + left: 50%; + transform: translateY(-50%) translateX(-50%); + } + + &::before, + &::after { + height: 2.5rem; + transition: opacity $pl-animate-quick ease-out; + content: ''; + display: block; + position: absolute; + top: 50%; + background-color: currentColor; + } + + &:hover { + &::after, + &:focus::after { + opacity: 0.1; + } + } + + &:focus { + outline-offset: -1px; + outline: 1px dotted; + } +} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.js b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.js new file mode 100644 index 000000000..b8538fa54 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.js @@ -0,0 +1,89 @@ +/* eslint-disable no-unused-vars, no-shadow */ +// this line is required for rendering even if it is note used in the code +import { h, Fragment } from 'preact'; +import { NavLink } from './nav-link'; + +export const NavList = (props) => { + const { children, category, elem } = props; + + const nonViewAllItems = elem.noViewAll + ? children.filter((item) => item.patternName !== 'View All') + : children.filter( + (item) => + item.patternName !== 'View All' && !item.patternName.includes(' Docs') + ); + const viewAllItems = elem.noViewAll + ? [] + : children.filter((item) => item.patternName === 'View All'); + + return ( +
    1. + {viewAllItems.length > 0 ? ( + viewAllItems.map((patternSubtypeItem) => ( + <> + + elem.handleClick(e, patternSubtypeItem.patternPartial) + } + state={patternSubtypeItem.patternState} + data-patternpartial={patternSubtypeItem.patternPartial} + > + {patternSubtypeItem.patternName === 'View All' + ? `${category}` + : patternSubtypeItem.patternName} + + + {nonViewAllItems.length >= 1 && ( + elem.iconOnlyPanelToggle(e.target)} + > + {category} + + )} + + )) + ) : ( + elem.panelToggle(e.target)} + > + {category} + + )} + + {((viewAllItems.length && nonViewAllItems.length) || + viewAllItems.length === 0) && ( +
        + {nonViewAllItems.map((patternSubtypeItem) => ( +
      1. + + elem.handleClick(e, patternSubtypeItem.patternPartial) + } + data-patternpartial={patternSubtypeItem.patternPartial} + status={patternSubtypeItem.patternState} + > + {patternSubtypeItem.patternName === 'View All' + ? `${category} Overview` + : patternSubtypeItem.patternName} + +
      2. + ))} +
      + )} +
    2. + ); +}; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.scss new file mode 100644 index 000000000..0e01cf1c5 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav-list.scss @@ -0,0 +1,37 @@ +@import '../../../sass/scss/core.scss'; + +/** + * Nav list + * 1) appears as an
        + * 2) display as a horizontal list on larger screens + * 3) On small screens, move the nav list after the typeahead form field + */ +.pl-c-nav__list { + z-index: 1; + margin: 0; + padding: 0; + list-style: none; + flex-shrink: 0; // helps prevent top-level nav items from occasionally wrapping to multiple lines + flex-grow: 1; // auto-fill extra space available + width: 100%; + max-width: 100%; // so content doesn't won't spill out horizontally + order: 2; + background-color: inherit; // allows the nav's children inherit from the parent header + + @media all and (min-width: $pl-bp-med) { + display: flex; /* 2 */ + order: 1; + } +} + +/** + * Nav list item + */ +.pl-c-nav__list-item { + background-color: inherit; // allows the nav's children inherit from the parent header + position: relative; + display: flex; + flex-direction: column; + flex-flow: row wrap; + width: 100%; +} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav.js b/packages/uikit-workshop/src/scripts/components/pl-nav/nav.js new file mode 100644 index 000000000..a38cf006c --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav.js @@ -0,0 +1,308 @@ +/* eslint-disable no-unused-vars, no-shadow */ +import { define, props } from 'skatejs'; +// this line is required for rendering even if it is note used in the code +import { h, Fragment } from 'preact'; + +const classNames = require('classnames'); + +import { getParents } from './get-parents'; +import { store } from '../../store.js'; // redux store +import { BaseComponent } from '../base-component.js'; +import Mousetrap from 'mousetrap'; + +import { NavLink } from './nav-link'; +import { NavList } from './nav-list'; +import { iframeMsgDataExtraction } from '../../utils'; + +@define +class Nav extends BaseComponent { + static is = 'pl-nav'; + + static props = { + autoClose: { + ...props.boolean, + ...{ default: true }, + }, + currentPattern: props.string, + layoutMode: props.string, + collapsedByDefault: { + ...props.boolean, + ...{ default: true }, + }, + noViewAll: { + ...props.boolean, + ...{ default: window.config?.theme?.noViewAll || false }, + }, + }; + + constructor(self) { + self = super(self); + self.panelToggle = self.panelToggle.bind(self); + self.iconOnlyPanelToggle = self.iconOnlyPanelToggle.bind(self); + self.handleClick = self.handleClick.bind(self); + self.handleTopLevelNavClick = self.handleTopLevelNavClick.bind(self); + self.handleURLChange = self.handleURLChange.bind(self); + self.handlePageClick = self.handlePageClick.bind(self); + self._hasInitiallyRendered = false; + self.receiveIframeMessage = self.receiveIframeMessage.bind(self); + self.useShadow = false; + return self; + } + + handlePageClick(e) { + if ( + e.target.closest && + e.target.closest('.pl-c-nav') === null && + e.target.closest('.pl-js-nav-trigger') === null && + e.target.closest('svg') === null && + e.target.closest('pl-toggle-layout') === null + ) { + if (this.layoutMode !== 'vertical' && window.innerWidth > 670) { + this.cleanupActiveNav(true); + } + } + } + + connected() { + this.isOpenClass = 'is-open'; + const state = store.getState(); + this.layoutMode = state.app.layoutMode || ''; + this.currentPattern = state.app.currentPattern || ''; + this.elem = this; + this.previouslyActiveLinks = []; + this.iframeElem = document.querySelector('pl-iframe'); + + window.addEventListener('message', this.receiveIframeMessage, false); + document.body.addEventListener('click', this.handlePageClick); + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + + Mousetrap.bind('esc', () => { + if (this.layoutMode !== 'vertical' && window.innerWidth > 670) { + this.cleanupActiveNav(true); + } + }); + } + + disconnected() { + super.disconnected && super.disconnected(); + document.body.removeEventListener('click', this.handlePageClick); + window.removeEventListener('message', this.receiveIframeMessage); + } + + _stateChanged(state) { + if (this.layoutMode !== state.app.layoutMode) { + this.layoutMode = state.app.layoutMode || ''; + } + + if ( + state.app.currentPattern && + this.currentPattern !== state.app.currentPattern + ) { + this.currentPattern = state.app.currentPattern; + this.handleURLChange(); // so the nav logic is always correct (ex. layout changes) + } + } + + receiveIframeMessage(event) { + const self = this; + const data = iframeMsgDataExtraction(event); + + if (data.event !== undefined && data.event === 'patternLab.pageClick') { + try { + if (self.layoutMode !== 'vertical') { + self.cleanupActiveNav(true); + } + } catch (error) { + console.log(error); + } + } + } + + /** + * Helper method that partially cleans up the active nav links + * @param {boolean} topLevelOnly - only clean up the top most level nav links + * @param {Node} exceptFor - optionally specify an element to skip cleaning up + */ + cleanupActiveNav(topLevelOnly, exceptFor) { + this.navContainer = document.querySelector('.pl-js-nav-container'); + this.topLevelTriggers = document.querySelectorAll( + '.pl-c-nav__link--title.is-open' + ); + + if (topLevelOnly === true && window.innerWidth > 670) { + this.navContainer.classList.remove('is-open'); + this.topLevelTriggers.forEach((trigger) => { + if (trigger !== exceptFor || exceptFor === undefined) { + trigger.classList.remove('is-open'); + } + }); + } else { + this.navContainer.classList.remove('is-open'); + } + } + + handleClick(event, pattern) { + event.preventDefault(); + this.iframeElem.navigateTo(pattern); + this.cleanupActiveNav(); + } + + // auto-close other top level nav dropdowns on larger screens + handleTopLevelNavClick(e) { + if (this.layoutMode !== 'vertical' && window.innerWidth > 670) { + this.cleanupActiveNav(true, e.target); + } + this.panelToggle(e.target); + } + + handleURLChange() { + const currentPattern = this.currentPattern; + this.activeLink = document.querySelector( + `[data-patternpartial="${currentPattern}"]` + ); + + if (this.previouslyActiveLinks) { + this.previouslyActiveLinks.forEach((link, index) => { + this.previouslyActiveLinks[index].classList.remove('is-open'); + this.previouslyActiveLinks[index].classList.remove('is-active'); + }); + } + this.previouslyActiveLinks = []; + + if (this.activeLink) { + this.activeLink.classList.add('is-active'); + + const triggers = [this.activeLink]; + const panels = Array.from( + getParents(this.activeLink, '.pl-js-nav-accordion') + ); + + panels.forEach((panel) => { + const panelTrigger = panel.previousSibling; + if (panelTrigger) { + if (panelTrigger.previousSibling) { + triggers.push(panelTrigger.previousSibling); + } else { + triggers.push(panelTrigger); + } + } + }); + + triggers.forEach((trigger) => { + trigger.classList.add('is-open'); + this.previouslyActiveLinks.push(trigger); + }); + } + } + + iconOnlyPanelToggle(target) { + target.previousSibling.classList.toggle('is-open'); + } + + panelToggle(target) { + target.classList.toggle('is-open'); + } + + rendered() { + if (this._hasInitiallyRendered === false) { + this._hasInitiallyRendered = true; + } + + if (!this.activeLink) { + this.handleURLChange(); + } + + if (this.layoutMode !== 'vertical' && window.innerWidth > 670) { + this.cleanupActiveNav(true); + } + } + + render({ layoutMode }) { + const patternGroups = window.navItems.patternGroups; + + return ( +
          + {patternGroups.map((item, i) => { + const classes = classNames('pl-c-nav__list-item'); + const patternItems = item.patternItems; + + return ( +
        1. + + {item.patternGroupLC} + +
            + {item.patternGroupItems.map((patternSubgroup, i) => { + return ( + + {patternSubgroup.patternSubgroupItems} + + ); + })} + + {patternItems && + patternItems.map((patternItem, i) => { + return this.noViewAll && + patternItem.patternPartial.includes('viewall') ? ( + '' + ) : ( +
          1. + + this.handleClick(e, patternItem.patternPartial) + } + data-patternpartial={patternItem.patternPartial} + state={patternItem.patternState} + > + {patternItem.patternName === 'View All' + ? patternItem.patternName + ' ' + item.patternTypeUC + : patternItem.patternName} + +
          2. + ); + })} +
          +
        2. + ); + })} + + {/* display the All link if window.ishControlsHide is undefined (for some reason) OR window.ishControls.ishControlsHide doesn't have `views-all` and/or `all` set to true */} + {(window.ishControls === undefined || + window.ishControls.ishControlsHide === undefined || + (window.ishControls.ishControlsHide['views-all'] !== true && + window.ishControls.ishControlsHide.all !== true)) && + !this.noViewAll && ( +
        3. + this.handleClick(e, 'all')} + href="styleguide/html/styleguide.html" + level={0} + data-patternpartial="all" + > + All + +
        4. + )} +
        + ); + } +} + +export { Nav }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/nav.scss b/packages/uikit-workshop/src/scripts/components/pl-nav/nav.scss new file mode 100644 index 000000000..9a2c1e682 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/nav.scss @@ -0,0 +1,137 @@ +/*------------------------------------*\ + #NAVIGATION +\*------------------------------------*/ + +pl-nav { + background-color: inherit; // so the inside of dropdowns inherits the correct color + display: block; // vertically align children + flex-grow: 1; + align-items: center; + + @media all and (min-width: $pl-bp-med) { + padding: 0; + display: flex; // vertically align children + } + + .pl-c-body--theme-sidebar & { + display: block; + max-height: 100%; + overflow-y: scroll; + } +} + +/** + * Navigation container + * 1) Collapse height on small screens. Menu trigger button + * activates nav + */ +.pl-c-nav { + @include accordionPanel; + background-color: inherit; // allows the nav's children inherit from the parent header + position: absolute; + left: 0; // IE 11 layout broken + top: 100%; + width: 100%; + display: flex; + flex-direction: column; + transition: max-height $pl-animate-quick ease-out; + flex-shrink: 1; + visibility: hidden; + transition: transform 0.2s ease-out, opacity 0 0.2s ease-out; + + @media all and (max-width: $pl-bp-med) { + position: fixed; + top: 44px; + bottom: 0; + height: auto; + z-index: -1; + } + + &.pl-is-active { + visibility: visible; + opacity: 1; + } + + .pl-c-body--theme-sidebar & { + display: block; + display: flex; + overflow: hidden; + visibility: visible; + flex-shrink: 0; + + @media all and (min-height: 500px) { + flex-shrink: 1; + } + + @media all and (max-width: $pl-bp-med) { + max-width: 240px; + + position: fixed; + top: 44px; + bottom: 0; + height: auto; + max-height: calc(100% - 2rem); + overflow: auto; + -webkit-overflow-scrolling: touch; + transform: translateX(-100%); + transition: all 0.3s ease; + opacity: 0; + box-shadow: 0 3px 6px rgba(21, 22, 25, 0.16), + 0 3px 6px rgba(21, 22, 25, 0.23); + visibility: visible; + + &.pl-is-active { + transform: translateX(0); + opacity: 1; + transition: transform 0.2s ease-out; + } + } + } + + @media all and (max-width: $pl-bp-med) { + &.is-open { + padding-top: 1rem; + padding-bottom: 1rem; + } + } + + // if nav was opened on smaller screen and screen is resized, it'll be cut off otherwise + @media all and (min-width: $pl-bp-med) { + overflow: visible; + max-height: none; + visibility: visible; + + &.is-open { + overflow: visible; + } + } + + /** + * Active navigaiton + * 1) Slide + * 2) Set the height to the vierport height minus the height + * of the header + */ + &.is-open { + @media all and (max-width: $pl-bp-med - 1) { + box-shadow: 0 2px 4px $pl-color-black; + + .pl-c-body--theme-light & { + box-shadow: 0 2px 4px darken($pl-color-gray-20, 15%); + } + } + + // if nav was opened on smaller screen and screen is resized, it'll be cut off otherwise + @media all and (min-width: $pl-bp-med) { + max-height: none; + } + } + + @media all and (min-width: $pl-bp-med) { + flex-direction: row; + position: relative; + top: auto; + width: auto; + box-shadow: none; + } +} diff --git a/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.iframe-helper.js b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.iframe-helper.js new file mode 100644 index 000000000..5b2a0fd13 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/pl-nav/pl-nav.iframe-helper.js @@ -0,0 +1,32 @@ +// Tiny helper script to listen for keyboard combos and to communicate back to the main Search component (via the Pattern Lab iframe) +import Mousetrap from 'mousetrap'; +import { targetOrigin } from '../../utils'; + +document.addEventListener('click', function () { + try { + const obj = JSON.stringify({ + event: 'patternLab.pageClick', + }); + window.parent.postMessage(obj, targetOrigin); + } catch (error) { + // @todo: how do we want to handle exceptions here? + } +}); + +Mousetrap.bind('esc', function (e) { + try { + const obj = JSON.stringify({ + event: 'patternLab.keyPress', + key: e.key, + altKey: e.altKey, + ctrlKey: e.ctrlKey, + metaKey: e.metaKey, + shiftKey: e.shiftKey, + }); + window.parent.postMessage(obj, targetOrigin); + } catch (error) { + // @todo: how do we want to handle exceptions here? + } + + return false; +}); diff --git a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.iframe-helper.js b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.iframe-helper.js index f330c8cd7..b62896af0 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.iframe-helper.js +++ b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.iframe-helper.js @@ -2,7 +2,7 @@ import Mousetrap from 'mousetrap'; import { targetOrigin } from '../../utils'; -Mousetrap.bind('command+shift+f', function(e) { +Mousetrap.bind('command+shift+f', function (e) { e.preventDefault(); try { diff --git a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.js b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.js index c27480a44..8aa566a73 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.js +++ b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.js @@ -1,22 +1,23 @@ +/* eslint-disable no-unused-vars, no-param-reassign */ import { define, props } from 'skatejs'; import { h } from 'preact'; +import { store } from '../../store.js'; // connect to redux + import Fuse from 'fuse.js'; import ReactHtmlParser from 'react-html-parser'; import classNames from 'classnames'; import Mousetrap from 'mousetrap'; - -import VisuallyHidden from '@reach/visually-hidden'; import Autosuggest from 'react-autosuggest'; -import { urlHandler } from '../../utils'; +import { urlHandler, iframeMsgDataExtraction } from '../../utils'; import { BaseComponent } from '../base-component'; @define class Search extends BaseComponent { static is = 'pl-search'; - constructor(self) { - self = super(self); + constructor() { + super(); this.useShadow = false; this.defaultMaxResults = 10; @@ -28,42 +29,48 @@ class Search extends BaseComponent { this.state = { value: '', suggestions: [], + isFocused: false, }; this.receiveIframeMessage = this.receiveIframeMessage.bind(this); this.onChange = this.onChange.bind(this); this.toggleSearch = this.toggleSearch.bind(this); - // this.clearSearch = this.clearSearch.bind(this); this.closeSearch = this.closeSearch.bind(this); this.renderInputComponent = this.renderInputComponent.bind(this); this.openSearch = this.openSearch.bind(this); + } + + connecting() { + super.connecting && super.connecting(); this.items = []; - for (const patternType in window.patternPaths) { - if (window.patternPaths.hasOwnProperty(patternType)) { - for (const pattern in window.patternPaths[patternType]) { - if (window.patternPaths[patternType].hasOwnProperty(pattern)) { + for (const patternGroup in window.patternPaths) { + if (window.patternPaths.hasOwnProperty(patternGroup)) { + for (const pattern in window.patternPaths[patternGroup]) { + if (window.patternPaths[patternGroup].hasOwnProperty(pattern)) { const obj = {}; - obj.label = patternType + '-' + pattern; - obj.id = window.patternPaths[patternType][pattern]; + obj.label = patternGroup + '-' + pattern; + obj.id = window.patternPaths[patternGroup][pattern]; this.items.push(obj); } } } } - - return self; } connected() { - const self = this; - Mousetrap.bind('command+shift+f', function(e) { + Mousetrap.bind('command+shift+f', function (e) { e.preventDefault(); - self.toggleSearch(); + this.toggleSearch(); }); window.addEventListener('message', this.receiveIframeMessage, false); } + _stateChanged(state) { + // throw new Error('_stateChanged() not implemented', this); + this.triggerUpdate(); + } + rendered() { this.inputElement = this.querySelector('.js-c-typeahead__input'); } @@ -75,8 +82,8 @@ class Search extends BaseComponent { clearButtonText: props.string, }; - onInput = e => { - let value = e.target.value; + onInput = (e) => { + const value = e.target.value; this.setState({ value: value, @@ -85,9 +92,6 @@ class Search extends BaseComponent { this.onSuggestionsFetchRequested({ value }); // re-render search results immediately based on latest input value }; - // External Redux store not yet in use - _stateChanged(state) {} - toggleSearch() { if (!this.state.isOpen) { this.openSearch(); @@ -111,22 +115,12 @@ class Search extends BaseComponent { document.activeElement.blur(); } - receiveIframeMessage(event) { - // does the origin sending the message match the current host? if not dev/null the request - if ( - window.location.protocol !== 'file:' && - event.origin !== window.location.protocol + '//' + window.location.host - ) { - return; - } - - let data = {}; - try { - data = - typeof event.data !== 'string' ? event.data : JSON.parse(event.data); - } catch (e) { - // @todo: how do we want to handle exceptions here? - } + /** + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); if (data.event !== undefined && data.event === 'patternLab.keyPress') { if (data.key === 'f' && data.metaKey === true) { @@ -135,7 +129,7 @@ class Search extends BaseComponent { } } - getSuggestionValue = suggestion => suggestion.label; + getSuggestionValue = (suggestion) => suggestion.label; renderSuggestion(item, { query, isHighlighted }) { return {item.highlightedLabel}; @@ -150,20 +144,18 @@ class Search extends BaseComponent { const fuseOptions = { shouldSort: true, threshold: 0.3, - tokenize: true, includeMatches: true, location: 0, distance: 100, - maxPatternLength: 32, minMatchCharLength: 1, keys: ['label'], }; const fuse = new Fuse(this.items, fuseOptions); const results = fuse.search(value); - const highlighter = function(item) { + const highlighter = function (item) { const resultItem = item; - resultItem.matches.forEach(matchItem => { + resultItem.matches.forEach((matchItem) => { const text = resultItem.item[matchItem.key]; const result = []; const matches = [].concat(matchItem.indices); @@ -187,14 +179,14 @@ class Search extends BaseComponent { ); if (resultItem.children && resultItem.children.length > 0) { - resultItem.children.forEach(child => { + resultItem.children.forEach((child) => { highlighter(child); }); } }); }; - results.forEach(resultItem => { + results.forEach((resultItem) => { highlighter(resultItem); }); @@ -215,14 +207,7 @@ class Search extends BaseComponent { const patternName = urlHandler.getFileName(newValue); if (patternName) { - const obj = JSON.stringify({ - event: 'patternLab.updatePath', - path: patternName, - }); - - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, urlHandler.targetOrigin); + document.querySelector('pl-iframe').navigateTo(newValue); } this.setState({ @@ -254,7 +239,8 @@ class Search extends BaseComponent { return (
        @@ -266,8 +252,9 @@ class Search extends BaseComponent { onClick={() => { this.clearSearch(); }} + type="button" > - {clearButtonText} + {clearButtonText} +
        + +
        ); } } diff --git a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.scss b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.scss index 94e6d3a4e..7daf4614e 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.scss +++ b/packages/uikit-workshop/src/scripts/components/pl-search/pl-search.scss @@ -13,24 +13,29 @@ $pl-clear-button-size-at-med: 1.4rem; pl-search { background-color: inherit; - order: 2; // Display after nav list items top: 0; - z-index: 10; flex-shrink: 0; - padding: 0.3rem 0.5rem; + padding: 0.4rem 0.5rem; display: inline-block; + align-self: stretch; + transition: all 0.2s ease; @media screen and (min-width: $pl-bp-med) { - margin-left: 1rem; flex-direction: row; flex-shrink: 1; + order: 2; // Display after nav list items on wider screens + align-self: center; + + // grow in size when focusing on inner input + &:focus-within { + flex-shrink: 0.5; + } .pl-c-body--theme-sidebar & { flex-direction: column; margin-left: 0; - padding-left: 0; - padding-right: 0; width: 100%; + margin-bottom: 0.5rem; } } } @@ -75,23 +80,27 @@ pl-search { text-transform: capitalize; background-color: $pl-color-gray-87; color: $pl-color-white; - border-color: darken($pl-color-gray-87, 10%); + background-color: rgba(var(--theme-text-rgb), 0.05); + color: rgba(var(--theme-text-rgb), 0.67); + border-color: rgba(0, 0, 0, 0.1); + border-color: rgba(var(--theme-text-rgb), 0.17); text-overflow: ellipsis; border-width: 1px; border-style: solid; transition: all 0.1s ease; max-width: 100%; - padding: 0.31rem 0.5rem; + padding: 0.4rem 0.5rem; font-size: 16px; // prevent zooming in on mobile width: 100%; outline-offset: -3px; outline-width: 2px; + border-radius: 3px; -webkit-appearance: none; // removes default styling (ex. heavy box shadow) in Safari @media all and (min-width: 900px) { font-size: inherit; } - + // Remove the native clear button in IE 11 in lieu of JS-controlled clear button &::-ms-clear { display: none; @@ -111,7 +120,6 @@ pl-search { } @media all and (min-width: $pl-bp-med) { - .pl-c-body--theme-sidebar & { max-width: none; } @@ -119,11 +127,26 @@ pl-search { .pl-c-body--theme-light & { background-color: $pl-color-gray-07; - color: $pl-color-gray-70 !important; - border-color: $pl-color-gray-13 !important; + background-color: rgba(var(--theme-text-rgb), 0.05); + color: $pl-color-gray-70; + color: rgba(var(--theme-text-rgb), 0.67); + + &::-webkit-input-placeholder { + color: black !important; + transition: all 0.1s ease; + } + + &::-moz-input-placeholder { + color: black !important; + transition: all 0.1s ease; + } + } + + &::-webkit-input-placeholder { + color: $pl-color-white !important; + transition: all 0.1s ease; } - &::-webkit-input-placeholder, &::-moz-input-placeholder { color: $pl-color-white !important; transition: all 0.1s ease; @@ -132,12 +155,9 @@ pl-search { &:hover, &:focus { color: $pl-color-white; - background-color: darken($pl-color-gray-87, 2%) !important; .pl-c-body--theme-light & { color: $pl-color-gray-87 !important; - background-color: $pl-color-gray-13 !important; - border-color: $pl-color-gray-20 !important; } &::-moz-input-placeholder, @@ -154,6 +174,8 @@ pl-search { .pl-c-typeahead__menu { @include accordionPanel; background-color: $pl-color-gray-87; + background-color: var(--theme-primary); + color: var(--theme-text); text-transform: capitalize; position: absolute; min-width: 100%; @@ -176,8 +198,8 @@ pl-search { } &.pl-is-open { - max-height: 120rem; - max-height: calc(var(--viewport-height) - 4rem); + max-height: 90vh; + overflow: auto; opacity: 1; } @@ -229,14 +251,20 @@ pl-search { .pl-c-typeahead__result { transition: all 0.3s ease; background-color: inherit; - padding: 0.8em; + padding: 0.5rem 0.75rem; cursor: pointer; overflow: hidden; + font-size: 0.8rem; + color: inherit; &:last-child { border-bottom-right-radius: $pl-border-radius-med; border-bottom-left-radius: $pl-border-radius-med; + @media all and (max-width: $pl-bp-med - 1) { + border-radius: 0; + } + .pl-c-body--theme-sidebar & { border-radius: 0; } @@ -272,6 +300,7 @@ pl-search { .pl-c-typeahead__input-wrapper { position: relative; // used for positioning search clear button in relation to the + flex-shrink: 1; } .pl-c-typeahead__clear-button { diff --git a/packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.js b/packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.js deleted file mode 100644 index 5c32b282b..000000000 --- a/packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.js +++ /dev/null @@ -1,86 +0,0 @@ -import { define, props } from 'skatejs'; -import { h } from 'preact'; - -import { store } from '../../store.js'; // connect to the Redux store. -import { updateLayoutMode } from '../../actions/app.js'; // redux actions -import { BaseComponent } from '../base-component.js'; - -import './pl-toggle-layout.scss?external'; -import styles from './pl-toggle-layout.scss'; - -@define -class LayoutToggle extends BaseComponent { - static is = 'pl-toggle-layout'; - - constructor(self) { - self = super(self); - this.useShadow = false; - return self; - } - - connected() { - const state = store.getState(); - this.layoutMode = state.app.layoutMode || 'vertical'; - store.dispatch(updateLayoutMode(this.layoutMode)); - } - - static props = { - layoutMode: props.string, - text: props.string, - }; - - _stateChanged(state) { - if (this.layoutMode !== state.app.layoutMode) { - this.layoutMode = state.app.layoutMode; - } - } - - render({ layoutMode, text }) { - const toggleLayoutMode = - layoutMode !== 'vertical' ? 'vertical' : 'horizontal'; - return ( -
        - {this._renderStyles([styles])} - -
        - ); - } -} - -export { LayoutToggle }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.js b/packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.js deleted file mode 100644 index 776a429ea..000000000 --- a/packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.js +++ /dev/null @@ -1,92 +0,0 @@ -import { define, props } from 'skatejs'; -import { h } from 'preact'; - -import { store } from '../../store.js'; // connect to the Redux store. -import { updateThemeMode } from '../../actions/app.js'; // redux actions needed -import { BaseComponent } from '../base-component.js'; - -import './pl-toggle-theme.scss?external'; -import styles from './pl-toggle-theme.scss'; - -@define -class ThemeToggle extends BaseComponent { - static is = 'pl-toggle-theme'; - - constructor(self) { - self = super(self); - this.useShadow = false; - return self; - } - - connected() { - const state = store.getState(); - this.themeMode = state.app.themeMode || 'dark'; - store.dispatch(updateThemeMode(this.themeMode)); - } - - static props = { - themeMode: props.string, - }; - - _stateChanged(state) { - this.themeMode = state.app.themeMode; - } - - render({ themeMode }) { - const toggleThemeMode = this.themeMode !== 'dark' ? 'dark' : 'light'; - return ( -
        - {this._renderStyles([styles])} - -
        - ); - } -} - -export { ThemeToggle }; diff --git a/packages/uikit-workshop/src/scripts/components/plugin-loader.js b/packages/uikit-workshop/src/scripts/components/plugin-loader.js index 239e1b992..7a7cc5c64 100644 --- a/packages/uikit-workshop/src/scripts/components/plugin-loader.js +++ b/packages/uikit-workshop/src/scripts/components/plugin-loader.js @@ -10,7 +10,7 @@ const scriptjs = require('scriptjs'); export const pluginLoader = { init() { for (let i = 0; i < window.plugins.length; ++i) { - const plugin = window.lugins[i]; + const plugin = window.plugins[i]; // load the templates for (const key in plugin.templates) { diff --git a/packages/uikit-workshop/src/scripts/components/prism-languages.js b/packages/uikit-workshop/src/scripts/components/prism-languages.js index 11a807c46..c418f9194 100644 --- a/packages/uikit-workshop/src/scripts/components/prism-languages.js +++ b/packages/uikit-workshop/src/scripts/components/prism-languages.js @@ -1,45 +1,17 @@ -/** - * Default languages for Prism to match rendering capability - */ - -export const PrismLanguages = { - languages: [], - - get(key) { - let language; - - for (let i = 0; i < this.languages.length; ++i) { - language = this.languages[i]; - if (language[key] !== undefined) { - return language[key]; - } - } - - return 'markup'; - }, - - add(language) { - // see if the language already exists, overwrite if it does - for (const key in language) { - if (language.hasOwnProperty(key)) { - for (let i = 0; i < this.languages.length; ++i) { - if (this.languages[i][key] !== undefined) { - this.languages[i][key] = language[key]; - return; - } - } - } - } - - this.languages.push(language); - }, -}; - -// this shouldn't get hardcoded, also need to think about including Prism's real lang libraries (e.g. handlebars & twig) -PrismLanguages.add({ - twig: 'markup', -}); - -PrismLanguages.add({ - mustache: 'markup', -}); +import Prism from 'prismjs/components/prism-core'; +import 'prismjs/components/prism-markup-templating'; +import 'prismjs/components/prism-markup'; +import 'prismjs/components/prism-twig'; +import 'prismjs/components/prism-clike'; +import 'prismjs/components/prism-javascript'; +import 'prismjs/components/prism-typescript'; +import 'prismjs/components/prism-json'; +import 'prismjs/components/prism-css'; +import 'prismjs/components/prism-css-extras'; +import 'prismjs/components/prism-scss'; +import 'prismjs/components/prism-bash'; +import 'prismjs/components/prism-markdown'; +import 'prismjs/components/prism-yaml'; +import 'prismjs/components/prism-handlebars'; + +export const PrismLanguages = Prism; diff --git a/packages/uikit-workshop/src/scripts/components/styleguide.js b/packages/uikit-workshop/src/scripts/components/styleguide.js index 1e996eec9..86dcc7a7e 100644 --- a/packages/uikit-workshop/src/scripts/components/styleguide.js +++ b/packages/uikit-workshop/src/scripts/components/styleguide.js @@ -2,688 +2,528 @@ * Styleguide.js - misc UI logic for Pattern Lab that needs refactoring */ -import $ from 'jquery'; -import Mousetrap from 'mousetrap'; -import { urlHandler, DataSaver } from '../utils'; - -(function(w) { - let sw = document.body.clientWidth; //Viewport Width - - let minViewportWidth = 240; - let maxViewportWidth = 2600; - - //set minimum and maximum viewport based on confg - if (window.config.ishMinimum !== undefined) { - minViewportWidth = parseInt(window.config.ishMinimum, 10); //Minimum Size for Viewport - } - if (window.config.ishMaximum !== undefined) { - maxViewportWidth = parseInt(window.config.ishMaximum, 10); //Maxiumum Size for Viewport - } - - //alternatively, use the ishViewportRange object - if (window.config.ishViewportRange !== undefined) { - minViewportWidth = window.config.ishViewportRange.s[0]; - maxViewportWidth = window.config.ishViewportRange.l[1]; - } - - //if both are set, then let's use the larger one. - if (window.config.ishViewportRange && window.config.ishMaximum) { - const largeRange = parseInt(window.config.ishViewportRange.l[1], 10); - const ishMaximum = parseInt(window.config.ishMaximum, 10); - maxViewportWidth = largeRange > ishMaximum ? largeRange : ishMaximum; - } - - const viewportResizeHandleWidth = 14; //Width of the viewport drag-to-resize handle - const $sgIframe = $('.pl-js-iframe'); //Viewport element - const $sizePx = $('#pl-size-px'); //Px size input element in toolbar - const $sizeEms = $('#pl-size-em'); //Em size input element in toolbar - const $bodySize = - window.config.ishFontSize !== undefined - ? parseInt(window.config.ishFontSize, 10) - : parseInt($('body').css('font-size'), 10); //Body size of the document - let discoID = false; - let discoMode = false; - let fullMode = true; - let hayMode = false; - - //Update dimensions on resize - $(w).resize(function() { - sw = document.body.clientWidth; - - if (fullMode === true) { - sizeiframe(sw, false); - } - }); - - // Nav menu button on small screens - $('.pl-js-nav-trigger').on('click', function(e) { - e.preventDefault(); - $('.pl-js-nav-target').toggleClass('pl-is-active'); - }); - - // Accordion dropdown - $('.pl-js-acc-handle').on('click', function(e) { - const $this = $(this); - const $panel = $this.next('.pl-js-acc-panel'); - const subnav = $this - .parent() - .parent() - .hasClass('pl-js-acc-panel'); - - //Close other panels if link isn't a subnavigation item - if (!subnav) { - $('.pl-js-acc-handle') - .not($this) - .removeClass('pl-is-active'); - $('.pl-js-acc-panel') - .not($panel) - .removeClass('pl-is-active'); - } - - //Activate selected panel - $this.toggleClass('pl-is-active'); - $panel.toggleClass('pl-is-active'); - }); - - //Size View Events - - // handle small button - function goSmall() { +// import $ from 'jquery'; +// import Mousetrap from 'mousetrap'; +// import { urlHandler, DataSaver, patternName } from '../utils'; + +// import { store } from '../store.js'; // connect to the Redux store. +// import { updateViewportPx, updateViewportEm } from '../actions/app.js'; // redux actions needed + +// import { minViewportWidth, maxViewportWidth } from '../utils'; + +// (function(w) { +// let sw = document.body.clientWidth; //Viewport Width + +// const viewportResizeHandleWidth = 14; //Width of the viewport drag-to-resize handle +// const $sgIframe = $('.pl-js-iframe'); //Viewport element +// const $sizePx = $('#pl-size-px'); //Px size input element in toolbar +// const $sizeEms = $('#pl-size-em'); //Em size input element in toolbar +// let discoID = false; +// let discoMode = false; +// let fullMode = true; +// let hayMode = false; + +//Update dimensions on resize +// $(w).resize(function() { +// sw = document.body.clientWidth; + +// if (fullMode === true) { +// sizeiframe(sw, false); +// } +// }); + +//Size View Events + +// handle small button +// function goSmall() { +// killDisco(); +// killHay(); +// fullMode = false; +// sizeiframe( +// getRandom( +// minViewportWidth, +// window.config.ishViewportRange !== undefined +// ? parseInt(window.config.ishViewportRange.s[1], 10) +// : 500 +// ) +// ); +// } + +// $('#pl-size-s').on('click', function(e) { +// e.preventDefault(); +// goSmall(); +// }); + +Mousetrap.bind('ctrl+shift+s', function (e) { + goSmall(); + return false; +}); + +// // handle medium button +// function goMedium() { +// killDisco(); +// killHay(); +// fullMode = false; +// sizeiframe( +// getRandom( +// window.config.ishViewportRange !== undefined +// ? parseInt(window.config.ishViewportRange.m[0], 10) +// : 500, +// window.config.ishViewportRange !== undefined +// ? parseInt(window.config.ishViewportRange.m[1], 10) +// : 800 +// ) +// ); +// } + +// $('#pl-size-m').on('click', function(e) { +// e.preventDefault(); +// goMedium(); +// }); + +Mousetrap.bind('ctrl+shift+m', function (e) { + goMedium(); + return false; +}); + +// // handle large button +// function goLarge() { +// killDisco(); +// killHay(); +// fullMode = false; +// sizeiframe( +// getRandom( +// window.config.ishViewportRange !== undefined +// ? parseInt(window.config.ishViewportRange.l[0], 10) +// : 800, +// maxViewportWidth +// ) +// ); +// } + +// $('#pl-size-l').on('click', function(e) { +// e.preventDefault(); +// goLarge(); +// }); + +Mousetrap.bind('ctrl+shift+l', function (e) { + goLarge(); + return false; +}); + +// //Click Full Width Button +// $('#pl-size-full').on('click', function(e) { +// //Resets +// e.preventDefault(); +// killDisco(); +// killHay(); +// fullMode = true; +// sizeiframe(sw); +// }); + +//Click Random Size Button +$('#pl-size-random').on('click', function (e) { + e.preventDefault(); + killDisco(); + killHay(); + fullMode = false; + sizeiframe(getRandom(minViewportWidth, sw)); +}); + +//Click for Disco Mode, which resizes the viewport randomly +$('#pl-size-disco').on('click', function (e) { + e.preventDefault(); + killHay(); + fullMode = false; + + if (discoMode) { killDisco(); - killHay(); - fullMode = false; - sizeiframe( - getRandom( - minViewportWidth, - window.config.ishViewportRange !== undefined - ? parseInt(window.config.ishViewportRange.s[1], 10) - : 500 - ) - ); + } else { + startDisco(); } - - $('#pl-size-s').on('click', function(e) { - e.preventDefault(); - goSmall(); - }); - - Mousetrap.bind('ctrl+shift+s', function(e) { - goSmall(); - return false; - }); - - // handle medium button - function goMedium() { +}); + +// Disco Mode +function disco() { + sizeiframe(getRandom(minViewportWidth, sw)); +} + +function killDisco() { + discoMode = false; + clearInterval(discoID); + discoID = false; +} + +function startDisco() { + discoMode = true; + discoID = setInterval(disco, 800); +} + +Mousetrap.bind('ctrl+shift+d', function (e) { + if (!discoMode) { + startDisco(); + } else { killDisco(); - killHay(); - fullMode = false; - sizeiframe( - getRandom( - window.config.ishViewportRange !== undefined - ? parseInt(window.config.ishViewportRange.m[0], 10) - : 500, - window.config.ishViewportRange !== undefined - ? parseInt(window.config.ishViewportRange.m[1], 10) - : 800 - ) - ); } - - $('#pl-size-m').on('click', function(e) { - e.preventDefault(); - goMedium(); - }); - - Mousetrap.bind('ctrl+shift+m', function(e) { - goMedium(); - return false; - }); - - // handle large button - function goLarge() { - killDisco(); + return false; +}); + +//Stephen Hay Mode - "Start with the small screen first, then expand until it looks like shit. Time for a breakpoint!" +$('#pl-size-hay').on('click', function (e) { + e.preventDefault(); + killDisco(); + if (hayMode) { killHay(); - fullMode = false; - sizeiframe( - getRandom( - window.config.ishViewportRange !== undefined - ? parseInt(window.config.ishViewportRange.l[0], 10) - : 800, - maxViewportWidth - ) - ); - } - - $('#pl-size-l').on('click', function(e) { - e.preventDefault(); - goLarge(); - }); - - Mousetrap.bind('ctrl+shift+l', function(e) { - goLarge(); - return false; - }); - - //Click Full Width Button - $('#pl-size-full').on('click', function(e) { - //Resets - e.preventDefault(); - killDisco(); - killHay(); - fullMode = true; - sizeiframe(sw); - }); - - //Click Random Size Button - $('#pl-size-random').on('click', function(e) { - e.preventDefault(); - killDisco(); - killHay(); - fullMode = false; - sizeiframe(getRandom(minViewportWidth, sw)); - }); - - //Click for Disco Mode, which resizes the viewport randomly - $('#pl-size-disco').on('click', function(e) { - e.preventDefault(); - killHay(); - fullMode = false; - - if (discoMode) { - killDisco(); - } else { - startDisco(); - } - }); - - // Disco Mode - function disco() { - sizeiframe(getRandom(minViewportWidth, sw)); - } - - function killDisco() { - discoMode = false; - clearInterval(discoID); - discoID = false; - } - - function startDisco() { - discoMode = true; - discoID = setInterval(disco, 800); + } else { + startHay(); } - - Mousetrap.bind('ctrl+shift+d', function(e) { - if (!discoMode) { - startDisco(); - } else { - killDisco(); - } - return false; - }); - - //Stephen Hay Mode - "Start with the small screen first, then expand until it looks like shit. Time for a breakpoint!" - $('#pl-size-hay').on('click', function(e) { +}); + +//Stop Hay! Mode +function killHay() { + const currentWidth = $sgIframe.width(); + hayMode = false; + $sgIframe.removeClass('hay-mode'); + $('.pl-js-vp-iframe-container').removeClass('hay-mode'); + sizeiframe(Math.floor(currentWidth)); +} + +// start Hay! mode +// function startHay() { +// hayMode = true; +// $('.pl-js-vp-iframe-container') +// .removeClass('vp-animate') +// .width(minViewportWidth + viewportResizeHandleWidth); +// $sgIframe.removeClass('vp-animate').width(minViewportWidth); + +// const timeoutID = window.setTimeout(function() { +// $('.pl-js-vp-iframe-container') +// .addClass('hay-mode') +// .width(maxViewportWidth + viewportResizeHandleWidth); +// $sgIframe.addClass('hay-mode').width(maxViewportWidth); + +// setInterval(function() { +// const vpSize = $sgIframe.width(); +// updateSizeReading(vpSize); +// }, 100); +// }, 200); +// } + +// start hay from a keyboard shortcut +// Mousetrap.bind('ctrl+shift+h', function(e) { +// if (!hayMode) { +// startHay(); +// } else { +// killHay(); +// } +// }); + +//Pixel input +$sizePx.on('keydown', function (e) { + let val = Math.floor($(this).val()); + + if (e.keyCode === 38) { + //If the up arrow key is hit + val++; + sizeiframe(val, false); + } else if (e.keyCode === 40) { + //If the down arrow key is hit + val--; + sizeiframe(val, false); + } else if (e.keyCode === 13) { + //If the Enter key is hit e.preventDefault(); - killDisco(); - if (hayMode) { - killHay(); - } else { - startHay(); - } - }); - - //Stop Hay! Mode - function killHay() { - const currentWidth = $sgIframe.width(); - hayMode = false; - $sgIframe.removeClass('hay-mode'); - $('.pl-js-vp-iframe-container').removeClass('hay-mode'); - sizeiframe(Math.floor(currentWidth)); + sizeiframe(val); //Size Iframe to value of text box + $(this).blur(); } - - // start Hay! mode - function startHay() { - hayMode = true; - $('.pl-js-vp-iframe-container') - .removeClass('vp-animate') - .width(minViewportWidth + viewportResizeHandleWidth); - $sgIframe.removeClass('vp-animate').width(minViewportWidth); - - const timeoutID = window.setTimeout(function() { - $('.pl-js-vp-iframe-container') - .addClass('hay-mode') - .width(maxViewportWidth + viewportResizeHandleWidth); - $sgIframe.addClass('hay-mode').width(maxViewportWidth); - - setInterval(function() { - const vpSize = $sgIframe.width(); - updateSizeReading(vpSize); - }, 100); - }, 200); - } - - // start hay from a keyboard shortcut - Mousetrap.bind('ctrl+shift+h', function(e) { - if (!hayMode) { - startHay(); - } else { - killHay(); - } - }); - - //Pixel input - $sizePx.on('keydown', function(e) { - let val = Math.floor($(this).val()); - - if (e.keyCode === 38) { - //If the up arrow key is hit - val++; - sizeiframe(val, false); - } else if (e.keyCode === 40) { - //If the down arrow key is hit - val--; - sizeiframe(val, false); - } else if (e.keyCode === 13) { - //If the Enter key is hit - e.preventDefault(); - sizeiframe(val); //Size Iframe to value of text box - $(this).blur(); - } - }); - - $sizePx.on('keyup', function() { - const val = Math.floor($(this).val()); - updateSizeReading(val, 'px', 'updateEmInput'); - }); - - //Em input - $sizeEms.on('keydown', function(e) { - let val = parseFloat($(this).val()); - - if (e.keyCode === 38) { - //If the up arrow key is hit - val++; - sizeiframe(Math.floor(val * $bodySize), false); - } else if (e.keyCode === 40) { - //If the down arrow key is hit - val--; - sizeiframe(Math.floor(val * $bodySize), false); - } else if (e.keyCode === 13) { - //If the Enter key is hit - e.preventDefault(); - sizeiframe(Math.floor(val * $bodySize)); //Size Iframe to value of text box - } - }); - - $sizeEms.on('keyup', function() { - const val = parseFloat($(this).val()); - updateSizeReading(val, 'em', 'updatePxInput'); - }); - - // set 0 to 320px as a default - Mousetrap.bind('ctrl+shift+0', function(e) { +}); + +$sizePx.on('keyup', function () { + const val = Math.floor($(this).val()); + updateSizeReading(val, 'px', 'updateEmInput'); +}); + +//Em input +$sizeEms.on('keydown', function (e) { + let val = parseFloat($(this).val()); + + if (e.keyCode === 38) { + //If the up arrow key is hit + val++; + sizeiframe(Math.floor(val * $bodySize), false); + } else if (e.keyCode === 40) { + //If the down arrow key is hit + val--; + sizeiframe(Math.floor(val * $bodySize), false); + } else if (e.keyCode === 13) { + //If the Enter key is hit e.preventDefault(); - sizeiframe(320, true); - return false; - }); - - //Resize the viewport - //'size' is the target size of the viewport - //'animate' is a boolean for switching the CSS animation on or off. 'animate' is true by default, but can be set to false for things like nudging and dragging - function sizeiframe(size, animate) { - let theSize; - - if (size > maxViewportWidth) { - //If the entered size is larger than the max allowed viewport size, cap value at max vp size - theSize = maxViewportWidth; - } else if (size < minViewportWidth) { - //If the entered size is less than the minimum allowed viewport size, cap value at min vp size - theSize = minViewportWidth; - } else { - theSize = size; - } - - //Conditionally remove CSS animation class from viewport - if (animate === false) { - $('.pl-js-vp-iframe-container, .pl-js-iframe').removeClass('vp-animate'); //If aninate is set to false, remove animate class from viewport - } else { - $('.pl-js-vp-iframe-container, .pl-js-iframe').addClass('vp-animate'); - } - - $('.pl-js-vp-iframe-container').width(theSize + viewportResizeHandleWidth); //Resize viewport wrapper to desired size + size of drag resize handler - $sgIframe.width(theSize); //Resize viewport to desired size - - const targetOrigin = - window.location.protocol === 'file:' - ? '*' - : window.location.protocol + '//' + window.location.host; - const obj = JSON.stringify({ - event: 'patternLab.resize', - resize: 'true', - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, targetOrigin); - - updateSizeReading(theSize); //Update values in toolbar - saveSize(theSize); //Save current viewport to cookie - } - - $('.pl-js-vp-iframe-container').on( - 'transitionend webkitTransitionEnd', - function(e) { - const targetOrigin = - window.location.protocol === 'file:' - ? '*' - : window.location.protocol + '//' + window.location.host; - const obj = JSON.stringify({ - event: 'patternLab.resize', - resize: 'true', - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, targetOrigin); - } - ); - - function saveSize(size) { - if (!DataSaver.findValue('vpWidth')) { - DataSaver.addValue('vpWidth', size); - } else { - DataSaver.updateValue('vpWidth', size); - } - } - - //Update Pixel and Em inputs - //'size' is the input number - //'unit' is the type of unit: either px or em. Default is px. Accepted values are 'px' and 'em' - //'target' is what inputs to update. Defaults to both - function updateSizeReading(size, unit, target) { - let emSize, pxSize; - - if (unit === 'em') { - //If size value is in em units - emSize = size; - pxSize = Math.floor(size * $bodySize); - } else { - //If value is px or absent - pxSize = size; - emSize = size / $bodySize; - } - - if (target === 'updatePxInput') { - $sizePx.val(pxSize); - } else if (target === 'updateEmInput') { - $sizeEms.val(emSize.toFixed(2)); - } else { - $sizeEms.val(emSize.toFixed(2)); - $sizePx.val(pxSize); - } - } - - /* Returns a random number between min and max */ - function getRandom(min, max) { - return Math.floor(Math.random() * (max - min) + min); - } - - //Update The viewport size - function updateViewportWidth(size) { - $('.pl-js-iframe').width(size); - $('.pl-js-vp-iframe-container').width(size * 1 + 14); - - updateSizeReading(size); - } - - $('.pl-js-vp-iframe-container').on('touchstart', function(event) {}); - - // handles widening the "viewport" - // 1. on "mousedown" store the click location - // 2. make a hidden div visible so that it can track mouse movements and make sure the pointer doesn't get lost in the iframe - // 3. on "mousemove" calculate the math, save the results to a cookie, and update the viewport - $('.pl-js-resize-handle').mousedown(function(event) { - // capture default data - const origClientX = event.clientX; - const origViewportWidth = $sgIframe.width(); - - fullMode = false; - - // show the cover - $('.pl-js-viewport-cover').css('display', 'block'); - - // add the mouse move event and capture data. also update the viewport width - $('.pl-js-viewport-cover').mousemove(function(e) { - const viewportWidth = origViewportWidth + 2 * (e.clientX - origClientX); - - if (viewportWidth > minViewportWidth) { - if (!DataSaver.findValue('vpWidth')) { - DataSaver.addValue('vpWidth', viewportWidth); - } else { - DataSaver.updateValue('vpWidth', viewportWidth); - } - - sizeiframe(viewportWidth, false); - } - }); - - return false; - }); - - // on "mouseup" we unbind the "mousemove" event and hide the cover again - $('body').mouseup(function() { - $('.pl-js-viewport-cover').unbind('mousemove'); - $('.pl-js-viewport-cover').css('display', 'none'); - }); - - // capture the viewport width that was loaded and modify it so it fits with the pull bar - const origViewportWidth = $('.pl-js-iframe').width(); - $('.pl-js-vp-iframe-container').width(origViewportWidth); - - let testWidth = window.screen.width; - if (window.orientation !== undefined) { - testWidth = - window.orientation === 0 ? window.screen.width : window.screen.height; + sizeiframe(Math.floor(val * $bodySize)); //Size Iframe to value of text box } +}); + +$sizeEms.on('keyup', function () { + const val = parseFloat($(this).val()); + updateSizeReading(val, 'em', 'updatePxInput'); +}); + +// set 0 to 320px as a default +Mousetrap.bind('ctrl+shift+0', function (e) { + e.preventDefault(); + sizeiframe(320, true); + return false; +}); + +// //Resize the viewport +// //'size' is the target size of the viewport +// //'animate' is a boolean for switching the CSS animation on or off. 'animate' is true by default, but can be set to false for things like nudging and dragging +// function sizeiframe(size, animate) { +// let theSize; + +// console.log('sizeiframe'); + +// // @todo: refactor to better handle the iframe async rendering +// if (document.querySelector('.pl-js-iframe')){ +// if (size > maxViewportWidth) { +// //If the entered size is larger than the max allowed viewport size, cap value at max vp size +// theSize = maxViewportWidth; +// } else if (size < minViewportWidth) { +// //If the entered size is less than the minimum allowed viewport size, cap value at min vp size +// theSize = minViewportWidth; +// } else { +// theSize = size; +// } + +// //Conditionally remove CSS animation class from viewport +// if (animate === false) { +// $('.pl-js-vp-iframe-container, .pl-js-iframe').removeClass('vp-animate'); //If aninate is set to false, remove animate class from viewport +// } else { +// $('.pl-js-vp-iframe-container, .pl-js-iframe').addClass('vp-animate'); +// } + +// $('.pl-js-vp-iframe-container').width(theSize + viewportResizeHandleWidth); //Resize viewport wrapper to desired size + size of drag resize handler +// $sgIframe.width(theSize); //Resize viewport to desired size +// const state = store.getState(); +// const isViewallPage = state.app.isViewallPage; + +// const targetOrigin = +// window.location.protocol === 'file:' +// ? '*' +// : window.location.protocol + '//' + window.location.host; +// const obj = JSON.stringify({ +// event: 'patternLab.resize', +// resize: 'true', +// }); +// document +// .querySelector('.pl-js-iframe') +// .contentWindow.postMessage(obj, targetOrigin); + +// updateSizeReading(theSize); //Update values in toolbar +// saveSize(theSize); //Save current viewport to cookie +// } +// } + +// $('.pl-js-vp-iframe-container').on( +// 'transitionend webkitTransitionEnd', +// function(e) { +// const targetOrigin = +// window.location.protocol === 'file:' +// ? '*' +// : window.location.protocol + '//' + window.location.host; +// const obj = JSON.stringify({ +// event: 'patternLab.resize', +// resize: 'true', +// }); +// document +// .querySelector('.pl-js-iframe') +// .contentWindow.postMessage(obj, targetOrigin); +// } +// ); + +// function saveSize(size) { +// if (!DataSaver.findValue('vpWidth')) { +// DataSaver.addValue('vpWidth', size); +// } else { +// DataSaver.updateValue('vpWidth', size); +// } +// } + +// /* Returns a random number between min and max */ +// function getRandom(min, max) { +// return Math.floor(Math.random() * (max - min) + min); +// } + +//Update The viewport size +// function updateViewportWidth(size) { + +// // @todo: update to conditionally adjust behavior of viewall page width +// const state = store.getState(); +// const isViewallPage = state.app.isViewallPage; + +// if(!isViewallPage){ +// $('.pl-js-iframe').width(size); +// $('.pl-js-vp-iframe-container').width(size * 1 + 14); +// } + +// updateSizeReading(size); +// } + +// $('.pl-js-vp-iframe-container').on('touchstart', function(event) {}); + +// handles widening the "viewport" +// 1. on "mousedown" store the click location +// 2. make a hidden div visible so that it can track mouse movements and make sure the pointer doesn't get lost in the iframe +// 3. on "mousemove" calculate the math, save the results to a cookie, and update the viewport +// $('.pl-js-resize-handle').mousedown(function(event) { +// // capture default data +// const origClientX = event.clientX; +// const origViewportWidth = $sgIframe.width(); + +// fullMode = false; + +// // show the cover +// $('.pl-js-viewport-cover').css('display', 'block'); + +// // add the mouse move event and capture data. also update the viewport width +// $('.pl-js-viewport-cover').mousemove(function(e) { +// const viewportWidth = origViewportWidth + 2 * (e.clientX - origClientX); + +// if (viewportWidth > minViewportWidth) { +// if (!DataSaver.findValue('vpWidth')) { +// DataSaver.addValue('vpWidth', viewportWidth); +// } else { +// DataSaver.updateValue('vpWidth', viewportWidth); +// } + +// sizeiframe(viewportWidth, false); +// } +// }); + +// return false; +// }); + +// on "mouseup" we unbind the "mousemove" event and hide the cover again +// $('body').mouseup(function() { +// $('.pl-js-viewport-cover').unbind('mousemove'); +// $('.pl-js-viewport-cover').css('display', 'none'); +// }); + +// capture the viewport width that was loaded and modify it so it fits with the pull bar +// const origViewportWidth = $('.pl-js-iframe').width(); +// $('.pl-js-vp-iframe-container').width(origViewportWidth); + +// let testWidth = window.screen.width; +// if (window.orientation !== undefined) { +// testWidth = +// window.orientation === 0 ? window.screen.width : window.screen.height; +// } +// if ( +// $(window).width() === testWidth && +// 'ontouchstart' in document.documentElement && +// $(window).width() <= 1024 +// ) { +// $('.pl-js-resize-container').width(0); +// } else { +// $('.pl-js-iframe').width(origViewportWidth - 14); +// } +// updateSizeReading($('.pl-js-iframe').width()); + +// get the request vars +const oGetVars = urlHandler.getRequestVars(); + +// pre-load the viewport width +let vpWidth = 0; +const trackViewportWidth = true; // can toggle this feature on & off + +// if (oGetVars.h !== undefined || oGetVars.hay !== undefined) { +// startHay(); +// } else if (oGetVars.d !== undefined || oGetVars.disco !== undefined) { +// startDisco(); +// } else if (oGetVars.w !== undefined || oGetVars.width !== undefined) { +// vpWidth = oGetVars.w !== undefined ? oGetVars.w : oGetVars.width; +// vpWidth = +// vpWidth.indexOf('em') !== -1 +// ? Math.floor(Math.floor(vpWidth.replace('em', '')) * $bodySize) +// : Math.floor(vpWidth.replace('px', '')); +// DataSaver.updateValue('vpWidth', vpWidth); +// updateViewportWidth(vpWidth); +// } else if (trackViewportWidth && (vpWidth = DataSaver.findValue('vpWidth'))) { +// updateViewportWidth(vpWidth); +// } + +// watch the iframe source so that it can be sent back to everyone else. +// based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage +function receiveIframeMessage(event) { + // does the origin sending the message match the current host? if not dev/null the request if ( - $(window).width() === testWidth && - 'ontouchstart' in document.documentElement && - $(window).width() <= 1024 + (window.location.protocol !== 'file:' && + event.origin !== + window.location.protocol + '//' + window.location.host) || + event.data === '' // message received, but no data included; prevents JSON.parse error below ) { - $('.pl-js-resize-container').width(0); - } else { - $('.pl-js-iframe').width(origViewportWidth - 14); - } - updateSizeReading($('.pl-js-iframe').width()); - - // get the request vars - const oGetVars = urlHandler.getRequestVars(); - - // pre-load the viewport width - let vpWidth = 0; - const trackViewportWidth = true; // can toggle this feature on & off - - if (oGetVars.h !== undefined || oGetVars.hay !== undefined) { - startHay(); - } else if (oGetVars.d !== undefined || oGetVars.disco !== undefined) { - startDisco(); - } else if (oGetVars.w !== undefined || oGetVars.width !== undefined) { - vpWidth = oGetVars.w !== undefined ? oGetVars.w : oGetVars.width; - vpWidth = - vpWidth.indexOf('em') !== -1 - ? Math.floor(Math.floor(vpWidth.replace('em', '')) * $bodySize) - : Math.floor(vpWidth.replace('px', '')); - DataSaver.updateValue('vpWidth', vpWidth); - updateViewportWidth(vpWidth); - } else if (trackViewportWidth && (vpWidth = DataSaver.findValue('vpWidth'))) { - updateViewportWidth(vpWidth); - } - - // set up the defaults for the - const baseIframePath = - window.location.protocol + - '//' + - window.location.host + - window.location.pathname.replace('index.html', ''); - let patternName = - window.config.defaultPattern !== undefined && - typeof window.config.defaultPattern === 'string' && - window.config.defaultPattern.trim().length > 0 - ? window.config.defaultPattern - : 'all'; - let iFramePath = - baseIframePath + 'styleguide/html/styleguide.html?' + Date.now(); - if (oGetVars.p !== undefined || oGetVars.pattern !== undefined) { - patternName = oGetVars.p !== undefined ? oGetVars.p : oGetVars.pattern; - } - - if (patternName !== 'all') { - const patternPath = urlHandler.getFileName(patternName); - iFramePath = - patternPath !== '' - ? baseIframePath + patternPath + '?' + Date.now() - : iFramePath; - document.getElementById('title').innerHTML = 'Pattern Lab - ' + patternName; - window.history.replaceState( - { - pattern: patternName, - }, - null, - null - ); + return; } - // Open in new window link - if (document.querySelector('.pl-js-open-new-window')) { - // Set value of href to the path to the pattern - document - .querySelector('.pl-js-open-new-window') - .setAttribute('href', urlHandler.getFileName(patternName)); + let data = {}; + try { + data = typeof event.data !== 'string' ? event.data : JSON.parse(event.data); + } catch (e) { + // @todo: how do we want to handle exceptions here? } - urlHandler.skipBack = true; - document - .querySelector('.pl-js-iframe') - .contentWindow.location.replace(iFramePath); - - // Close all dropdowns and navigation - function closePanels() { - $('.pl-js-nav-container, .pl-js-acc-handle, .pl-js-acc-panel').removeClass( - 'pl-is-active' - ); - } - - // update the iframe with the source from clicked element in pull down menu. also close the menu - // having it outside fixes an auto-close bug i ran into - $('a[data-patternpartial]').on('click', function(e) { - e.preventDefault(); - // update the iframe via the history api handler - const obj = JSON.stringify({ - event: 'patternLab.updatePath', - path: urlHandler.getFileName($(this).attr('data-patternpartial')), - }); - document - .querySelector('.pl-js-iframe') - .contentWindow.postMessage(obj, urlHandler.targetOrigin); - closePanels(); - }); - - // handle when someone clicks on the grey area of the viewport so it auto-closes the nav - $('.pl-js-viewport').click(function() { - closePanels(); - }); - - // Listen for resize changes - if (window.orientation !== undefined) { - let origOrientation = window.orientation; - window.addEventListener( - 'orientationchange', - function() { - if (window.orientation !== origOrientation) { - $('.pl-js-vp-iframe-container').width($(window).width()); - $('.pl-js-iframe').width($(window).width()); - updateSizeReading($(window).width()); - origOrientation = window.orientation; - } - }, - false - ); - } - - // watch the iframe source so that it can be sent back to everyone else. - // based on the great MDN docs at https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage - function receiveIframeMessage(event) { - // does the origin sending the message match the current host? if not dev/null the request - if ( - (window.location.protocol !== 'file:' && - event.origin !== - window.location.protocol + '//' + window.location.host) || - event.data === '' // message received, but no data included; prevents JSON.parse error below - ) { - return; - } - - let data = {}; - try { - data = - typeof event.data !== 'string' ? event.data : JSON.parse(event.data); - } catch (e) { - // @todo: how do we want to handle exceptions here? - } - - if (data.event !== undefined) { - if (data.event === 'patternLab.pageLoad') { - if (!urlHandler.skipBack) { - if ( - window.history.state === undefined || - window.history.state === null || - window.history.state.pattern !== data.patternpartial - ) { - urlHandler.pushPattern(data.patternpartial, data.path); - } - - /* - if (wsnConnected) { - var iFramePath = urlHandler.getFileName(data.patternpartial); - wsn.send( '{"url": "'+iFramePath+'", "patternpartial": "'+event.data.patternpartial+'" }' ); - } - */ + if (data.event !== undefined) { + if (data.event === 'patternLab.pageLoad') { + // if (!urlHandler.skipBack) { + // if ( + // window.history.state === undefined || + // window.history.state === null || + // window.history.state.pattern !== data.patternpartial + // ) { + // urlHandler.pushPattern(data.patternpartial, data.path); + // } + // /* + // if (wsnConnected) { + // var iFramePath = urlHandler.getFileName(data.patternpartial); + // wsn.send( '{"url": "'+iFramePath+'", "patternpartial": "'+event.data.patternpartial+'" }' ); + // } + // */ + // } + // // reset the defaults + // urlHandler.skipBack = false; + } else if (data.event === 'patternLab.keyPress') { + if (data.keyPress === 'ctrl+shift+s') { + goSmall(); + } else if (data.keyPress === 'ctrl+shift+m') { + goMedium(); + } else if (data.keyPress === 'ctrl+shift+l') { + goLarge(); + } else if (data.keyPress === 'ctrl+shift+d') { + if (!discoMode) { + startDisco(); + } else { + killDisco(); } - - // reset the defaults - urlHandler.skipBack = false; - } else if (data.event === 'patternLab.keyPress') { - if (data.keyPress === 'ctrl+shift+s') { - goSmall(); - } else if (data.keyPress === 'ctrl+shift+m') { - goMedium(); - } else if (data.keyPress === 'ctrl+shift+l') { - goLarge(); - } else if (data.keyPress === 'ctrl+shift+d') { - if (!discoMode) { - startDisco(); - } else { - killDisco(); - } - } else if (data.keyPress === 'ctrl+shift+h') { - if (!hayMode) { - startHay(); - } else { - killHay(); - } - } else if (data.keyPress === 'ctrl+shift+0') { - sizeiframe(320, true); + } else if (data.keyPress === 'ctrl+shift+h') { + if (!hayMode) { + startHay(); + } else { + killHay(); } - - // @todo: chat with Brian on if this code is still used and necessary; both the `mqs` and `found` variables are both currently undefined. - // else if (found === data.keyPress.match(/ctrl\+shift\+([1-9])/)) { - // let val = mqs[found[1] - 1]; - // const type = val.indexOf('px') !== -1 ? 'px' : 'em'; - // val = val.replace(type, ''); - // const width = type === 'px' ? val * 1 : val * $bodySize; - // sizeiframe(width, true); - // } - // return false; + } else if (data.keyPress === 'ctrl+shift+0') { + sizeiframe(320, true); } + + // @todo: chat with Brian on if this code is still used and necessary; both the `mqs` and `found` variables are both currently undefined. + // else if (found === data.keyPress.match(/ctrl\+shift\+([1-9])/)) { + // let val = mqs[found[1] - 1]; + // const type = val.indexOf('px') !== -1 ? 'px' : 'em'; + // val = val.replace(type, ''); + // const width = type === 'px' ? val * 1 : val * $bodySize; + // sizeiframe(width, true); + // } + // return false; } } - window.addEventListener('message', receiveIframeMessage, false); -})(this); +} +window.addEventListener('message', receiveIframeMessage, false); +// })(this); diff --git a/packages/uikit-workshop/src/scripts/components/with-lit-html.js b/packages/uikit-workshop/src/scripts/components/with-lit-html.js new file mode 100644 index 000000000..055f78960 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/components/with-lit-html.js @@ -0,0 +1,8 @@ +import { render } from 'lit-html'; + +export default (Base = HTMLElement) => + class extends Base { + renderer(root, call) { + render(call(), root); + } + }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.js b/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.js new file mode 100644 index 000000000..80e539fe1 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.js @@ -0,0 +1,107 @@ +import { LitElement, html } from 'lit-element'; +import { Slotify } from '../slotify'; +import styles from './pl-button.scss?external'; +import { ifDefined } from 'lit-html/directives/if-defined'; + +// This decorator defines the element. +class Button extends Slotify(LitElement) { + static get properties() { + return { + href: { + attribute: true, + type: String, + }, + target: { + attribute: true, + type: String, + }, + size: { + attribute: true, + type: String, + }, + iconOnly: { + attribute: 'icon-only', + type: Boolean, + reflect: true, + }, + title: { + attribute: true, + type: String, + }, + }; + } + + createRenderRoot() { + return this; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + innerTemplate() { + return html` + ${this.slotify('before') + ? html` + ${this.slotify('before')} + ` + : ''} + ${this.slotify('default') + ? html` + ${this.slotify('default')} + ` + : ''} + ${this.slotify('after') + ? html` + ${this.slotify('after')} + ` + : ''} + `; + } + + // Render element DOM by returning a `lit-html` template. + render() { + const size = this.size || 'medium'; + // const iconOnly = this.iconOnly !== false|| false; + + return html` + ${this.href + ? html` + + ${this.innerTemplate()} + + ` + : html` + + `} + `; + } +} + +customElements.define('pl-button', Button); + +export { Button }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.scss new file mode 100644 index 000000000..bec09cc4d --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-button/pl-button.scss @@ -0,0 +1,42 @@ +@import '../../../sass/scss/core.scss'; + +:host { + width: 100%; +} + +pl-button { + width: 100%; +} + +.pl-c-button { + @include buttonStyles; +} + +.pl-c-button__text { + text-align: left; +} + +.pl-c-button--medium { + padding: 0.65rem 1rem; + + &.pl-c-button--icon-only { + padding: 0.65rem; + } +} + +.pl-c-button--small { + padding: 0.5rem 1rem; + + &.pl-c-button--icon-only { + padding: 0.5rem; + } +} + +// Make sure the text and icon align to the opposite ends +* + .pl-c-button__icon { + margin-right: 0.5rem; +} + +.pl-c-button__icon + * { + margin-right: 0.5rem; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.js b/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.js new file mode 100644 index 000000000..d7b736330 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.js @@ -0,0 +1,28 @@ +import { BaseLitComponent } from '../../components/base-component'; +import { html, customElement } from 'lit-element'; +import styles from './pl-controls.scss?external'; + +@customElement('pl-controls') +class Controls extends BaseLitComponent { + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + render() { + return html` +
        + + + +
        + `; + } +} + +export { Controls }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.scss new file mode 100644 index 000000000..2f648f880 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-controls/pl-controls.scss @@ -0,0 +1,62 @@ +/*------------------------------------*\ + #CONTROLS +\*------------------------------------*/ + +@import '../../../sass/scss/core.scss'; + +pl-controls { + margin-left: auto; /* 2 */ + display: flex; + flex-wrap: nowrap; + align-self: center; + + .pl-c-body--theme-sidebar & { + display: block; + + @media all and (min-width: $pl-bp-med) { + width: 100%; + position: relative; + padding-top: 0.5rem; + // box-shadow: 0 -2px 5px rgba($pl-color-black, 0.1); + + &::before { + position: absolute; + left: 0; + right: 0; + top: 0; + border-top: 1px solid; + border-top-color: $pl-color-gray-20; + border-top-color: var(--theme-border, $pl-color-gray-20); + height: 1px; + content: ''; + width: auto; + } + } + } +} + +/** + * 1) Controls contains viewport resizer and tools dropdown + * 2) Right-align inside of header + */ +.pl-c-controls { + margin-left: auto; /* 2 */ + display: flex; + flex-wrap: nowrap; + + // IE 11 layout bug + @media all and (min-width: $pl-bp-med) { + .pl-c-body--theme-sidebar & { + display: block; + } + } +} + +/** +* Control list +*/ +.pl-c-controls__list { + @include listReset(); + display: flex; + flex-wrap: nowrap; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.js b/packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.js new file mode 100644 index 000000000..6fa309662 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.js @@ -0,0 +1,210 @@ +import { styleMap } from 'lit-html/directives/style-map'; +import { classMap } from 'lit-html/directives/class-map'; +import { LitElement, html, customElement } from 'lit-element'; +import { store } from '../../store.js'; // redux store +import { + updateDrawerState, + updateDrawerHeight, + updateDrawerAnimationState, +} from '../../actions/app.js'; // redux actions needed by this element. +import styles from './pl-drawer.scss?external'; + +@customElement('pl-drawer') +class Drawer extends LitElement { + constructor() { + super(); + this.onMouseDown = this.onMouseDown.bind(this); // fix bindings so "this" works properly + this.onMouseUp = this.onMouseUp.bind(this); // fix bindings so "this" works properly + this.onMouseMove = this.onMouseMove.bind(this); // fix bindings so "this" works properly + } + + connectedCallback() { + styles.use(); + if (super.connectedCallback) { + super.connectedCallback(); + } + this.__storeUnsubscribe = store.subscribe(() => + this._stateChanged(store.getState()) + ); + this._stateChanged(store.getState()); + } + + disconnectedCallback() { + styles.unuse(); + this.__storeUnsubscribe && this.__storeUnsubscribe(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + static get properties() { + return { + drawerOpened: { + attribute: true, + type: Boolean, + }, + drawerHeight: { + attribute: true, + type: Number, + }, + isViewallPage: { + attribute: true, + type: Boolean, + }, + isMouseDown: { + attribute: true, + type: Boolean, + }, + }; + } + + createRenderRoot() { + return this; + } + + onMouseDown() { + this.isMouseDown = true; + store.dispatch(updateDrawerAnimationState(true)); + + document.addEventListener('mousemove', this.onMouseMove); + document.addEventListener('mouseup', this.onMouseUp); + } + + onMouseMove(event) { + // 1/2 the height of the UI being dragged. @todo: make sure this 20px is calculated + const clientHeight = event.targetTouches + ? event.targetTouches[0].clientY + : event.clientY; + const panelHeight = window.innerHeight - clientHeight + 28; + + this.drawerHeight = panelHeight; + } + + onMouseUp() { + this.isMouseDown = false; + document.removeEventListener('mousemove', this.onMouseMove); + document.removeEventListener('mouseup', this.onMouseUp); + + store.dispatch(updateDrawerHeight(this.drawerHeight)); + store.dispatch(updateDrawerAnimationState(false)); + } + + render() { + const classes = { + 'pl-c-drawer': true, + 'pl-js-drawer': true, + 'pl-is-active': this.drawerOpened && !this.isViewallPage, + }; + + const renderedHeight = + this.drawerOpened && !this.isViewallPage + ? this.drawerHeight > 20 + ? this.drawerHeight + : 300 + : 0; + + const drawerStyles = { + height: `${renderedHeight}px`, + transitionDuration: this.isMouseDown ? '0ms' : '300ms', + }; + + return html` +
        +
        +
        +
        + + Drag to resize Pattern Lab Drawer + + +
        +
        +
        +
        + + + + + +
        +
        +
        +
        +
        +
        +
        Loading Code Panel
        +
        + +
        +
        +
        +
        +
        +
        +
        +
        + `; + } + + _stateChanged(state) { + if (this.themeMode !== state.app.themeMode) { + this.themeMode = state.app.themeMode || 'dark'; + } + if (this.drawerOpened !== state.app.drawerOpened) { + this.drawerOpened = state.app.drawerOpened; + } + if (this.drawerHeight !== state.app.drawerHeight) { + this.drawerHeight = state.app.drawerHeight; + } + if (this.isDragging !== state.app.isDragging) { + this.isDragging = state.app.isDragging; + } + if (this.isViewallPage !== state.app.isViewallPage) { + this.isViewallPage = state.app.isViewallPage; + } + } +} + +export { Drawer }; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_modal.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.scss old mode 100644 new mode 100755 similarity index 51% rename from packages/uikit-workshop/src/sass/scss/04-components/_modal.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.scss index 384e44f86..7cc307b1f --- a/packages/uikit-workshop/src/sass/scss/04-components/_modal.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-drawer/pl-drawer.scss @@ -1,46 +1,46 @@ /*------------------------------------*\ - #MODAL + #drawer \*------------------------------------*/ -$pl-resizer-height: 14px; +@import '../../../sass/scss/core.scss'; -pl-modal { +$pl-drawer-resizer-height: 20px; + +pl-drawer { display: flex; flex-direction: column; position: relative; position: sticky; + top: auto; + bottom: 0; + left: 0; + right: 0; z-index: 20; - max-height: 100vh; - box-shadow: 0 0 2px 0 $pl-color-gray-70; overflow: visible; } - /** - * 1) The modal slides up from the bottom of the viewport when + * 1) The drawer slides up from the bottom of the viewport when * "show pattern info" is selected on the pattern detail screen. */ -.pl-c-modal { +.pl-c-drawer { display: flex; flex-direction: column; font-family: $pl-font; background-color: $pl-color-gray-87; + background-color: var(--theme-secondary, $pl-color-gray-87); color: $pl-color-gray-20; - position: sticky; - top: auto; - bottom: 0; - left: 0; - right: 0; - z-index: 5; width: 100%; - height: 0; - transition: transform 0.3s ease, height 0.3s ease; - transform: translate3d(0, 100%, 0); + height: 100%; + transform: translate3d(0, 0, 0); pointer-events: none; - will-change: height, transform; overflow: hidden; max-width: 100vw; - box-shadow: 0 -1px 2px rgba($pl-color-gray-70, 0.1); + + @supports (padding: max(0px)) { + padding-left: calc(env(safe-area-inset-left) / 2); + padding-right: calc(env(safe-area-inset-right) / 2); + } .pl-c-body--theme-sidebar & { @media all and (min-width: $pl-bp-med) { @@ -48,64 +48,77 @@ pl-modal { } } + .pl-c-body--theme-light & { + // Modal / Drawer inside a light theme + background-color: $pl-color-white; + color: $pl-color-gray-70; + } + /** - * Active modal + * Active drawer */ &.pl-is-active { - transform: translate3d(0, 0, 0); - height: 40vh; // default height unless manually resized - transition: transform 0.3s ease; pointer-events: auto; } } -.pl-c-modal__wrapper { +.pl-c-drawer__wrapper { transform: translate3d(0, 0, 0); + will-change: height; + overflow: hidden; } -.pl-c-modal__wrapper > * { +.pl-c-drawer__wrapper > * { height: 100%; } -.pl-c-modal__content { +.pl-c-drawer__content { flex-grow: 1; display: flex; width: 100%; overflow: hidden; // needed for IE 11 so scrollbars show up + max-height: calc( + 100% - 32px - 1.5rem + ); // workaround to fix drawer content collapsing. @todo: remove once larger tabs refactor PR'd } -.pl-c-modal__toolbar { +.pl-c-drawer__toolbar { display: flex; flex-direction: column; flex-shrink: 0; // so that the resizer height doesn't change unexpectedly } -.pl-c-modal__content-wrapper { +.pl-c-drawer__content-wrapper { display: flex; flex-direction: column; flex-grow: 1; overflow: hidden; // needed for IE 11 so scrollbars show up + + @supports (padding: env(safe-area-inset-top)) { + padding-right: calc(env(safe-area-inset-right) - 0.9rem); + } } -.pl-c-modal__toolbar-controls { +.pl-c-drawer__toolbar-controls { display: flex; flex-direction: row; align-self: flex-end; position: relative; z-index: 10; - flex-shrink: 0; + flex-shrink: 0; // fix for IE 11 squishing UI controls } /** - * Modal close button - * 1) Closes the modal popup + * drawer close button + * 1) Closes the drawer popup */ -.pl-c-modal__close-btn { +.pl-c-drawer__close-btn { @include linkStyle; margin: 0; + padding: 0.2rem; -webkit-appearance: none; flex-shrink: 0; // needed for IE 11 - + @media all and (max-width: $pl-bp-med - 1) { border-radius: 20rem; padding-top: 0.5rem; @@ -128,88 +141,77 @@ pl-modal { } } - -.pl-c-modal__cover { +.pl-c-drawer__cover { width: 100%; height: 100%; - display: none; - position: absolute; + top: 0; + left: 0; + position: fixed; z-index: 20; cursor: move; } -.pl-c-modal__resizer { +.pl-c-drawer__resizer { display: flex; - position: absolute; + position: relative; top: 0; left: 0; right: 0; align-items: center; justify-content: center; - left: 0; - height: $pl-resizer-height; + height: $pl-drawer-resizer-height; width: 100%; background-color: inherit; z-index: 2; cursor: ns-resize; + border-bottom: 1.1px solid $pl-color-gray-20; // sub-pixel bug in Chrome. border disappears sometimes when set to 1px + border-bottom-color: $pl-color-gray-20; + border-bottom-color: var(--theme-border, $pl-color-gray-20); + padding-top: 5px; + padding-bottom: 5px; - &:after { + &::after { content: ''; - height: 3px; - width: 50px; - border-top: 1px solid currentColor; - border-bottom: 1px solid currentColor; - transition: opacity $pl-animate-normal ease-out; - opacity: 0.5; - background-color: currentColor; - border-radius: 3px; + height: 100%; + width: 100%; + left: 0; + opacity: 0; + top: 0; + position: absolute; + pointer-events: none; display: block; + background-color: currentColor; + transition: 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } - &:hover:after { - opacity: 0.8; + &:hover::after { + opacity: 0.1; } - &:focus:after, - &:active:after { - opacity: 0.95; + &:focus::after, + &:active::after { + opacity: 0.2; } } +.pl-c-drawer__resizer-icon { + width: 10px; + height: 100%; + fill: currentColor; + z-index: 100; + transform: scale(3, 1) rotate(90deg); +} + /** * Close button icon * 1) Displayed as an e */ -.pl-c-modal__close-btn-icon { - width: 12px; - height: 12px; +.pl-c-drawer__close-btn-icon { + width: 20px; + height: 20px; color: currentColor; fill: currentColor; transition: fill $pl-animate-quick ease-out; flex-shrink: 0; // needed for IE 11 align-self: center; // valign in IE 11 } - -.pl-c-code-copy-btn { - display: inline-block; - position: absolute; - top: 0.5rem; - right: 0.5rem; - padding: 0.2rem 0.4rem; - background-color: $pl-color-gray-07; - color: $pl-color-gray-87; - border: 1px solid $pl-color-gray-13; - border-radius: $pl-border-radius-med; - font-family: $pl-font; - font-size: $pl-font-size-norm; - text-transform: lowercase; - line-height: 1; - cursor: pointer; - z-index: 2; - transition: background-color $pl-animate-quick ease-out; - - &:hover, - &:focus { - background-color: $pl-color-gray-20; - } -} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.js b/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.js new file mode 100644 index 000000000..91dc15a64 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.js @@ -0,0 +1,172 @@ +/* eslint-disable no-unused-vars, no-param-reassign */ +import { store } from '../../store.js'; // connect to redux +import { ifDefined } from 'lit-html/directives/if-defined'; +import { html } from 'lit-html'; +import { BaseLitComponent } from '../../components/base-component'; +import { iframeMsgDataExtraction } from '../../utils'; +import { customElement } from 'lit-element'; +import Mousetrap from 'mousetrap'; +import styles from './pl-header.scss?external'; + +@customElement('pl-header') +class Header extends BaseLitComponent { + constructor() { + super(); + this._wasInitiallyRendered = false; + this.receiveIframeMessage = this.receiveIframeMessage.bind(this); + this.handleExternalClicks = this.handleExternalClicks.bind(this); + this.toggleNav = this.toggleNav.bind(this); + } + + static get properties() { + return { + themeMode: String, + isActive: Boolean, + currentPattern: String, + }; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + this.currentPattern = state.app.currentPattern || ''; + this.themeMode = state.app.themeMode || 'dark'; + + window.addEventListener('message', this.receiveIframeMessage, false); + document.addEventListener('click', this.handleExternalClicks); + + Mousetrap(this).bind('esc', () => { + if (window.innerWidth <= 670) { + this.isActive = false; + } + }); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + window.removeEventListener('message', this.receiveIframeMessage); + document.removeEventListener('click', this.handleExternalClicks); + } + + _stateChanged(state) { + if (this.themeMode !== state.app.themeMode) { + this.themeMode = state.app.themeMode || 'dark'; + } + + if (this.currentPattern !== state.app.currentPattern) { + if (this.isActive === true) { + this.isActive = false; + } + this.currentPattern = state.app.currentPattern; + } + } + + handleExternalClicks(e) { + if (window.innerWidth <= 670) { + if ( + e.target !== this.navToggle && + !e.target.closest('.pl-js-nav-container') && + !e.target.closest('pl-toggle-layout') && + this.isActive === true + ) { + this.isActive = false; + } + } + } + + firstUpdated() { + this.navToggle = this.renderRoot.querySelector('.pl-js-nav-trigger'); + this.navTarget = this.querySelector('.pl-js-nav-target'); + + if (!window.__PRERENDER_INJECTED) { + this._wasInitiallyRendered = true; + } + } + + toggleNav() { + this.isActive = !this.isActive; + } + + render() { + return html` + + `; + } + + /** + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(event) { + const self = this; + + const data = iframeMsgDataExtraction(event); + + if (data.event !== undefined && data.event === 'patternLab.pageClick') { + try { + if ( + window.innerWidth <= 670 || + (window.innerWidth >= 670 && self.layoutMode !== 'vertical') + ) { + this.isActive = false; + } + } catch (error) { + console.log(error); + } + } + } +} + +export { Header }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.scss new file mode 100644 index 000000000..9732e0c23 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-header/pl-header.scss @@ -0,0 +1,95 @@ +/*------------------------------------*\ + #HEADER +\*------------------------------------*/ + +@import '../../../sass/scss/core.scss'; + +pl-header { + position: relative; + position: sticky; + top: 0; + left: 0; + z-index: 100; + display: flex; /* 2 */ + width: 100%; + background-color: $pl-color-black; + background-color: var(--theme-secondary, $pl-color-black); + max-height: 100vh; + + color: $pl-color-gray-20; + color: var(--theme-text, $pl-color-gray-20); + border-right: 1px solid; + border-right-color: $pl-color-gray-20; + border-right-color: var(--theme-border, $pl-color-gray-20); + padding-left: calc(env(safe-area-inset-left) / 2); + padding-right: calc(env(safe-area-inset-right) / 2); + + .pl-c-body--theme-light & { + color: $pl-color-black; + background-color: $pl-color-white; + } + + .pl-c-body--theme-sidebar & { + padding-right: 0; + } + + @media all and (min-width: $pl-bp-med) { + .pl-c-body--theme-sidebar & { + position: fixed; + position: sticky; + overflow: auto; + /** + * Header + * 1) Set width to sidebar width defined above + * 2) Make header 100% of the viewport height + * 3) Stack header content stack on top of each other + * 4) void bottom border for light theme + */ + width: $pl-sidebar-width; /* 1 */ + border-bottom: 0; /* 4 */ + } + } +} + +/** +* 1) Pattern Lab's header is fixed across the top of the viewport and +* contains the primary pattern navigation, viewport resizing items, +* and tools. +* 2) Display nav and controls horizontally +*/ +.pl-c-header { + display: flex; /* 2 */ + flex-direction: row; + width: 100%; + font-family: $pl-font; + font-size: $pl-font-size-sm; + min-height: 30px; // magic number -- needed for initial skeleton screen styles used in the critical CSS + background-color: inherit; + + @media all and (min-width: $pl-bp-med) { + .pl-c-body--theme-sidebar & { + flex-direction: column; /* 3 */ + justify-content: space-between; + } + } +} + +/** + * Nav toggle button + * 1) Styles for the general nav toggle button, which + * only appears on small screens + */ +.pl-c-header__nav-toggle { + @include linkStyle(); + padding: 11px 12px; + border: 0; + + @media all and (min-width: $pl-bp-med) { + display: none; + } + + &:focus { + outline: 1px dotted; + outline-offset: -1px; + } +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.js b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.js new file mode 100644 index 000000000..0d8a2d8d2 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.js @@ -0,0 +1,65 @@ +import { html, LitElement, customElement } from 'lit-element'; +import styles from './pl-icon.scss?external'; +import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +const icons = {}; + +// automatically pull in every SVG icon file in from the icons folder +const svgIcons = require.context('../../../icons', true, /\.svg$/); +svgIcons.keys().forEach((iconName) => { + const name = iconName.replace('./', ''); + const icon = import(`../../../icons/${name}`); + + icon.then((Icon) => { + icons[Icon.default.id] = Icon.default; + }); +}); + +// This decorator defines the element. +@customElement('pl-icon') +class Icon extends LitElement { + static get properties() { + return { + name: String, + size: String, + }; + } + + createRenderRoot() { + return this; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + // Render element DOM by returning a `lit-html` template. + render() { + const svgMarkup = ` + + + + + `; + + return html` ${unsafeHTML(svgMarkup)} `; + } +} + +export { Icon }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.scss new file mode 100644 index 000000000..392a1ba29 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/pl-icon.scss @@ -0,0 +1,15 @@ +@import '../../../sass/scss/core.scss'; + +pl-icon { + display: block; + width: 1.2em; + height: 1.2em; + pointer-events: none; // so click events aren't disrupted when clicking into an SVG; +} + +// @todo: build out additional icon sizes +.c-icon { + display: block; + width: 1.2em; + height: 1.2em; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-icon/unsafe-svg.js b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/unsafe-svg.js new file mode 100644 index 000000000..f6d374dae --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-icon/unsafe-svg.js @@ -0,0 +1,64 @@ +/** + * @license + * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at + * https://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at + * https://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at + * https://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at + * https://polymer.github.io/PATENTS.txt + */ + +import { reparentNodes } from 'lit-html/lib/dom.js'; +// import { isPrimitive } from 'lit-html/lib/parts.js'; +import { directive } from 'lit-html/lit-html.js'; +import importNode from '@ungap/import-node'; +// document.importNode = importNode; + +// interface PreviousValue { +// readonly value: unknown; +// readonly fragment: DocumentFragment; +// } + +// For each part, remember the value that was last rendered to the part by the +// unsafeSVG directive, and the DocumentFragment that was last set as a value. +// The DocumentFragment is used as a unique key to check if the last value +// rendered to the part was with unsafeSVG. If not, we'll always re-render the +// value passed to unsafeSVG. + +/** + * Renders the result as SVG, rather than text. + * + * Note, this is unsafe to use with any user-provided input that hasn't been + * sanitized or escaped, as it may lead to cross-site-scripting + * vulnerabilities. + */ +export const unsafeSVG = directive((value) => (part) => { + // if (!(part instanceof NodePart)) { + // throw new Error('unsafeSVG can only be used in text bindings'); + // } + + // const previousValue = previousValues.get(part); + + // if ( + // previousValue !== undefined && + // isPrimitive(value) && + // value === previousValue.value && + // part.value === previousValue.fragment + // ) { + // return; + // } + + const template = document.createElement('template'); + template.innerHTML = `${value}`; + const content = template.content; + const svgElement = content.firstElementChild; + content.removeChild(svgElement); + reparentNodes(content, svgElement.firstChild); + const fragment = importNode(content, true); + part.setValue(fragment); + // previousValues.set(part, { value, fragment }); +}); diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.js b/packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.js new file mode 100644 index 000000000..1f6a7f73d --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.js @@ -0,0 +1,84 @@ +/* eslint-disable no-unused-vars, no-param-reassign */ +import { define, props } from 'skatejs'; +const classNames = require('classnames'); +import { html } from 'lit-html'; + +import { store } from '../../store.js'; // connect to redux +import { BaseLitComponent } from '../../components/base-component.js'; +import styles from './pl-layout.scss?external'; + +class Layout extends BaseLitComponent { + constructor() { + super(); + this.targetOrigin = + window.location.protocol === 'file:' + ? '*' + : window.location.protocol + '//' + window.location.host; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + this.layoutMode = state.app.layoutMode; + this.themeMode = state.app.themeMode; + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + firstUpdated() { + this.iframeElement = this.renderRoot.querySelector('.pl-js-iframe'); + } + + _stateChanged(state) { + let hasChanged = false; + if (this.layoutMode !== state.app.layoutMode) { + hasChanged = true; + this.layoutMode = state.app.layoutMode || 'vertical'; + } + + if (this.themeMode !== state.app.themeMode) { + hasChanged = true; + this.themeMode = state.app.themeMode; + } + + if (hasChanged === true) { + hasChanged = false; + const layoutModeClass = + this.layoutMode === 'vertical' ? 'sidebar' : 'horizontal'; + + const classes = classNames(`pl-c-body--theme-${layoutModeClass}`, { + [`pl-c-body--theme-${this.themeMode}`]: this.themeMode !== undefined, + }); + + this.className = classes; + } + + this.iframeElement = document.querySelector('.pl-js-iframe'); + + if (this.iframeElement) { + const obj = JSON.stringify({ + event: 'patternLab.stateChange', + state, + }); + this.iframeElement.contentWindow.postMessage(obj, this.targetOrigin); + } + } + + render() { + return html` + +
        + + +
        + `; + } +} + +customElements.define('pl-layout', Layout); + +export { Layout }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.scss similarity index 79% rename from packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.scss index 00dde1208..1d4cf9253 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-layout/pl-layout.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-layout/pl-layout.scss @@ -4,15 +4,20 @@ pl-layout { display: flex; flex-direction: column; width: 100%; - min-height: 100vh; + min-height: 100%; max-width: 100vw; - background-color: $pl-color-gray-13; - + background-color: $pl-color-white; + overflow: initial; + // Prevent extra scrollbars in just IE 11 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { overflow: hidden; } + .pl-c-layout { + flex-grow: 1; + } + &.pl-c-body--theme-sidebar { @media all and (min-width: $pl-bp-med) { flex-direction: row; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.js b/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.js new file mode 100644 index 000000000..75eba1f21 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.js @@ -0,0 +1,64 @@ +import { store } from '../../store.js'; // connect to redux +import { ifDefined } from 'lit-html/directives/if-defined'; +import { html } from 'lit-html'; +import { customElement } from 'lit-element'; +import { BaseLitComponent } from '../../components/base-component'; +import styles from './pl-logo.scss?external'; + +@customElement('pl-logo') +class Logo extends BaseLitComponent { + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + this.theme = this.theme || state.app.themeMode || 'dark'; + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + static get properties() { + return { + width: String, + height: String, + theme: String, + url: String, + text: String, + altText: { + type: String, + attribute: 'alt-text', + }, + srcLight: { + type: String, + attribute: 'src-light', + }, + srcDark: { + type: String, + attribute: 'src-dark', + }, + }; + } + + render() { + const imageSrc = this.theme === 'dark' ? this.srcDark : this.srcLight; + + return html` + + `; + } +} + +export { Logo }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.scss new file mode 100644 index 000000000..0156a983c --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-logo/pl-logo.scss @@ -0,0 +1,63 @@ +/*------------------------------------*\ + #LOGO +\*------------------------------------*/ + +@import '../../../sass/scss/core.scss'; + +pl-logo { + align-self: center; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + flex-shrink: 0; + position: relative; + z-index: 100; + padding: 0; + min-height: 44px; + min-width: 44px; +} + +.pl-c-logo { + width: auto; + flex-grow: 1; + padding: 0.5rem 0.25rem; + display: flex; + align-items: center; + justify-content: center; + color: inherit; + text-decoration: none; + + @media screen and (min-width: 400px) { + padding: 0.5rem 12px; + } + + outline: 0; + text-transform: lowercase; + font-size: 1.2rem; + font-weight: bold; + line-height: 1; + margin: 0; + transition: color 0.2s ease; + + &:focus { + outline: 1px dotted; + outline-offset: -1px; + } +} + +.pl-c-logo__img { + display: block; + height: 100%; // fix to address scaling issue in ie 11 on windows 7 + max-width: 100%; + max-height: 23px; + + &:not(:last-child) { + margin-right: 0.25rem; + } +} + +.pl-c-logo__text { + display: flex; + white-space: nowrap; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.js b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.js new file mode 100644 index 000000000..1264e8919 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.js @@ -0,0 +1,82 @@ +import { LitElement, html, customElement } from 'lit-element'; +import { store } from '../../store.js'; // connect to the Redux store. +import { updateDrawerState } from '../../actions/app.js'; // redux actions +import styles from './pl-toggle-info.scss?external'; + +@customElement('pl-toggle-info') +class InfoToggle extends LitElement { + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + isDrawerOpen: { + attribute: 'is-drawer-open', + type: Boolean, + }, + isViewallPage: { + attribute: 'is-viewall-page', + type: Boolean, + }, + }; + } + + connectedCallback() { + if (super.connectedCallback) { + super.connectedCallback(); + } + styles.use(); + + const state = store.getState(); + this.isDrawerOpen = state.app.drawerOpened; + this.isViewallPage = state.app.isViewallPage; + + this.__storeUnsubscribe = store.subscribe(() => + this._stateChanged(store.getState()) + ); + this._stateChanged(store.getState()); + } + + disconnectedCallback() { + this.__storeUnsubscribe && this.__storeUnsubscribe(); + styles.unuse(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + _stateChanged(state) { + this.isDrawerOpen = state.app.drawerOpened; + this.isViewallPage = state.app.isViewallPage; + } + + handleClick() { + this.isDrawerOpen = !this.isDrawerOpen; + store.dispatch(updateDrawerState(this.isDrawerOpen)); + } + + render() { + return html` + + ${this.isDrawerOpen ? 'Collapse' : 'Expand'} + ${this.isViewallPage ? 'All Panels' : 'Panel'} + + + `; + } +} + +export { InfoToggle }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.scss new file mode 100644 index 000000000..8896eb2aa --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-info/pl-toggle-info.scss @@ -0,0 +1,16 @@ +@import '../../../sass/scss/core.scss'; + +pl-toggle-info { + display: flex; + align-self: center; + justify-content: center; + align-items: center; + z-index: 10; + width: 100%; + cursor: pointer; +} + +.pl-c-toggle-info, +.pl-c-toggle-info__action { + width: 100%; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.js b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.js new file mode 100644 index 000000000..ff6b00cfc --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.js @@ -0,0 +1,98 @@ +import { LitElement, html, customElement } from 'lit-element'; +import { store } from '../../store.js'; // connect to the Redux store. +import { updateLayoutMode } from '../../actions/app.js'; // redux actions +import styles from './pl-toggle-layout.scss?external'; + +@customElement('pl-toggle-layout') +class LayoutToggle extends LitElement { + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + } + + createRenderRoot() { + return this; + } + + connectedCallback() { + if (super.connectedCallback) { + super.connectedCallback(); + } + styles.use(); + + const state = store.getState(); + this.layoutMode = state.app.layoutMode || 'vertical'; + + this.__storeUnsubscribe = store.subscribe(() => + this._stateChanged(store.getState()) + ); + this._stateChanged(store.getState()); + + this.size = this.size || 'medium'; + } + + disconnectedCallback() { + this.__storeUnsubscribe && this.__storeUnsubscribe(); + styles.unuse(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + static get properties() { + return { + layoutMode: { + attribute: true, + type: String, + }, + text: { + attribute: true, + type: String, + }, + size: { + attribute: true, + type: String, + }, + iconOnly: { + attribute: 'icon-only', + type: Boolean, + reflect: true, + }, + }; + } + + _stateChanged(state) { + if (this.layoutMode !== state.app.layoutMode) { + this.layoutMode = state.app.layoutMode; + } + } + + handleClick() { + const getLayoutMode = + this.layoutMode !== 'vertical' ? 'vertical' : 'horizontal'; + + this.layoutMode = getLayoutMode; + store.dispatch(updateLayoutMode(this.layoutMode)); + } + + render() { + return html` + + ${this.text} + + + `; + } +} + +export { LayoutToggle }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.scss similarity index 74% rename from packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.scss index f9c6a9cab..4412646f8 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-toggle-layout/pl-toggle-layout.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-layout/pl-toggle-layout.scss @@ -1,20 +1,16 @@ @import '../../../sass/scss/core.scss'; pl-toggle-layout { - display: none; + display: flex; align-self: center; justify-content: center; align-items: center; z-index: 10; width: 100%; cursor: pointer; - - @media all and (min-width: $pl-bp-med) { - display: flex; - } } .pl-c-toggle-layout, .pl-c-toggle-layout__action { width: 100%; -} \ No newline at end of file +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.js b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.js new file mode 100644 index 000000000..d98c8f654 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.js @@ -0,0 +1,89 @@ +/* eslint-disable no-unused-vars, no-param-reassign */ +import { LitElement, html, customElement } from 'lit-element'; +import { store } from '../../store.js'; // connect to the Redux store. +import { updateThemeMode } from '../../actions/app.js'; // redux actions needed +import styles from './pl-toggle-theme.scss?external'; + +@customElement('pl-toggle-theme') +class ThemeToggle extends LitElement { + constructor() { + super(); + this.targetOrigin = + window.location.protocol === 'file:' + ? '*' + : window.location.protocol + '//' + window.location.host; + } + + static get properties() { + return { + themeMode: { + attribute: true, + type: String, + }, + }; + } + + createRenderRoot() { + return this; + } + + connectedCallback() { + if (super.connectedCallback) { + super.connectedCallback(); + } + styles.use(); + + const state = store.getState(); + this.themeMode = state.app.themeMode || 'dark'; + + this.__storeUnsubscribe = store.subscribe(() => + this._stateChanged(store.getState()) + ); + this._stateChanged(store.getState()); + + store.dispatch(updateThemeMode(this.themeMode)); + } + + disconnectedCallback() { + this.__storeUnsubscribe && this.__storeUnsubscribe(); + styles.unuse(); + + if (super.disconnectedCallback) { + super.disconnectedCallback(); + } + } + + _stateChanged(state) { + this.themeMode = state.app.themeMode; + this.iframeElement = document.querySelector('.pl-js-iframe'); + + if (this.iframeElement) { + const obj = JSON.stringify({ + event: 'patternLab.stateChange', + state, + }); + this.iframeElement.contentWindow.postMessage(obj, this.targetOrigin); + } + } + + render() { + const toggleThemeMode = this.themeMode !== 'dark' ? 'dark' : 'light'; + return html` + + Switch Theme + + + + `; + } +} + +export { ThemeToggle }; diff --git a/packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.scss similarity index 66% rename from packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.scss index 26aa1ba53..074dbaac8 100644 --- a/packages/uikit-workshop/src/scripts/components/pl-toggle-theme/pl-toggle-theme.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-toggle-theme/pl-toggle-theme.scss @@ -1,5 +1,4 @@ @import '../../../sass/scss/core.scss'; -@import '{ .pl-c-tools__action, .pl-c-tools__action-text, .pl-c-tools__action-icon } from ../../../sass/scss/04-components/_tools.scss'; pl-toggle-theme { display: flex; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.js b/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.js new file mode 100644 index 000000000..fed628846 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.js @@ -0,0 +1,187 @@ +/* eslint-disable no-unused-vars */ +import { define, props } from 'skatejs'; +import Mousetrap from 'mousetrap'; +import { h } from 'preact'; +import { urlHandler, patternName, iframeMsgDataExtraction } from '../../utils'; +import { store } from '../../store'; // redux store +import styles from './pl-tools-menu.scss?external'; + +const listeningForBodyClicks = false; + +import { html } from 'lit-html'; +import { BaseLitComponent } from '../../components/base-component'; +import { customElement } from 'lit-element'; + +@customElement('pl-tools-menu') +class ToolsMenu extends BaseLitComponent { + static get properties() { + return { + isOpen: Boolean, + layoutMode: String, + currentUrl: String, + }; + } + + _stateChanged(state) { + if (this.currentUrl !== state.app.currentUrl) { + this.currentUrl = state.app.currentUrl; + } + + if (this.layoutMode !== state.app.layoutMode) { + this.layoutMode = state.app.layoutMode || 'vertical'; + } + } + + constructor() { + super(); + this.handleClick = this.handleClick.bind(this); + this.receiveIframeMessage = this.receiveIframeMessage.bind(this); + this.handleExternalClicks = this.handleExternalClicks.bind(this); + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + const { ishControlsHide } = window.ishControls; + this.currentUrl = state.app.currentUrl || ''; + this.ishControlsHide = ishControlsHide; + + window.addEventListener('message', this.receiveIframeMessage, false); + document.addEventListener('click', this.handleExternalClicks); + + Mousetrap(this).bind('esc', () => { + this.close(); + }); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + document.removeEventListener('click', this.handleExternalClicks); + window.removeEventListener('message', this.receiveIframeMessage); + } + + handleExternalClicks(e) { + if (window.innerWidth >= 670 && this.layoutMode === 'vertical') { + return; + } + + if (!this.contains(e.target) && this.isOpen === true) { + this.isOpen = false; + } + } + + close() { + this.isOpen = false; + } + + toggle() { + if (this.isOpen) { + this.close(); + } else { + this.open(); + } + } + + open() { + this.isOpen = true; + } + + handleClick(e) { + if (window.innerWidth >= 670 && this.layoutMode === 'vertical') { + return; + } + + e.preventDefault(); + e.stopPropagation(); + + this.toggle(); + } + + /** + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(event) { + const self = this; + + const data = iframeMsgDataExtraction(event); + + if (data.event !== undefined && data.event === 'patternLab.pageClick') { + try { + self.isOpen = false; + } catch (error) { + console.log(error); + } + } + } + + render() { + if (window.innerWidth >= 670 && this.layoutMode === 'vertical') { + this.isOpen = true; + } + + return html` +
        + + + +
          +
        • + +
        • + +
        • + +
        • +
        • + +
        • + + ${!this.ishControlsHide['views-new'] + ? html` +
        • + + Open In New Tab + + +
        • + ` + : ''} + ${!this.ishControlsHide['tools-docs'] + ? html` +
        • + + Pattern Lab Docs + + +
        • + ` + : ''} +
        +
        + `; + } +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.scss new file mode 100644 index 000000000..00a453234 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-tools-menu/pl-tools-menu.scss @@ -0,0 +1,129 @@ +/*------------------------------------*\ + #TOOLS +\*------------------------------------*/ + +@import '../../../sass/scss/core.scss'; + +// vertical align in container +pl-tools-menu { + display: flex; + flex-direction: column; + justify-content: center; +} + +/** + * The tools dropdown contains more utilities such as show/hide + * pattern info and pattern search, and also links to open in a + * new window and view the documentation + */ +.pl-c-tools { + position: relative; + display: flex; +} + +/** + * Tools dropdown list + */ +.pl-c-tools__list { + @include listReset(); + transform: translateY(-10px); + position: absolute; + right: 5px; + z-index: 10; // make sure context dropdown z-index is higher than nav dropdown z-index + width: 12rem; + border-radius: 6px; + top: calc(100% - 2px); + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + background-color: $pl-color-gray-87; + background-color: var(--theme-primary, $pl-color-gray-87); + transform: translateY(-4rem); + opacity: 0; + max-height: 0; + visibility: hidden; + pointer-events: none; + + &.is-open { + opacity: 1; + max-height: 9999px; + visibility: visible; + pointer-events: auto; + transform: translateY(0); + } + + .pl-c-body--theme-light & { + background-color: $pl-color-white; + background-color: var(--theme-primary, $pl-color-white); + } + + .pl-c-body--theme-sidebar & { + @media all and (min-width: $pl-bp-med) { + box-shadow: none; + top: 0; + transform: none; + border-radius: 0; + background-color: transparent; + right: 0; + opacity: 1; + visibility: visible; + pointer-events: auto; + } + } + + &.is-active { + overflow: visible; + } + + &::before { + content: ''; + height: 14px; + width: 14px; + background-color: $pl-color-gray-87; + background-color: var(--theme-primary, $pl-color-gray-87); + position: absolute; + right: 0px; + top: -10px; + transform: translateY(50%) translateX(-50%) rotate(45deg); + transition: opacity 0.1s ease-out; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); + + .pl-c-body--theme-sidebar & { + @media all and (min-width: $pl-bp-med) { + display: none; + } + } + } + + &.is-active::before { + opacity: 1; + visibility: visible; + } +} + +.pl-c-tools__item { + position: relative; + overflow: hidden; + background-color: inherit; + + // crop list item when hover + &:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + + .pl-c-body--theme-sidebar & { + @media all and (min-width: $pl-bp-med) { + border-radius: 0; + } + } + } + + &:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + + .pl-c-body--theme-sidebar & { + @media all and (min-width: $pl-bp-med) { + border-radius: 0; + } + } + } +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.js b/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.js new file mode 100644 index 000000000..f24f73043 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.js @@ -0,0 +1,59 @@ +import { LitElement, html } from 'lit-element'; +import styles from './pl-tooltip.scss?external'; +import { Slotify } from '../slotify'; + +class Tooltip extends Slotify(LitElement) { + static get properties() { + return { + message: { type: String }, + position: { type: String }, + child: {}, + }; + } + + constructor() { + super(); + + // property defaults + this.position = 'top'; + } + + createRenderRoot() { + return this; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + render() { + return html` +
        + ${this.slotify('default') ? this.slotify('default') : ''} + ${this.message} +
        + `; + } + + hideTooltip() { + this.opened = false; + } + + showTooltip() { + this.opened = true; + } + + toggleTooltip() { + this.opened = !this.opened; + } +} + +customElements.define('pl-tooltip', Tooltip); + +export { Tooltip }; diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.scss new file mode 100644 index 000000000..f54842395 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-tooltip/pl-tooltip.scss @@ -0,0 +1,62 @@ +@import '../../../sass/scss/core.scss'; + +.tooltip-container { + color: $pl-color-gray-87; +} + +pl-tooltip { + > *:not(.pl-tooltip) { + display: none; + } +} + +.pl-tooltip { + position: relative; + display: inline-block; + + &__text { + visibility: hidden; + width: 120px; + max-width: 200px; + background-color: black; + color: #fff; + text-align: center; + padding: 5px 0; + border-radius: 6px; + + position: absolute; + z-index: 50; + } + + &--right &__text, + &--left &__text { + top: 50%; + transform: translateY(-50%); + } + + &--right &__text { + left: 115%; + } + + &--left &__text { + right: 115%; + } + + &--top &__text, + &--bottom &__text { + left: 50%; + transform: translateX(-50%); + } + + &--top &__text { + bottom: 115%; + } + + &--bottom &__text { + top: 115%; + } + + &:hover &__text { + visibility: visible; + } +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.iframe-helper.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.iframe-helper.js new file mode 100644 index 000000000..c1fe8b7a0 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.iframe-helper.js @@ -0,0 +1,24 @@ +import { targetOrigin } from '../../utils'; + +function sendPatternLabKeyEvent(e, name) { + try { + window.parent.postMessage( + JSON.stringify({ + event: `patternLab.${name}`, + key: e.key, + code: e.code, + }), + targetOrigin + ); + } catch (error) { + // @todo: how do we want to handle exceptions here? + } +} + +document.addEventListener('keydown', (e) => { + sendPatternLabKeyEvent(e, 'iframeKeyDownEvent'); +}); + +document.addEventListener('keyup', (e) => { + sendPatternLabKeyEvent(e, 'iframeKeyUpEvent'); +}); diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js new file mode 100644 index 000000000..b7ec9f3e3 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.js @@ -0,0 +1,436 @@ +/* eslint-disable no-unused-vars */ +import { h } from 'preact'; +import { define, props } from 'skatejs'; +import { BaseComponent } from '../../components/base-component.js'; +import { store } from '../../store.js'; // connect to redux + +import { + minViewportWidth, + maxViewportWidth, + getRandom, + iframeMsgDataExtraction, +} from '../../utils'; + +import styles from './pl-viewport-size-list.scss?external'; + +@define +class ViewportSizes extends BaseComponent { + static is = 'pl-viewport-sizes'; + + sizes = Object.freeze({ + ZERO: 'zero', + SMALL: 'small', + MEDIUM: 'medium', + LARGE: 'large', + FULL: 'full', + RANDOM: 'random', + DISCO: 'disco', + HAY: 'hay', + }); + + discomode = false; + doscoId = null; + hayMode = false; + hayId = null; + layoutMode = null; + tooltipPos = null; + + controlIsPressed = false; + altIsPressed = false; + + _stateChanged(state) { + this.triggerUpdate(); + + if (this.layoutMode !== state.app.layoutMode) { + this.layoutMode = state.app.layoutMode || 'vertical'; + this.tooltipPos = this.layoutMode === 'horizontal' ? 'bottom' : 'top'; + } + } + + constructor() { + super(); + this.resizeViewport = this.resizeViewport.bind(this); + this.useShadow = false; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + const { ishControlsHide } = window?.ishControls; + this.ishControlsHide = ishControlsHide; + + // Remove EventListener or they will be added multiple times when reloading in serve mode + document.removeEventListener('keydown', this.handleKeyDownEvent); + document.removeEventListener('keyup', this.handleKeyCombination); + document.addEventListener('keydown', this.handleKeyDownEvent.bind(this)); + document.addEventListener('keyup', this.handleKeyCombination.bind(this)); + this.receiveIframeMessage = this.receiveIframeMessage.bind(this); + + window.removeEventListener('message', this.receiveIframeMessage); + window.addEventListener('message', this.receiveIframeMessage, false); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + shouldUpdate(prevProps, prevState) { + return true; + } + + resizeViewport(size) { + if (this.iframe) { + this.killDisco(); + this.killHay(); + + switch (size) { + case this.sizes.ZERO: + this.iframe.fullMode = false; + this.iframe.sizeiframe(0, true); + case this.sizes.SMALL: + this.iframe.fullMode = false; + this.iframe.sizeiframe( + getRandom( + minViewportWidth, + window.config.ishViewportRange !== undefined + ? parseInt(window.config.ishViewportRange.s[1], 10) + : 500 + ), + true + ); + break; + case this.sizes.MEDIUM: + this.iframe.fullMode = false; + this.iframe.sizeiframe( + getRandom( + window.config.ishViewportRange !== undefined + ? parseInt(window.config.ishViewportRange.m[0], 10) + : 500, + window.config.ishViewportRange !== undefined + ? parseInt(window.config.ishViewportRange.m[1], 10) + : 800 + ), + true + ); + break; + case this.sizes.LARGE: + this.iframe.fullMode = false; + this.iframe.sizeiframe( + getRandom( + window.config.ishViewportRange !== undefined + ? parseInt(window.config.ishViewportRange.l[0], 10) + : 800, + window.config.ishViewportRange !== undefined + ? parseInt(window.config.ishViewportRange.l[1], 10) + : 1000 + ), + true + ); + break; + case this.sizes.FULL: + this.iframe.fullMode = true; + this.iframe.sizeiframe(maxViewportWidth, true); + break; + case this.sizes.RANDOM: + this.fullMode = false; + this.iframe.sizeiframe(this.getRangeRandomNumber(), true); + break; + case this.sizes.DISCO: + this.fullMode = false; + this.startDisco(); + break; + case this.sizes.HAY: + this.fullMode = false; + this.iframe.sizeiframe(minViewportWidth, true); + this.startHay(); + break; + } + } + } + + /** + * Get a random number between minViewportWidth and maxViewportWidth + */ + getRangeRandomNumber() { + return getRandom( + minViewportWidth, + // Do not evaluate a number higher than the clientWidth of the Iframe + // to prevent having max size multiple times + maxViewportWidth > this.iframe.clientWidth + ? this.iframe.clientWidth + : maxViewportWidth + ); + } + + /** + * Start the disco mode, which means in a specific interval resize + * the iframe random between minViewportWidth and maxViewportWidth + */ + startDisco() { + this.discoMode = true; + this.discoId = setInterval(this.disco.bind(this), 1000); + } + + /** + * Stop the disco mode + */ + killDisco() { + this.discoMode = false; + clearInterval(this.discoId); + this.discoID = null; + } + + /** + * Action to resize the Iframe in disco mode + */ + disco() { + this.iframe.sizeiframe(this.getRangeRandomNumber(), true); + } + + /** + * Start the Hay! mode, which means the iframe is growing slowly + * from minViewportWidth to maxViewportWidth + */ + startHay() { + this.hayMode = true; + this.hayId = setInterval(this.hay.bind(this), 100); + } + + /** + * Stop the Hay! Mode + */ + killHay() { + this.hayMode = false; + clearInterval(this.hayId); + this.hayId = null; + } + + /** + * Action to resize the Iframe in Hay! mode + */ + hay() { + this.iframe.sizeiframe(store.getState().app.viewportPx + 1, true); + } + + /** + * Litte workaround for Firefox Bug. + * + * On QWERTZ keyboards the e.altKey and e.ctrlKey will + * not be set if you click on a key that has a specific + * secondary or third char at ALT + ... + * + * @param {KeyboardEvent} e the keyevent + */ + handleKeyDownEvent(e) { + if (e.key === 'Control') { + this.controlIsPressed = true; + } + if (e.key === 'Alt') { + this.altIsPressed = true; + } + } + + /** + * https://patternlab.io/docs/advanced-keyboard-shortcuts.html + * + * Why use these specific key combinations? + * Works on QUERTZ, QUERTY and AZERTY keyboard and they are no + * reserved browser functionality key combinations. + * + * QUERTY https://en.wikipedia.org/wiki/QWERTY + * QUERTZ https://en.wikipedia.org/wiki/QWERTZ + * AZERTY https://en.wikipedia.org/wiki/AZERTY + * + * Chromium + * https://support.google.com/chrome/answer/157179?hl=en + * + * Firefox + * https://support.mozilla.org/en-US/kb/keyboard-shortcuts-perform-firefox-tasks-quickly + * + * @param {KeyboardEvent} e the keyevent + */ + handleKeyCombination(e) { + const ctrlKey = this.controlIsPressed; + const altKey = this.altIsPressed; + + if (ctrlKey && altKey && (e.code === 'Digit0' || e.code === 'Numpad0')) { + this.resizeViewport(this.sizes.ZERO); + } else if (ctrlKey && altKey && e.code === 'KeyS') { + this.resizeViewport(this.sizes.SMALL); + } else if (ctrlKey && altKey && e.code === 'KeyM') { + this.resizeViewport(this.sizes.MEDIUM); + } else if (ctrlKey && altKey && e.code === 'KeyL') { + this.resizeViewport(this.sizes.LARGE); + } else if (ctrlKey && altKey && e.code === 'KeyF') { + this.resizeViewport(this.sizes.FULL); + } else if (ctrlKey && altKey && e.code === 'KeyR') { + this.resizeViewport(this.sizes.RANDOM); + } else if (ctrlKey && altKey && e.code === 'KeyD') { + this.resizeViewport(this.sizes.DISCO); + } else if (ctrlKey && altKey && e.code === 'KeyH') { + this.resizeViewport(this.sizes.HAY); + } + + if (e.key === 'Control') { + this.controlIsPressed = false; + } + if (e.key === 'Alt') { + this.altIsPressed = false; + } + } + + /** + * Interpret and handle the received message input + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); + + if (data.event && data.event === 'patternLab.iframeKeyDownEvent') { + this.handleKeyDownEvent(data); + } else if (data.event && data.event === 'patternLab.iframeKeyUpEvent') { + this.handleKeyCombination(data); + } + } + + rendered() { + this.iframe = document.querySelector('pl-iframe'); + this.iframeElem = document.querySelector('pl-iframe iframe'); + } + + render() { + return ( +
          + {!this.ishControlsHide?.s && ( +
        • + +
        • + )} + {!this.ishControlsHide?.m && ( +
        • + +
        • + )} + {!this.ishControlsHide?.l && ( +
        • + +
        • + )} + {!this.ishControlsHide?.full && ( +
        • + +
        • + )} + {!this.ishControlsHide?.random && ( +
        • + +
        • + )} + {!this.ishControlsHide?.disco && ( +
        • + +
        • + )} + {!this.ishControlsHide?.hay && ( +
        • + +
        • + )} +
        + ); + } +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.scss new file mode 100644 index 000000000..3048f46ed --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size-list/pl-viewport-size-list.scss @@ -0,0 +1,56 @@ +@import '../../../sass/scss/core.scss'; + +pl-viewport-sizes { + display: flex; + justify-content: center; +} + +/** + * Size options + * 1) This holds the S, M, L, Rand, Disco links + * 2) Depending on the config, these number of options may be + * larger or smaller. + */ +.pl-c-size-list { + display: none; + list-style: none; + margin: 0; + padding: 0; + padding: 0 0.25rem; + + @media all and (min-width: $pl-bp-med) { + align-items: center; + -webkit-overflow-scrolling: touch; + } + + @media all and (min-width: $pl-bp-med) { + display: block; + display: flex; + } +} + +/** + * Size actions + * 1) These are the buttons that control the viewport resizing + */ +.pl-c-size-list__action { + @include buttonStyles; + display: inline-block; // workaround to fix valign issues in IE 11 + min-height: 35px; + min-width: 0; + padding-left: 0.35rem; + padding-right: 0.35rem; + + pl-icon { + pointer-events: none; + } +} + +// Force list items to center align if not overflow scrolling +.pl-c-size-list__item:first-child { + margin-left: auto; +} + +.pl-c-size-list__item:last-child { + margin-right: auto; +} diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.js new file mode 100644 index 000000000..96e189bee --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.js @@ -0,0 +1,204 @@ +/* eslint-disable no-unused-vars */ +import { h } from 'preact'; + +import { BaseLitComponent } from '../../components/base-component'; +import { html, customElement } from 'lit-element'; +import styles from './pl-viewport-size.scss?external'; +import { store } from '../../store.js'; // connect to redux + +const nRegex = /\D+/g; +const fpRegex = /[^0-9\.]+/g; + +function round(value, decimals) { + return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals); +} + +@customElement('pl-viewport-size') +class ViewportSize extends BaseLitComponent { + static get properties() { + return { + px: String, + em: String, + }; + } + + constructor() { + super(); + this.state = { inputPixelValue: 0, inputEmValue: 0 }; + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + styles.use(); + const state = store.getState(); + this.setPxEm(state); + this.iframe = document.querySelector('pl-iframe'); + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + styles.unuse(); + } + + _stateChanged(state) { + this.setPxEm(state); + } + + setPxEm(state) { + if (state.app.viewportPx !== this.px) { + this.px = round(state.app.viewportPx, 0); + this.setState({ inputPixelValue: this.px }, () => {}); + } + + if (round(state.app.viewportEm, 1) !== this.em) { + this.em = round(state.app.viewportEm, 1); + this.setState({ inputEmValue: this.em }, () => {}); + } + } + + firstUpdated() { + this.viewport = document.querySelector('pl-viewport'); + } + + updated() { + if (this.viewport && this.viewport.bodySize) { + this.em = Math.floor(this.px * this.bodySize); + } + } + + handlePixelUpdateUp(e) { + this.setState( + { inputPixelValue: e.target.value.replace(nRegex, '') }, + () => {} + ); + } + + handlePixelUpdatePress(e) { + if (e.key.match(nRegex)) { + // Prevent inserting letters or symbols + e.preventDefault(); + } + } + + handlePixelUpdateDown(e) { + if (e.key === 'Enter') { + event.preventDefault(); + this.iframe.sizeiframe(this.state.inputPixelValue, true); + } else if (e.key === 'ArrowUp') { + this.setState( + { + inputPixelValue: + Number(e.target.value.replace(nRegex, '')) + (e.shiftKey ? 10 : 1), + }, + () => {} + ); + this.iframe.sizeiframe(this.state.inputPixelValue, true); + } else if (e.key === 'ArrowDown') { + this.setState( + { + inputPixelValue: + Number(e.target.value.replace(nRegex, '')) - (e.shiftKey ? 10 : 1), + }, + () => {} + ); + this.iframe.sizeiframe(this.state.inputPixelValue, true); + } + } + + handlePixelBlur(e) { + this.setState({ inputPixelValue: this.px }, () => {}); + e.target.value = this.state.inputPixelValue; + } + + handleEmUpdateUp(e) { + this.setState( + { inputEmValue: e.target.value.replace(fpRegex, '') }, + () => {} + ); + } + + handleEmUpdatePress(e) { + if (e.key.match(fpRegex)) { + // Prevent inserting letters or symbols + e.preventDefault(); + } + } + + handleEmUpdateDown(e) { + if (e.key === 'Enter') { + event.preventDefault(); + this.iframe.sizeiframe(this.toPixelValue(), true); + } else if (e.key === 'ArrowUp') { + this.setState( + { + inputEmValue: round( + Number(e.target.value.replace(fpRegex, '')) + + (e.shiftKey ? 0.5 : 0.1), + 1 + ), + }, + () => {} + ); + this.iframe.sizeiframe(this.toPixelValue(), true); + } else if (e.key === 'ArrowDown') { + this.setState( + { + inputEmValue: round( + Number(e.target.value.replace(fpRegex, '')) - + (e.shiftKey ? 0.5 : 0.1), + 1 + ), + }, + () => {} + ); + this.iframe.sizeiframe(this.toPixelValue(), true); + } + } + + handleEmBlur(e) { + this.setState({ inputEmValue: this.em }, () => {}); + e.target.value = this.state.inputEmValue; + } + + toPixelValue() { + return Math.floor(this.state.inputEmValue * this.iframe.bodySize); + } + + render() { + if (!window.__PRERENDER_INJECTED) { + return html` +
        +  /  +
        + `; + } + } +} + +export { ViewportSize }; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_ish-sizing.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.scss similarity index 53% rename from packages/uikit-workshop/src/sass/scss/04-components/_ish-sizing.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.scss index 5435c4537..a811d6ced 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_ish-sizing.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport-size/pl-viewport-size.scss @@ -2,18 +2,34 @@ #ISH SIZING \*------------------------------------*/ +@import '../../../sass/scss/core.scss'; + /** * Viewport size form * 1) This is the form for the form that houses the current * viewport size in px and em */ +pl-viewport-size { + display: flex; + align-items: center; + justify-content: center; +} + .pl-c-viewport-size { margin: 0; border: 0; - padding: 0.3rem 0.5rem 0.4rem; + + // Prevent zooming on phone browser when the font size is smaller than 16px + // As it would break the visualization the field itself will be scaled to 85% + font-size: 1rem; + transform: scale(0.85); + + padding: 0.3rem 0.25rem; line-height: 1; display: flex; align-items: center; + flex-shrink: 0; + justify-content: center; } /** @@ -25,11 +41,18 @@ border: 0; border-radius: $pl-border-radius; background-color: transparent; - font-size: inherit; - color: $pl-color-gray-50; - width: 35px; + color: inherit; + width: auto; text-align: right; transition: all $pl-animate-quick ease-out; + pointer-events: none; + text-overflow: ellipsis; +} + +.pl-c-viewport-size__input-action { + max-width: 47px; + font-size: inherit; + pointer-events: auto; &::-moz-focus-inner { padding: 0; @@ -49,7 +72,6 @@ outline-offset: -1px; } } - /** * Size input labels */ @@ -57,47 +79,5 @@ display: block; margin: 0; padding: 0; + cursor: pointer; } - -/** - * Size options - * 1) This holds the S, M, L, Rand, Disco links - * 2) Depending on the config, these number of options may be - * larger or smaller. - */ -.pl-c-size-list { - display: none; - list-style: none; - margin: 0; - padding: 0; - overflow-x: auto; - padding: 0 0.25rem; - - @media all and (min-width: $pl-bp-med) { - align-items: center; - -webkit-overflow-scrolling: touch; - - } - - @media all and (min-width: $pl-bp-large) { - display: block; - display: flex; - } -} - -/** - * Size actions - * 1) These are the buttons that control the viewport resizing - */ -.pl-c-size-list__action { - @include linkStyle(); -} - -// Force list items to center align if not overflow scrolling -.pl-c-size-list__item:first-child { - margin-left: auto; -} - -.pl-c-size-list__item:last-child { - margin-right: auto; -} \ No newline at end of file diff --git a/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js new file mode 100644 index 000000000..ffbef44d7 --- /dev/null +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.js @@ -0,0 +1,543 @@ +/* eslint-disable no-unused-vars, no-param-reassign */ +import { ifDefined } from 'lit-html/directives/if-defined'; +import { store } from '../../store.js'; // connect to redux +import { updateCurrentPattern, updateCurrentUrl } from '../../actions/app.js'; // redux actions +import { updateViewportPx, updateViewportEm } from '../../actions/app.js'; // redux actions needed +import { + minViewportWidth, + maxViewportWidth, + urlHandler, + patternName, + iframeMsgDataExtraction, +} from '../../utils'; + +import { html } from 'lit-html'; +import { BaseLitComponent } from '../../components/base-component.js'; + +import iframeLoaderStyles from '../../../sass/pattern-lab--iframe-loader.scss?external'; +import styles from './pl-viewport.scss?external'; +import { customElement } from 'lit-element'; + +let trackingPageChange = false; + +@customElement('pl-iframe') +class IFrame extends BaseLitComponent { + constructor() { + super(); + this.handlePageChange = this.handlePageChange.bind(this); + this.handlePageLoad = this.handlePageLoad.bind(this); + this.receiveIframeMessage = this.receiveIframeMessage.bind(this); + this.handleResize = this.handleResize.bind(this); + this.handleMouseDown = this.handleMouseDown.bind(this); + this.handleIframe404 = this.handleIframe404.bind(this); + } + + connectedCallback() { + super.connectedCallback && super.connectedCallback(); + iframeLoaderStyles.use(); + styles.use(); + + this.defaultPattern = + window.config && window.config.defaultPattern + ? window.config.defaultPattern + : 'all'; + + this.defaultIframeUrl = urlHandler.getFileName(this.defaultPattern); + + if (trackingPageChange === false) { + trackingPageChange = true; + document.addEventListener('patternPartial', this.handlePageLoad); + window.addEventListener('popstate', this.handlePageChange); + } + + const state = store.getState(); + this.themeMode = state.app.themeMode || 'dark'; + this.isViewallPage = state.app.isViewallPage || false; + this.currentPattern = state.app.currentPattern || ''; + this.layoutMode = state.app.layoutMode; + + if (state.app.viewportPx) { + this.sizeiframe(state.app.viewportPx, false); + } + + window.addEventListener('message', this.receiveIframeMessage, false); + window.addEventListener('resize', this.handleResize); + this.handleOrientationChange(); + + // the simple HTML to render in the iFrame when encountering broken links + this.iframe404Fallback = ` +
        +
        +
        +
        +

        Oh snap, a 404!

        +

        You might want to double-check to see if the page you're looking for has moved or if your URL is correct.

        +

        Alternatively, click here to head back to the default Pattern Lab page!

        +
        +
        +
        +
        + `; + + this._hasInitiallyRendered = false; + this.fullMode = true; + this.viewportResizeHandleWidth = 22; //Width of the viewport drag-to-resize handle + this.bodySize = + window.config.ishFontSize !== undefined + ? parseInt(window.config.ishFontSize, 10) + : parseInt( + window + .getComputedStyle(document.body, null) + .getPropertyValue('font-size'), + 10 + ); //Body size of the document + + //set up the default for the + this.baseIframePath = + window.location.protocol + + '//' + + window.location.host + + window.location.pathname.replace('index.html', ''); + this.defaultIframePath = this.baseIframePath + '?p=components-overview'; + } + + disconnectedCallback() { + super.disconnectedCallback && super.disconnectedCallback(); + iframeLoaderStyles.unuse(); + styles.unuse(); + } + + /** + * returns the current patternName after removing any numbers / dashes + * Workaround to PL Node not always having clean viewall / pattern links + */ + sanitizePatternName(plName) { + if (urlHandler.getFileName(plName)) { + return plName; + } else if ( + !document.querySelector(`[data-patternpartial="${plName}"]`) && + plName + ) { + return plName.replace(/[-][0-9][0-9]/g, ''); + } else { + return plName; + } + } + + // returns the current patternName based on the `p=` query string OR the default pattern that's set globall (as a fallback) + getPatternParam() { + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const patternParam = urlParams.get('p'); + + if (patternParam === null) { + return this.defaultPattern; + } else { + return this.sanitizePatternName(patternParam); + } + } + + // adds / updates the page's query string + handlePageLoad(e) { + const currentPattern = this.getPatternParam(); + + if (currentPattern) { + document.title = 'Pattern Lab - ' + currentPattern; + + const addressReplacement = + window.location.protocol === 'file:' + ? null + : window.location.protocol + + '//' + + window.location.host + + (window.config.noIndexHtmlremoval + ? window.location.pathname + : window.location.pathname.replace('index.html', '')) + + '?p=' + + currentPattern; + + if (this.dontWipeBrowserHistory === true) { + window.history.replaceState( + { + currentPattern: currentPattern, + }, + null, + addressReplacement + ); + this.dontWipeBrowserHistory = false; + } else { + window.history.pushState( + { + currentPattern: currentPattern, + }, + null, + addressReplacement + ); + } + } + } + + // navigate to the new PL page (based on the query string) when the page's pop state changes + handlePageChange(e) { + if (e?.state?.currentPattern) { + this.navigateTo(e.state.currentPattern); + } else { + this.navigateTo(this.getPatternParam()); + } + } + + //Resize the viewport + //'size' is the target size of the viewport + //'animate' is a boolean for switching the CSS animation on or off. 'animate' is true by default, but can be set to false for things like nudging and dragging + sizeiframe(size, animate) { + let theSize; + const self = this; + + // @todo: refactor to better handle the iframe async rendering + if (this.iframe) { + if (animate === true) { + this.iframeContainer.classList.add('is-animating'); + this.iframe.classList.add('is-animating'); + } + + if (size < maxViewportWidth) { + theSize = size; + } else { + //If the entered size is larger than the max allowed viewport size, cap value at max vp size + theSize = maxViewportWidth; + } + + if (size < minViewportWidth) { + //If the entered size is less than the minimum allowed viewport size, cap value at min vp size + theSize = minViewportWidth; + } + + if (theSize > this.clientWidth) { + theSize = this.clientWidth; + } + + // resize viewport wrapper to desired size + size of drag resize handler + // this.iframeContainer.style.width = theSize + this.viewportResizeHandleWidth + 'px'; + this.iframeContainer.style.width = theSize + 'px'; + // this.iframe.style.width = theSize + 'px'; // resize viewport to desired size + + // auto-remove transition classes if not the animate param isn't set to true + setTimeout(function () { + if (animate === true) { + self.iframeContainer.classList.remove('is-animating'); + self.iframe.classList.remove('is-animating'); + } + }, 800); + + const targetOrigin = + window.location.protocol === 'file:' + ? '*' + : window.location.protocol + '//' + window.location.host; + + const obj = JSON.stringify({ + event: 'patternLab.resize', + resize: 'true', + }); + + // only tell the iframe to resize when it's ready + if (this._hasInitiallyRendered) { + this.iframe.contentWindow.postMessage(obj, targetOrigin); + } + + this.updateSizeReading(theSize); // update the displayed values in the toolbar + } + } + + handleOrientationChange() { + // Listen for resize changes + const self = this; + if (window.orientation !== undefined) { + this.origOrientation = window.orientation; + window.addEventListener( + 'orientationchange', + function () { + if (window.orientation !== this.origOrientation) { + const newWidth = window.innerWidth; + self.iframeContainer.style.width = newWidth; + self.iframe.style.width = newWidth; + self.updateSizeReading(newWidth); + this.origOrientation = window.orientation; + } + }, + false + ); + } + } + + handleResize() { + this.updateSizeReading(this.iframeContainer.clientWidth); + } + + // Update Pixel and Em inputs + // 'size' is the input number + // 'unit' is the type of unit: either px or em. Default is px. + // Accepted values are 'px' and 'em' + // 'target' is what inputs to update. Defaults to both + updateSizeReading(size, unit, target) { + if (size === 0) { + return; + } + let emSize, pxSize; + + if (unit === 'em') { + // if size value is in em units + emSize = size; + pxSize = Math.floor(size * this.bodySize); + } else { + // if value is px or absent + pxSize = size; + emSize = size / this.bodySize; + } + + if (target === 'updatePxInput') { + store.dispatch(updateViewportPx(pxSize)); + } else if (target === 'updateEmInput') { + store.dispatch(updateViewportEm(emSize.toFixed(2))); + } else { + store.dispatch(updateViewportPx(pxSize)); + store.dispatch(updateViewportEm(emSize.toFixed(2))); + } + } + + _stateChanged(state) { + if (this._hasInitiallyRendered) { + if (state.app.viewportPx) { + this.sizeiframe(state.app.viewportPx, false); + } else { + this.sizeiframe(this.iframe.clientWidth, false); + } + } + + // Update size when layout is changed + if (this.layoutMode !== state.app.layoutMode) { + this.layoutMode = state.app.layoutMode; + if (this.iframeContainer) { + this.updateSizeReading(this.iframeContainer.clientWidth); + } + } + } + + navigateTo(pattern = patternName) { + const plName = this.sanitizePatternName(pattern); + const plPath = urlHandler.getFileName(plName); + + if (plPath) { + this.iFramePath = + plPath !== '' + ? this.baseIframePath + plPath + '?' + Date.now() + : this.defaultIframePath; + this.dontWipeBrowserHistory = true; + + document + .querySelector('.pl-js-iframe') + .contentWindow.location.replace(this.iFramePath); + } + } + + firstUpdated() { + this.iframe = this.querySelector('.pl-js-iframe'); + this.iframeContainer = this.querySelector('.pl-js-vp-iframe-container'); + this.iframeCover = this.querySelector('.pl-js-viewport-cover'); + this.updateSizeReading(this.iframeContainer.clientWidth); + + // watch for URL changes to try and catch any 404s within PL's iFrame + // + // technique loosely based off of https://stackoverflow.com/a/47675884 + const unloadIframeHandler = () => { + // Timeout needed since the URL changes immediately after the `unload` event is dispatched. + setTimeout(() => { + this.handleIframe404(); + }, 0); + }; + + const attachIframeUnload = () => { + // Remove the unloadIframeHandler in case it was already attached to avoid firing twice + if (this.iframe.contentWindow) { + this.iframe.contentWindow.removeEventListener( + 'unload', + unloadIframeHandler + ); + this.iframe.contentWindow.addEventListener( + 'unload', + unloadIframeHandler + ); + } + }; + + this.iframe.addEventListener('load', attachIframeUnload); + attachIframeUnload(); + } + + // logic that trying to handle 404s in the PL iframe + handleIframe404() { + setTimeout(() => { + if ( + this.iframe?.contentWindow?.document?.body?.textContent.includes( + 'Cannot GET' + ) || + this.iframe?.contentWindow?.document?.title.includes('Error') + ) { + /** + * Replace the iFrame's inner contents vs literally use a srcdoc. + * Workaround to avoiding an infinite loop (if using srcdoc) which breaks the ability to + * hit the back button if you hit a 404 + */ + this.iframe.contentWindow.document.body.innerHTML = + this.iframe404Fallback; + } + }, 100); + } + + render() { + const url = urlHandler.getFileName(this.getPatternParam()); + + const initialWidth = + !window.config.defaultInitialViewportWidth && + store.getState().app.viewportPx && + store.getState().app.viewportPx <= this.clientWidth + ? store.getState().app.viewportPx + 'px;' + : '100%'; + + return html` +
        + +
        + + +
        +
        + + Drag to resize Pattern Lab + + +
        +
        +
        +
        + `; + } + + handleMouseDown(event) { + // capture default data + const self = this; + self.querySelector('.pl-js-resize-handle').classList.add('is-resizing'); + const origClientX = event.clientX; + const origViewportWidth = this.iframeContainer.clientWidth; + + this.fullMode = false; + + // show the cover + this.iframeCover.hidden = false; + + function handleIframeCoverResize(e) { + const viewportWidth = origViewportWidth + 2 * (e.clientX - origClientX); + if ( + viewportWidth > minViewportWidth && + viewportWidth < maxViewportWidth + ) { + self.sizeiframe(viewportWidth, false); + } else if (viewportWidth > maxViewportWidth) { + self.sizeiframe(maxViewportWidth, false); + } else { + self.sizeiframe(minViewportWidth, false); + } + } + + // add the mouse move event and capture data. also update the viewport width + this.iframeCover.addEventListener('mousemove', handleIframeCoverResize); + + document.body.addEventListener( + 'mouseup', + function () { + self.iframeCover.removeEventListener( + 'mousemove', + handleIframeCoverResize + ); + self.iframeCover.hidden = true; + self + .querySelector('.pl-js-resize-handle') + .classList.remove('is-resizing'); + }, + { + once: true, + } + ); + + return false; + } + + /** + * updates the nav after the iframed page tells the iframe it's done loading + * + * @param {MessageEvent} e A message received by a target object. + */ + receiveIframeMessage(e) { + const data = iframeMsgDataExtraction(e); + + // try to auto-correct for currentPattern data that doesn't always match with url + // workaround for certain pages (especially view all pages) not always matching up internally with the expected current pattern key + if (data.event !== undefined && data.event === 'patternLab.pageLoad') { + try { + const currentPattern = + this.sanitizePatternName(data.patternpartial) || + this.getPatternParam(); + + document.title = 'Pattern Lab - ' + currentPattern; + + const addressReplacement = + window.location.protocol === 'file:' + ? null + : window.location.protocol + + '//' + + window.location.host + + (window.config.noIndexHtmlremoval + ? window.location.pathname + : window.location.pathname.replace('index.html', '')) + + '?p=' + + currentPattern; + + window.history.replaceState( + { + currentPattern: currentPattern, + }, + null, + addressReplacement + ); + + const currentUrl = urlHandler.getFileName(currentPattern); + if (currentUrl) { + store.dispatch(updateCurrentUrl(currentUrl)); + } + store.dispatch(updateCurrentPattern(currentPattern)); + } catch (error) { + console.log(error); + } + } + } +} + +export { IFrame }; diff --git a/packages/uikit-workshop/src/sass/scss/04-components/_viewport.scss b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.scss similarity index 61% rename from packages/uikit-workshop/src/sass/scss/04-components/_viewport.scss rename to packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.scss index a2dcdd6a7..d5e3211f0 100644 --- a/packages/uikit-workshop/src/sass/scss/04-components/_viewport.scss +++ b/packages/uikit-workshop/src/scripts/lit-components/pl-viewport/pl-viewport.scss @@ -2,12 +2,27 @@ #VIEWPORT \*------------------------------------*/ +@import '../../../sass/scss/core.scss'; + /** * To keep user code and PL code separate, and to make * resizing the viewport possible, PL contains an iframe * that houses all user code. */ +$pl-resizer-width: 20px; +$pl-viewport-bg: #f4f4f4; + +.pl-c-viewport-modal-wrapper { + background-color: $pl-viewport-bg; +} + +pl-iframe { + display: flex; + flex-grow: 1; + background-color: $pl-viewport-bg; +} + /** * Viewport * 1) This wrapper div occupies all remaining viewport space after PL's header @@ -17,7 +32,7 @@ flex-direction: column; width: 100%; position: relative; - top: $offset-top; + top: 0; bottom: 0; left: 0; right: 0; @@ -25,13 +40,13 @@ flex-grow: 1; transition: height 0.3s ease; - @supports (position: sticky) { - top: 0; - } + // @supports (position: sticky) { + // top: 0; + // } - .pl-c-body--theme-sidebar & { - top: 0; - } + // .pl-c-body--theme-sidebar & { + // top: 0; + // } } /** @@ -42,7 +57,6 @@ .pl-c-viewport__cover { width: 100%; height: 100%; - display: none; position: fixed; top: 0; left: 0; @@ -59,31 +73,40 @@ .pl-c-viewport__iframe-wrapper { display: flex; flex-direction: column; + width: 100vw; max-width: 100vw; - width: 100%; // bug fix for Safari and Firefox getting stuck calculating a width of 0px when the JS first kicks in position: relative; margin: 0 auto; - flex: 1; + flex-grow: 1; -webkit-overflow-scrolling: touch; + min-width: 240px; + max-width: 100vw; + background: $pl-viewport-bg; + padding-right: 0; + padding-left: 0; + // box-shadow: 0 3px 6px rgba(21,22,25,.16), 0 3px 6px rgba(21,22,25,.23); &.hay-mode { transition: all 40s linear; } - width: 100%; // bug fix for Safari and Firefox getting stuck calculating a width of 0px when the JS first kicks in .pl-c-body--theme-sidebar & { @media all and (min-width: $pl-bp-med) { max-width: calc(100vw - #{$pl-sidebar-width}); + width: calc(100vw - #{$pl-sidebar-width}); } } } +.is-animating { + transition: all 0.2s linear; +} + /** * Viewport iframe * 1) this is the actual