├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc.yml
├── .release-it.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── eslint.config.js
├── lib
└── index.d.ts
├── package-lock.json
├── package.json
├── src
├── index.js
└── set_defaults.js
└── test
├── fixture
├── file1
├── file2
├── func
└── nested
│ └── index
├── index.js
└── index.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | charset = utf-8
3 |
4 | [*.{js,json,yml}]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Automatically normalize line endings for all text-based files
2 | # http://git-scm.com/docs/gitattributes#_end_of_line_conversion
3 | * text=auto eol=lf
4 |
5 | # For binary file types, prevent converting CRLF chars
6 | *.jpg -text
7 | *.png -text
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches: ['**']
5 | pull_request:
6 | branches: ['main']
7 |
8 | jobs:
9 | pre-test:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 | - uses: actions/setup-node@v3
14 | with:
15 | cache: 'npm'
16 |
17 | - run: npm install
18 | - run: npm run format:check
19 | - run: npm run lint:check
20 |
21 | branch-test:
22 | if: github.ref_name != 'main' && success()
23 | needs: pre-test
24 | runs-on: ${{ matrix.os }}
25 | strategy:
26 | matrix:
27 | os: ['ubuntu-latest', 'windows-latest']
28 | node: ['14.18.0']
29 | name: Testing Node ${{ matrix.node }} on ${{ matrix.os }}
30 | steps:
31 | - uses: actions/checkout@v3
32 | - uses: actions/setup-node@v3
33 | with:
34 | cache: 'npm'
35 |
36 | - run: npm install
37 | - run: npm test
38 |
39 | test:
40 | if: github.ref_name == 'main' && success()
41 | needs: pre-test
42 | runs-on: ${{ matrix.os }}
43 | strategy:
44 | matrix:
45 | os: ['ubuntu-latest', 'windows-latest']
46 | node: ['14.18.0', '16.0', '18.0', '20.0']
47 | name: Testing Node ${{ matrix.node }} on ${{ matrix.os }}
48 | steps:
49 | - uses: actions/checkout@v3
50 | - uses: actions/setup-node@v3
51 | with:
52 | node-version: ${{ matrix.node }}
53 | cache: 'npm'
54 |
55 | - run: npm install
56 | - run: npm test
57 | - if: matrix.os == 'ubuntu-latest' && matrix.node == '20.0'
58 | run: npm run coverage
59 | - if: matrix.os == 'ubuntu-latest' && matrix.node == '20.0'
60 | uses: coverallsapp/github-action@v2
61 | with:
62 | file: coverage.info
63 | format: lcov
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log*
2 | .npm
3 | *.tgz
4 | .eslintcache
5 | coverage
6 | coverage.info
7 | test/fixtures/*/build
8 | node_modules
9 | lib/*.*js
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock.json = false
2 | sign-git-tag = true
3 | message = Bump package.json to %s
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | test/fixtures/**
2 | .nyc_output/**
3 | package-lock.json
--------------------------------------------------------------------------------
/.prettierrc.yml:
--------------------------------------------------------------------------------
1 | trailingComma: none
2 | tabWidth: 2
3 | semi: false
4 | singleQuote: true
5 | bracketSpacing: true
6 | arrowParens: always
7 | printWidth: 120
8 |
--------------------------------------------------------------------------------
/.release-it.json:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "before:init": ["npm run lint", "npm test"],
4 | "after:npm:bump": "npm pack",
5 | "after:bump": "auto-changelog -p --commit-limit false --ignore-commit-pattern '^((dev|chore|ci):|Release)'",
6 | "after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
7 | },
8 | "git": {
9 | "commitMessage": "Release ${version}",
10 | "commitArgs": ["-S"],
11 | "tagAnnotation": "Release ${version}",
12 | "tagArgs": ["-s"],
13 | "changelog": "auto-changelog -u --commit-limit false --ignore-commit-pattern '^((dev|chore|ci):|Release)' --stdout -t https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs"
14 | },
15 | "npm": {
16 | "publish": false
17 | },
18 | "github": {
19 | "release": true,
20 | "releaseName": "@metalsmith/default-values ${version}",
21 | "tokenRef": "GITHUB_TOKEN",
22 | "assets": ["metalsmith-default-values-${version}.tgz"]
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### Changelog
2 |
3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4 |
5 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6 |
7 | #### [v4.0.1](https://github.com/metalsmith/default-values/compare/v4.0.0...v4.0.1)
8 |
9 | - Updates dlv 3.1.3 -> 3.1.4, fixes security vulns [`d93c72c`](https://github.com/metalsmith/default-values/commit/d93c72cf61946c3df1f35dad8cc74d45a0421e92)
10 | - Documents potential pitfall when setting default object [`46b2db9`](https://github.com/metalsmith/default-values/commit/46b2db92db8c066bc93662b746c882f181a3bc85)
11 | - Changes set_defaults to return change delta, improves debug logs [`88a49da`](https://github.com/metalsmith/default-values/commit/88a49da6ea7e8b8d9d8a8b9e52a380284bb7d6b3)
12 |
13 | ### [v4.0.0](https://github.com/metalsmith/default-values/compare/v3.3.0...v4.0.0)
14 |
15 | > 20 March 2024
16 |
17 | - Provides dual ESM/CJS module and aligns repo setup with other core plugins [`5d23dbd`](https://github.com/metalsmith/default-values/commit/5d23dbd1091e8d09030bdd9b2d6c945e6cd80476)
18 | - test: migrate test coverage from nyc -> c8, tests from CJS to ESM [`e03aacf`](https://github.com/metalsmith/default-values/commit/e03aacf7b4956a962258d791027782fe34953aa2)
19 | - Moves to more permissive LGPL license [`294f77f`](https://github.com/metalsmith/default-values/commit/294f77ffff73f848064dccb2d1817d484e9853c5)
20 | - Provides access to metalsmith.metadata() within default setter functions [`d4a5723`](https://github.com/metalsmith/default-values/commit/d4a57232bb7942ef001ec348a5f44350990f43a2)
21 | - Swaps out lodash.get/set for resp. dlv/dset & fixes security vulnerability [`1c27fd3`](https://github.com/metalsmith/default-values/commit/1c27fd330d854529f7d11b084135fd7ac64d3f36)
22 | - Clarifies default setting at keypaths and buffer conversion [`6c363de`](https://github.com/metalsmith/default-values/commit/6c363de5f777046a03c7432ac425fbf6af089d9f)
23 | - Adds 'strategy' option to allow overwriting existing values [`6e61e96`](https://github.com/metalsmith/default-values/commit/6e61e9653e7bee8d425324805bbc6e88c9fb7a0a)
24 | - Transforms default value into buffer if target type is already a buffer [`7287c08`](https://github.com/metalsmith/default-values/commit/7287c08aa94ef7cd7bdbceb58687acdfdfbc533b)
25 | - Adds generics for file & global metadata to Typescript types [`fb81838`](https://github.com/metalsmith/default-values/commit/fb818381d1246fa023f57f2ee4adaaa53428866f)
26 | - test: adds TS test [`f00280c`](https://github.com/metalsmith/default-values/commit/f00280c89eb01cafd59875e605060a597aae56f0)
27 | - Minor performance enhancement in calling setDefaults [`9dd6a84`](https://github.com/metalsmith/default-values/commit/9dd6a843b8acd413b0d2323f5b056248e74313ae)
28 | - Drops support for Node.js < 14.18.0, updates CI [`fbfa2c7`](https://github.com/metalsmith/default-values/commit/fbfa2c7897368cd272a19d3038d0b98c69a78574)
29 | - Updates dset 3.1.2 -> 3.1.3 [`d9a8d1e`](https://github.com/metalsmith/default-values/commit/d9a8d1e5805f4ccb49c80bec36196d45f87ce7fd)
30 |
31 | #### [v3.3.0](https://github.com/metalsmith/default-values/compare/v3.2.1...v3.3.0)
32 |
33 | > 26 November 2022
34 |
35 | - Allow setting default contents when buffer is empty [`5d41d17`](https://github.com/metalsmith/default-values/commit/5d41d1790b1d4bc6a2905c08d028ab67c83221f4)
36 | - Docs: Add elaborate example with other plugins + single defaults set usage [`bb50253`](https://github.com/metalsmith/default-values/commit/bb502537ffb476208cb032570b3d7c4f4db98847)
37 | - Drops support for Metalsmith < 2.5.0, replaces debug with metalsmith.debug [`b5191b4`](https://github.com/metalsmith/default-values/commit/b5191b471b1d6a3742b57b5eb33629ed32acc12e)
38 | - Adds Typescript support [`3b1b438`](https://github.com/metalsmith/default-values/commit/3b1b438243b0638d0d25db69f55999a97a302f08)
39 | - Document features in README.md [`12102c8`](https://github.com/metalsmith/default-values/commit/12102c81d729d766d7b9be904aa601023b893426)
40 | - Log a warning when pattern matches no files [`c62cbc9`](https://github.com/metalsmith/default-values/commit/c62cbc98f19fa5ac2fe8529996d832895a2cdf93)
41 | - Allows passing a single defaults set as shorthand for [defaultsSet] [`39df8f7`](https://github.com/metalsmith/default-values/commit/39df8f749d22899aaaf4cd1adad5080ae821c193)
42 | - Renames default export initDefaultValues -> defaultValues [`30fc0c5`](https://github.com/metalsmith/default-values/commit/30fc0c5c54392cf21d3ced7eabdab209aac0e26d)
43 |
44 | #### [v3.2.1](https://github.com/metalsmith/default-values/compare/v3.2.0...v3.2.1)
45 |
46 | > 1 August 2022
47 |
48 | - Fixes #24: use ms.match(pattern, files) signature for branch/watch compat [`#24`](https://github.com/metalsmith/default-values/issues/24)
49 | - Updates debug 4.3.3 -> 4.3.4. Upgrades package-lock.json to v2 & fixes security issue [`67a968b`](https://github.com/metalsmith/default-values/commit/67a968b4d3799d6c95d98f2eb2472796c1b59b98)
50 | - Enhancement: add JSDoc example + better options doc [`93b52f2`](https://github.com/metalsmith/default-values/commit/93b52f22b8bf969fa7eb8a7ea10dd8c201c99f91)
51 |
52 | #### [v3.2.0](https://github.com/metalsmith/default-values/compare/v3.1.0...v3.2.0)
53 |
54 | > 2 May 2022
55 |
56 | - Removed console log from code [`#21`](https://github.com/metalsmith/default-values/pull/21)
57 | - Drops Node < 12 support, adds metalsmith as peer & devDep [`7262bf6`](https://github.com/metalsmith/default-values/commit/7262bf604d9d41774bbb13443fd384c3f3d136e1)
58 | - Removes multimatch, uses metalsmith.match. Simplified & refactored [`d6f8407`](https://github.com/metalsmith/default-values/commit/d6f84076e6fe91ca3205c1ed2c14a7cca4694b98)
59 | - Removed Joi options validation in favor of allowing options to be undefined [`19e5f23`](https://github.com/metalsmith/default-values/commit/19e5f23c11cdf2104d6ccce4027ff27728922775)
60 |
61 | #### [v3.1.0](https://github.com/metalsmith/default-values/compare/v3.0.2...v3.1.0)
62 |
63 | > 30 January 2022
64 |
65 | - Updated packages [`#18`](https://github.com/metalsmith/default-values/pull/18)
66 | - Align plugin with other core plugins. Update package.json, generate changelog, fix debug namespace [`cae2058`](https://github.com/metalsmith/default-values/commit/cae2058d73a736adf519f9b83b93b7879ad1a45e)
67 |
68 | #### [v3.0.2](https://github.com/metalsmith/default-values/compare/v3.0.1...v3.0.2)
69 |
70 | > 7 September 2020
71 |
72 | - Updated Packages [`#17`](https://github.com/metalsmith/default-values/pull/17)
73 | - Package updated [`8ae7cf2`](https://github.com/metalsmith/default-values/commit/8ae7cf224db67eb65c239fc473225149f1ab2670)
74 | - Package updated [`0e582de`](https://github.com/metalsmith/default-values/commit/0e582de4de19581ea02792415195395ad646c299)
75 | - Removed outdated badges [`2afcd0e`](https://github.com/metalsmith/default-values/commit/2afcd0e915c27ba7f91538042504160fb47edeb1)
76 | - Removed Node version warning [`f4a6327`](https://github.com/metalsmith/default-values/commit/f4a6327babaa2696062fad1f89d69033b1ee18a4)
77 |
78 | #### [v3.0.1](https://github.com/metalsmith/default-values/compare/v3.0.0...v3.0.1)
79 |
80 | > 7 September 2020
81 |
82 | - Org switch to Metalsmith scope [`#16`](https://github.com/metalsmith/default-values/pull/16)
83 | - Greenkeeper: removed ignore as Node.js v4 support is no longer required [`4b846f5`](https://github.com/metalsmith/default-values/commit/4b846f51e4072aabb2e51271a26742b6a6abde40)
84 |
85 | ### [v3.0.0](https://github.com/metalsmith/default-values/compare/v2.1.0...v3.0.0)
86 |
87 | > 11 September 2018
88 |
89 | - Packages updated [`#15`](https://github.com/metalsmith/default-values/pull/15)
90 | - Update debug to the latest version 🚀 [`#14`](https://github.com/metalsmith/default-values/pull/14)
91 | - Update eslint-config-prettier to the latest version 🚀 [`#12`](https://github.com/metalsmith/default-values/pull/12)
92 | - Travis: Removed testing for v4-5 as they're no longer maintained [`6277b21`](https://github.com/metalsmith/default-values/commit/6277b2161445bb915eef68bfb242f5ebc223596d)
93 | - fix(package): update debug to version 4.0.0 [`7f38589`](https://github.com/metalsmith/default-values/commit/7f38589494cd1d96e1f59f85543f91cf8dcf691a)
94 | - chore(package): update eslint-config-prettier to version 3.0.0 [`ac8689a`](https://github.com/metalsmith/default-values/commit/ac8689ad3d97fe55b43bbef6639c252158a5387d)
95 | - Travis: Added v10 to test [`d3b01e3`](https://github.com/metalsmith/default-values/commit/d3b01e33a35e5d6a7ea78b6dee27f9823cafeb0a)
96 |
97 | #### [v2.1.0](https://github.com/metalsmith/default-values/compare/v2.0.1...v2.1.0)
98 |
99 | > 19 July 2018
100 |
101 | - default value with a function [`#10`](https://github.com/metalsmith/default-values/pull/10)
102 | - Update dependencies to enable Greenkeeper 🌴 [`#11`](https://github.com/metalsmith/default-values/pull/11)
103 | - Revered packages and ignored with greenkeeper [`5e7645c`](https://github.com/metalsmith/default-values/commit/5e7645c6de8d23278f91b6160ec813921d2f16ac)
104 | - Removed BitHound Badges :( [`7b255a9`](https://github.com/metalsmith/default-values/commit/7b255a9e3a861d06744542febfcfa5b31da9f747)
105 | - Added badge [`210c7f9`](https://github.com/metalsmith/default-values/commit/210c7f9dbe4946685f7636ae87505334843fba2b)
106 | - chore(package): update dependencies [`d587d71`](https://github.com/metalsmith/default-values/commit/d587d7103483bd7a5b68d75707e1164f765763d1)
107 | - Update README.md [`e9de8d3`](https://github.com/metalsmith/default-values/commit/e9de8d3493943221012737a2583c760cc81bcca0)
108 | - Badges: updated [`fd0d488`](https://github.com/metalsmith/default-values/commit/fd0d4887a2178ff689ad7333bed9d2872e33de7b)
109 | - Updated package scripts [`4c26c3d`](https://github.com/metalsmith/default-values/commit/4c26c3d0110cc2ed99700ae7d7e30cb83dfd7b8b)
110 | - docs(readme): add Greenkeeper badge [`489007a`](https://github.com/metalsmith/default-values/commit/489007ae174d55f6ef375a0fe5984461286e3ca0)
111 | - Update README.md [`9d82281`](https://github.com/metalsmith/default-values/commit/9d82281a72a774c08c0c53f8d4ed4a4c8957e1f8)
112 |
113 | #### [v2.0.1](https://github.com/metalsmith/default-values/compare/v2.0.0...v2.0.1)
114 |
115 | > 24 January 2018
116 |
117 | - Dependencies: Updated Fixes #4 and general maintenance [`#8`](https://github.com/metalsmith/default-values/pull/8)
118 | - Merge pull request #8 from woodyrew/fix-dependencies [`#4`](https://github.com/metalsmith/default-values/issues/4)
119 | - Dependencies: Updated Fixes #4 and general maintenance [`#4`](https://github.com/metalsmith/default-values/issues/4) [`#7`](https://github.com/metalsmith/default-values/issues/7) [`#6`](https://github.com/metalsmith/default-values/issues/6) [`#3`](https://github.com/metalsmith/default-values/issues/3) [`#5`](https://github.com/metalsmith/default-values/issues/5)
120 | - Extra information and examples [`ae84ed0`](https://github.com/metalsmith/default-values/commit/ae84ed0d8d926695efb890150781489f7c3e1352)
121 | - All the badges [`df8316f`](https://github.com/metalsmith/default-values/commit/df8316f62a4658110eb8596f30f3635d7a4bc9de)
122 | - README: Formatting [`cfa537f`](https://github.com/metalsmith/default-values/commit/cfa537fa3f93ac2b8e4c65c7aeec95c72a0deb98)
123 | - Updated Dependencies [`412293b`](https://github.com/metalsmith/default-values/commit/412293be44b6c9d0beee54b590e02ea64c61a2ec)
124 | - Dependencies: Downgraded Joi to 12 for Node <6 compatibility [`4df7f3c`](https://github.com/metalsmith/default-values/commit/4df7f3c70b75e09f876006dbae97582eb49f7d4d)
125 |
126 | ### [v2.0.0](https://github.com/metalsmith/default-values/compare/v1.0.1...v2.0.0)
127 |
128 | > 7 August 2017
129 |
130 | - Dependancies: Upgraded [`#1`](https://github.com/metalsmith/default-values/pull/1)
131 | - Require typo: Corrected; Fixes #2 [`#2`](https://github.com/metalsmith/default-values/issues/2)
132 | - npm 5 - Added package-lock.json [`c3be173`](https://github.com/metalsmith/default-values/commit/c3be173fe482521ad7cd8bbaebb3249a02df0db5)
133 | - ES6 - Converted to modern JS; Also added allownUnknown for config [`4e9373a`](https://github.com/metalsmith/default-values/commit/4e9373a6f0a64b96a2f4077da6a9e473abc822b9)
134 | - Updated dev dependancies and switched to TAP [`2abbc83`](https://github.com/metalsmith/default-values/commit/2abbc8386f5e79a0c963b3b49de5f763d1b03360)
135 | - Removed unecessary test index file [`914e71e`](https://github.com/metalsmith/default-values/commit/914e71e068ce535cc18a7d09a135a02820ab6184)
136 | - Added engines and updated travis node versions [`616c5f7`](https://github.com/metalsmith/default-values/commit/616c5f769e86a02582a7bb7aca5970fd8dc59c6d)
137 | - Dependencies updated [`b6574a2`](https://github.com/metalsmith/default-values/commit/b6574a2770da152cfbeea66bc1e39dc859128fd2)
138 |
139 | #### [v1.0.1](https://github.com/metalsmith/default-values/compare/v1.0.0...v1.0.1)
140 |
141 | > 27 August 2016
142 |
143 | - Dependancies: Upgraded [`498e2d4`](https://github.com/metalsmith/default-values/commit/498e2d488bda5ca69906e7e804ad0bb174bc6752)
144 | - Travis: Limited to NodeJS v4 and above. [`c724323`](https://github.com/metalsmith/default-values/commit/c72432396611a6e9c9d812471e825ca96f0b4a42)
145 | - Travis: Removed 4.0 [`c58c6b7`](https://github.com/metalsmith/default-values/commit/c58c6b7f760fd544c52c88b6c49386e7eb430632)
146 |
147 | #### v1.0.0
148 |
149 | > 27 August 2016
150 |
151 | - Initial commit [`5238b14`](https://github.com/metalsmith/default-values/commit/5238b1401b34e384592239730e55f9a14367b313)
152 | - Plugin inital state: open sourced for <3 [`18844b6`](https://github.com/metalsmith/default-values/commit/18844b615993777b5183a63cc9321c4f4e38adf1)
153 | - Testing: Added basic tests and updated readme. [`d290ca5`](https://github.com/metalsmith/default-values/commit/d290ca5bd892d92cd58bd1e43d66aed7f923760e)
154 | - Error: Returns error properly [`b72f12a`](https://github.com/metalsmith/default-values/commit/b72f12a7c2569c25b50970791392746cba4eea22)
155 | - Travis: Added [`2fa32ab`](https://github.com/metalsmith/default-values/commit/2fa32ab1d40903ac23ea5a198b8a7ae4c4160c4c)
156 | - NPM & Travis Icons: added [`6f0e103`](https://github.com/metalsmith/default-values/commit/6f0e1034743b02b5346ddc37a16add84ff208625)
157 | - Added dependencies badge [`cea37af`](https://github.com/metalsmith/default-values/commit/cea37af6d04265ded7b01168faa957972e6ee0f3)
158 | - Readme: fix require statement [`d4225f2`](https://github.com/metalsmith/default-values/commit/d4225f2a5533d4d7a567935a1529e7b4bac60f57)
159 | - ESLint: update to default - duplicate key [`8668a5a`](https://github.com/metalsmith/default-values/commit/8668a5aaa14eff117d738d9150906abcc43de5a2)
160 | - ESLint Verson: Set [`d685194`](https://github.com/metalsmith/default-values/commit/d6851941ab931fc870f4192274b280c630ae0265)
161 | - Legacy compatibility: Switched to Joi 6.x [`7c1f1ea`](https://github.com/metalsmith/default-values/commit/7c1f1ea675aff4ffc4402300c9e6582fe5430166)
162 | - Update defaults to remove duplicate [`429b664`](https://github.com/metalsmith/default-values/commit/429b664e4d98805e811f9d776252b2c3a88c9a5f)
163 | - Travis: Renamed to correct name [`88b0688`](https://github.com/metalsmith/default-values/commit/88b0688a6745255efe5470287106d7ed2a5ecba1)
164 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @metalsmith/default-values
2 |
3 | A Metalsmith plugin for setting default values to file metadata.
4 |
5 | [![metalsmith: core plugin][metalsmith-badge]][metalsmith-url]
6 | [![npm: version][npm-badge]][npm-url]
7 | [![ci: build][ci-badge]][ci-url]
8 | [![code coverage][codecov-badge]][codecov-url]
9 | [![license: LGPL-3.0][license-badge]][license-url]
10 |
11 | ## Features
12 |
13 | - sets default values for metadata keys and file contents on files matched by pattern
14 | - does not overwrite or transform key values that are already defined, unless `strategy: 'overwrite'`.
15 | - can set computed defaults based on other file keys or metalsmith metadata
16 |
17 | ## Installation
18 |
19 | NPM:
20 |
21 | ```bash
22 | npm install @metalsmith/default-values
23 | ```
24 |
25 | Yarn:
26 |
27 | ```bash
28 | yarn add @metalsmith/default-values
29 | ```
30 |
31 | ## Usage:
32 |
33 | Pass `@metalsmith/default-values` to `metalsmith.use`:
34 |
35 | ```js
36 | import defaultValues from '@metalsmith/default-values'
37 |
38 | // single defaults set for all HTML and markdown files
39 | metalsmith.use({
40 | defaults: {
41 | pattern: '**/*.md',
42 | title: 'Lorem ipsum'
43 | }
44 | })
45 |
46 | metalsmith.use(
47 | defaultValues([
48 | {
49 | pattern: 'posts/*.md',
50 | defaults: {
51 | layout: 'post.hbs',
52 | date: function (post) {
53 | return post.stats.ctime
54 | }
55 | }
56 | },
57 | {
58 | pattern: 'diary/*.md',
59 | defaults: {
60 | layout: 'diary.hbs',
61 | private: true
62 | }
63 | },
64 | {
65 | pattern: ['diary/*.md', 'archive/**/*.md'],
66 | defaults: {
67 | no_index: true
68 | }
69 | },
70 | {
71 | pattern: '**/*.md',
72 | defaults: {
73 | layout: 'default.hbs'
74 | }
75 | }
76 | ])
77 | )
78 | ```
79 |
80 | ### Options
81 |
82 | `@metalsmith/default-values` takes an array of defaults sets or a single defaults set. The defaults set has the following properties:
83 |
84 | - `pattern` (`string|string[]`): One or more glob patterns to match file paths. Defaults to `'**'` (all).
85 | - `defaults` (`Object`): An object whose key-value pairs will be added to file metadata. You can also specify a function `callback(file, metadata)` to set dynamic defaults based on existing file or global metadata.
86 | - `strategy` (`'keep'|'overwrite'`): Strategy to handle setting defaults to keys that are aleady defined.
87 |
88 | ### Examples
89 |
90 | #### Setting defaults at a keypath
91 |
92 | You can set a default at a file's nested keypath:
93 |
94 | ```js
95 | metalsmith.use(
96 | defaultValues({
97 | pattern: '**/*.md',
98 | defaults: {
99 | pubdate(file) { return new Date() }
100 | 'config.scripts.app': '/app.js'
101 | }
102 | })
103 | )
104 | ```
105 |
106 | #### Setting default objects
107 |
108 | If you assign a default object like this:
109 |
110 | ```js
111 | metalsmith.use(defaultValues({ defaults: { someObject: { id: 'some' } } }))
112 | ```
113 |
114 | All files to which the value was set will refer to the same object (`files['index.html'].someObject === files['other.html'].someObject`). If the object needs to be unique for each file, use a default setter function or specify each property as a keypath:
115 |
116 | ```js
117 | // using a function
118 | metalsmith.use(
119 | defaultValues({
120 | defaults: {
121 | someObject: () => ({ id: 'some', other: true })
122 | }
123 | })
124 | )
125 |
126 | // using keypaths
127 | metalsmith.use(
128 | defaultValues({
129 | defaults: {
130 | 'someObject.id': 'some',
131 | 'someObject.other': true
132 | }
133 | })
134 | )
135 | ```
136 |
137 | #### Setting default contents
138 |
139 | You can set a file's default contents (which is a Node buffer) and any other Buffer properties:
140 |
141 | ```js
142 | metalsmith.use(
143 | defaultValues({
144 | pattern: '**/*.md',
145 | defaults: {
146 | strategy: 'overwrite',
147 | contents: Buffer.from('TO DO')
148 | }
149 | })
150 | )
151 | ```
152 |
153 | When using a JSON config, a string can be used as default and it will automatically be transformed into a buffer.
154 |
155 | #### Setting dynamic defaults
156 |
157 | You can set dynamic defaults based on current file metadata or metalsmith metadata:
158 |
159 | ```js
160 | metalsmith
161 | .metadata({
162 | build: { timestamp: Date.now() }
163 | })
164 | .use(
165 | defaultValues([
166 | {
167 | strategy: 'overwrite',
168 | defaults: {
169 | buildInfo(file, metadata) {
170 | return metadata.build
171 | },
172 | excerpt(file) {
173 | return file.contents.toString().slice(0, 200)
174 | }
175 | }
176 | }
177 | ])
178 | )
179 | ```
180 |
181 | #### Combining with other plugins
182 |
183 | @metalsmith/default-values works great with other `@metalsmith` plugins. The example below attaches a collection and layout matching the parent directory for all files in the directories `services`,`products`, and `articles`:
184 |
185 | ```js
186 | import slugify from 'slugify'
187 | const contentTypes = ['product', 'service', 'article']
188 |
189 | metalsmith
190 | .use(
191 | defaultValues(
192 | contentTypes.map((contentType) => ({
193 | pattern: `${contentType}s/*.md`, // pluralized
194 | defaults: {
195 | collection: `${contentType}s`, // pluralized
196 | bodyClass: contentType,
197 | layout: `${contentType}.njk`, // using jstransformer-nunjucks
198 | contentLength(file) {
199 | if (file.contents) return file.contents.toString().length
200 | return 0
201 | }
202 | }
203 | }))
204 | )
205 | )
206 | .use(markdown()) // @metalsmith/markdown
207 | .use(collections()) // @metalsmith/collections
208 | .use(
209 | layouts({
210 | // @metalsmith/layouts
211 | pattern: '**/*.html'
212 | })
213 | )
214 | ```
215 |
216 | ### Debug
217 |
218 | To enable debug logs, set the `DEBUG` environment variable to `@metalsmith/default-values*`:
219 |
220 | ```js
221 | metalsmith.env('DEBUG', '@metalsmith/default-values*')
222 | ```
223 |
224 | Alternatively you can set `DEBUG` to `@metalsmith/*` to debug all Metalsmith core plugins.
225 |
226 | ### CLI usage
227 |
228 | To use this plugin with the Metalsmith CLI, add `@metalsmith/default-values` to the `plugins` key in your `metalsmith.json` file:
229 |
230 | ```json
231 | {
232 | "plugins": [
233 | {
234 | "@metalsmith/default-values": [
235 | {
236 | "pattern": "diary/*.md",
237 | "defaults": {
238 | "layout": "diary.hbs",
239 | "private": true
240 | }
241 | }
242 | ]
243 | }
244 | ]
245 | }
246 | ```
247 |
248 | ## License
249 |
250 | [LGPL-3.0 or later](LICENSE)
251 |
252 | [npm-badge]: https://img.shields.io/npm/v/@metalsmith/default-values.svg
253 | [npm-url]: https://www.npmjs.com/package/@metalsmith/default-values
254 | [ci-badge]: https://github.com/metalsmith/default-values/actions/workflows/test.yml/badge.svg
255 | [ci-url]: https://github.com/metalsmith/default-values/actions/workflows/test.yml
256 | [metalsmith-badge]: https://img.shields.io/badge/metalsmith-core_plugin-green.svg?longCache=true
257 | [metalsmith-url]: https://metalsmith.io
258 | [codecov-badge]: https://img.shields.io/coveralls/github/metalsmith/default-values
259 | [codecov-url]: https://coveralls.io/github/metalsmith/default-values
260 | [license-badge]: https://img.shields.io/github/license/metalsmith/default-values
261 | [license-url]: LICENSE
262 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import prettier from 'eslint-config-prettier'
4 | import pluginImport from 'eslint-plugin-import'
5 | import pluginNode from 'eslint-plugin-n'
6 |
7 | const config = [
8 | {
9 | ignores: ['lib', 'test/fixtures'],
10 | languageOptions: {
11 | globals: {
12 | ...globals.node
13 | },
14 |
15 | ecmaVersion: 2020,
16 | sourceType: 'module'
17 | },
18 |
19 | rules: {
20 | ...js.configs.recommended.rules,
21 | 'no-console': 'error',
22 | 'prefer-const': 'error',
23 | 'no-var': 'error',
24 | 'no-use-before-define': 'error',
25 | 'no-unused-vars': [
26 | 'error',
27 | {
28 | argsIgnorePattern: '^_',
29 | varsIgnorePattern: '^_',
30 | caughtErrorsIgnorePattern: '^_'
31 | }
32 | ],
33 | 'no-await-in-loop': 'error',
34 | 'n/exports-style': [0, 'error'],
35 | 'import/first': 'error',
36 | 'import/no-anonymous-default-export': 'error',
37 | 'import/no-unassigned-import': 'error',
38 | 'import/no-internal-modules': [
39 | 'error',
40 | {
41 | allow: ['src/**']
42 | }
43 | ]
44 | },
45 | plugins: {
46 | import: pluginImport,
47 | n: pluginNode,
48 | prettier: prettier
49 | }
50 | },
51 | {
52 | files: ['test/{**/,}*.js'],
53 | languageOptions: {
54 | globals: { ...globals.mocha }
55 | }
56 | }
57 | ]
58 |
59 | export default config
60 |
--------------------------------------------------------------------------------
/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Plugin, File } from 'metalsmith';
2 |
3 | export default defaultValues;
4 |
5 | export type DefaultSetter = (data:FileMeta, metadata: GlobalMeta) => any
6 | export interface DefaultsSet {
7 | /** an object whose keys will be set as file metadata keys */
8 | defaults: {
9 | [key:string]: DefaultSetter|string|boolean|number|Object;
10 | }
11 | /**
12 | * 1 or more glob patterns to match files.
13 | * @default '**'
14 | **/
15 | pattern?: string;
16 | /**
17 | * Strategy to handle setting defaults to keys that are aleady defined.
18 | * @default 'keep'
19 | */
20 | strategy?: 'keep'|'overwrite'
21 | }
22 | export type Options = DefaultsSet|DefaultsSet[]
23 | /**
24 | * Set `defaults` to file metadata matching `pattern`'s.
25 | *
26 | * @example
27 | * metalsmith.use(defaultValues({
28 | pattern: 'posts/*.md',
29 | defaults: {
30 | layout: 'post.hbs',
31 | draft: false,
32 | date(post) {
33 | return post.stats.ctime
34 | }
35 | }
36 | }))
37 | **/
38 | declare function defaultValues(options: Options): Plugin;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@metalsmith/default-values",
3 | "version": "4.0.1",
4 | "description": "A metalsmith plugin for setting default values to file metadata.",
5 | "keywords": [
6 | "default-values",
7 | "metalsmith-plugin",
8 | "metalsmith",
9 | "static-site"
10 | ],
11 | "homepage": "https://github.com/metalsmith/default-values#readme",
12 | "bugs": {
13 | "url": "https://github.com/metalsmith/default-values/issues"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/metalsmith/default-values.git"
18 | },
19 | "license": "LGPL-3.0-or-later",
20 | "author": "Woody Goodricke ",
21 | "maintainers": [
22 | "Kevin Van Lierde (https://webketje.com)"
23 | ],
24 | "source": "src/index.js",
25 | "main": "lib/index.cjs",
26 | "module": "lib/index.js",
27 | "exports": {
28 | "import": "./lib/index.js",
29 | "require": "./lib/index.cjs"
30 | },
31 | "type": "module",
32 | "types": "lib/index.d.ts",
33 | "directories": {
34 | "lib": "lib",
35 | "test": "test"
36 | },
37 | "files": [
38 | "lib",
39 | "CHANGELOG.md"
40 | ],
41 | "scripts": {
42 | "changelog": "auto-changelog -u --commit-limit false --ignore-commit-pattern '^((dev|chore|test|ci):|Release)'",
43 | "format": "prettier --write \"**/*.{yml,md,js,json}\"",
44 | "format:check": "prettier --list-different \"**/*.{yml,md,js,json}\"",
45 | "lint": "eslint --fix .",
46 | "lint:check": "eslint --fix-dry-run .",
47 | "coverage": "npm test && c8 report --reporter=text-lcov > ./coverage.info",
48 | "release": "npm run build && release-it .",
49 | "build": "microbundle --target node --no-sourcemap -f cjs,esm --generateTypes=false",
50 | "test": "c8 mocha",
51 | "pretest": "npm run build"
52 | },
53 | "dependencies": {
54 | "dlv": "^1.1.3",
55 | "dset": "^3.1.4"
56 | },
57 | "devDependencies": {
58 | "auto-changelog": "^2.5.0",
59 | "c8": "^10.1.3",
60 | "eslint": "^9.17.0",
61 | "eslint-config-prettier": "^9.1.0",
62 | "eslint-plugin-import": "^2.31.0",
63 | "eslint-plugin-n": "^17.15.0",
64 | "metalsmith": "^2.6.3",
65 | "microbundle": "^0.15.1",
66 | "mocha": "^11.0.1",
67 | "prettier": "^3.4.2",
68 | "release-it": "^17.10.0"
69 | },
70 | "peerDependencies": {
71 | "metalsmith": "^2.5.0"
72 | },
73 | "engines": {
74 | "node": ">=14.18.0"
75 | },
76 | "publishConfig": {
77 | "access": "public"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import getDefaultsSetter from './set_defaults.js'
2 |
3 | /**
4 | * @callback DefaultSetter
5 | * @param {import('metalsmith').File} file
6 | * @param {Object} metadata
7 | */
8 |
9 | /**
10 | * @typedef {Object} DefaultsSet
11 | * @property {string|string[]} [pattern="**"] 1 or more glob patterns to match files. Defaults to `'**'` (all).
12 | * @property {Object} [defaults={}] an object whose keys will be set as file metadata keys
13 | * @property {'keep'|'overwrite'} [strategy="keep"] Strategy to handle setting defaults to keys that are aleady defined. Defaults to `'keep'`
14 | */
15 |
16 | /** @type {DefaultsSet} */
17 | const defaultDefaultsSet = {
18 | defaults: {},
19 | strategy: 'keep',
20 | pattern: '**'
21 | }
22 |
23 | /**
24 | * Set `defaults` to file metadata matching `pattern`'s.
25 | *
26 | * @param {DefaultsSet|DefaultsSet[]} options an array of defaults sets to add to files matched by pattern
27 | * @return {import('metalsmith').Plugin}
28 | *
29 | * @example
30 | * metalsmith.use(defaultValues({
31 | pattern: 'posts/*.md',
32 | defaults: {
33 | layout: 'post.hbs',
34 | draft: false,
35 | date(post) {
36 | return post.stats.ctime
37 | }
38 | }
39 | }))
40 | **/
41 |
42 | function defaultValues(options) {
43 | return function defaultValues(files, metalsmith, done) {
44 | const debug = metalsmith.debug('@metalsmith/default-values')
45 | if (!Array.isArray(options) && typeof options === 'object' && options !== null) {
46 | options = [options]
47 | }
48 | debug('Running with options: %O ', options)
49 | const defaultSets = (options || []).map((defaultsSet) => Object.assign({}, defaultDefaultsSet, defaultsSet))
50 |
51 | // Loop through configurations
52 | defaultSets.forEach(function ({ pattern, defaults, strategy }) {
53 | const matches = metalsmith.match(pattern, Object.keys(files))
54 | const defaultsEntries = Object.entries(defaults)
55 | debug.info('Matched %s files to pattern "%s": %o', matches.length, pattern, matches)
56 | if (matches.length) {
57 | const setDefaults = getDefaultsSetter(defaultsEntries, strategy)
58 | matches.forEach((file) => {
59 | const changed = setDefaults(files[file], metalsmith.metadata())
60 | debug.info('Values set for file "%s": %O', file, changed)
61 | })
62 | } else {
63 | debug.warn('No matches for pattern "%s"', pattern)
64 | }
65 | })
66 |
67 | done()
68 | }
69 | }
70 |
71 | export default defaultValues
72 |
--------------------------------------------------------------------------------
/src/set_defaults.js:
--------------------------------------------------------------------------------
1 | import { Buffer } from 'buffer'
2 | import get from 'dlv'
3 | import { dset as set } from 'dset'
4 |
5 | /**
6 | * Sets defaults for object values
7 | * @param {Array>} defaults
8 | * @param {'keep'|'overwrite'} strategy
9 | * @return {import('.').DefaultSetter} Takes an object and sets defaults
10 | */
11 | function set_defaults(defaults, strategy) {
12 | return (item, context) => {
13 | const delta = {}
14 | defaults.forEach(([key, defaultValue]) => {
15 | const value = get(item, key)
16 | if (
17 | strategy === 'overwrite' ||
18 | value === void 0 ||
19 | value === null ||
20 | (Buffer.isBuffer(value) && value.toString().trim().length === 0)
21 | ) {
22 | if (typeof defaultValue === 'function') defaultValue = defaultValue(item, context)
23 | if (Buffer.isBuffer(value) && !Buffer.isBuffer(defaultValue)) defaultValue = Buffer.from(defaultValue)
24 | set(item, key, defaultValue)
25 | set(delta, key, defaultValue)
26 | }
27 | })
28 | return delta
29 | }
30 | }
31 |
32 | export default set_defaults
33 |
--------------------------------------------------------------------------------
/test/fixture/file1:
--------------------------------------------------------------------------------
1 | ---
2 | existing_key: yes
3 | ---
4 | Hello world
--------------------------------------------------------------------------------
/test/fixture/file2:
--------------------------------------------------------------------------------
1 | ---
2 | existing_key: yes
3 | default_val: false
4 | ---
--------------------------------------------------------------------------------
/test/fixture/func:
--------------------------------------------------------------------------------
1 | ---
2 | funcDefault: 1
3 | ---
--------------------------------------------------------------------------------
/test/fixture/nested/index:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/metalsmith/default-values/8f138492ee59238e78979f2a6fbd6efa02857b3a/test/fixture/nested/index
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node, mocha */
2 | import { fileURLToPath } from 'node:url'
3 | import { readFileSync } from 'node:fs'
4 | import assert from 'node:assert'
5 | import path from 'node:path'
6 |
7 | import Metalsmith from 'metalsmith'
8 | import plugin from '../src/index.js'
9 |
10 | const __dirname = path.dirname(fileURLToPath(import.meta.url))
11 | const { name } = JSON.parse(readFileSync(path.resolve(__dirname, '../package.json')))
12 |
13 | let set_defaults_lib
14 |
15 | function relevantProps(expected, files) {
16 | return Object.keys(expected).reduce((acc, filename) => {
17 | acc[filename] = {}
18 | Object.keys(expected[filename]).forEach((prop) => {
19 | acc[filename][prop] = files[filename] && files[filename][prop]
20 | if (acc[filename][prop] instanceof Buffer) acc[filename][prop] = acc[filename][prop].toString()
21 | })
22 | return acc
23 | }, {})
24 | }
25 |
26 | describe('@metalsmith/default-values', function () {
27 | before(function (done) {
28 | import('../src/set_defaults.js').then((imported) => {
29 | set_defaults_lib = imported.default
30 | done()
31 | })
32 | })
33 |
34 | it('should export a named plugin function matching package.json name', function () {
35 | const namechars = name.split('/')[1]
36 | const camelCased = namechars.split('').reduce((str, char, i) => {
37 | str += namechars[i - 1] === '-' ? char.toUpperCase() : char === '-' ? '' : char
38 | return str
39 | }, '')
40 | assert.strictEqual(plugin().name, camelCased)
41 | })
42 |
43 | it('should not crash the metalsmith build when using default options', function (done) {
44 | Metalsmith(__dirname)
45 | .source('.')
46 | .env('DEBUG', process.env.DEBUG)
47 | .use(plugin())
48 | .process((err) => {
49 | if (err) done(err)
50 | else done()
51 | })
52 | })
53 | it('sets a key when not present', function (done) {
54 | const ms = Metalsmith(__dirname)
55 | .source('./fixture')
56 | .env('DEBUG', process.env.DEBUG)
57 | .use(
58 | plugin([
59 | {
60 | defaults: { default_val: true }
61 | },
62 | {
63 | pattern: 'file2',
64 | defaults: { another_default: 'hello' }
65 | }
66 | ])
67 | )
68 | const expected = {
69 | file1: {
70 | existing_key: 'yes',
71 | default_val: true
72 | },
73 | file2: {
74 | existing_key: 'yes',
75 | default_val: false,
76 | another_default: 'hello'
77 | }
78 | }
79 |
80 | ms.process((err, files) => {
81 | assert.ifError(err, 'Has not errored')
82 | assert.deepStrictEqual(relevantProps(expected, files), expected)
83 | done()
84 | })
85 | })
86 |
87 | it('logs a warning when no files match a pattern', function (done) {
88 | let warning
89 | function Debugger() {}
90 | Debugger.warn = (msg) => {
91 | warning = msg
92 | }
93 | Debugger.info = () => {}
94 |
95 | const msStub = {
96 | match() {
97 | return []
98 | },
99 | debug() {
100 | return Debugger
101 | }
102 | }
103 |
104 | plugin([
105 | {
106 | pattern: 'non-existant',
107 | defaults: { wontbeset: 1 }
108 | }
109 | ])({}, msStub, () => {
110 | try {
111 | assert.strictEqual(warning, 'No matches for pattern "%s"')
112 | } catch (err) {
113 | done(err)
114 | }
115 | done()
116 | })
117 | })
118 |
119 | it('supports defining a function to return default value', function (done) {
120 | const ms = Metalsmith(__dirname)
121 | .source('./fixture')
122 | .env('DEBUG', process.env.DEBUG)
123 | .use(
124 | plugin([
125 | {
126 | pattern: 'func',
127 | defaults: {
128 | computedDefault({ funcDefault }) {
129 | return funcDefault + 100
130 | }
131 | }
132 | }
133 | ])
134 | )
135 | const expected = {
136 | func: {
137 | funcDefault: 1,
138 | computedDefault: 101
139 | }
140 | }
141 |
142 | ms.process((err, files) => {
143 | if (err) done(err)
144 | try {
145 | assert.deepStrictEqual(relevantProps(expected, { func: files.func }), expected)
146 | done()
147 | } catch (err) {
148 | done(err)
149 | }
150 | })
151 | })
152 |
153 | it('allows passing a single defaults set as shorthand', function (done) {
154 | const ms = Metalsmith(__dirname)
155 | .source('./fixture')
156 | .env('DEBUG', process.env.DEBUG)
157 | .use(
158 | plugin({
159 | defaults: { all: 'ok' }
160 | })
161 | )
162 | const expected = {
163 | file1: { all: 'ok' },
164 | file2: { all: 'ok' },
165 | func: { all: 'ok' }
166 | }
167 |
168 | expected[path.join('nested', 'index')] = { all: 'ok' }
169 |
170 | ms.process((err, files) => {
171 | if (err) done(err)
172 | try {
173 | assert.deepStrictEqual(relevantProps(expected, files), expected)
174 | done()
175 | } catch (err) {
176 | done(err)
177 | }
178 | })
179 | })
180 |
181 | it('allows setting default contents when empty buffer', function (done) {
182 | const ms = Metalsmith(__dirname)
183 | .source('./fixture')
184 | .env('DEBUG', process.env.DEBUG)
185 | .use(
186 | plugin({
187 | pattern: 'file*',
188 | defaults: { contents: Buffer.from('Lorem ipsum') }
189 | })
190 | )
191 |
192 | ms.process((err, files) => {
193 | if (err) done(err)
194 | try {
195 | const expected = {
196 | file1: { contents: 'Hello world' },
197 | file2: { contents: 'Lorem ipsum' }
198 | }
199 | assert.deepStrictEqual(relevantProps(expected, files), expected)
200 | done()
201 | } catch (err) {
202 | done(err)
203 | }
204 | })
205 | })
206 |
207 | // this is essential for CLI flows to be able to set default values in JSON
208 | it('converts non-buffer defaults to buffers if the target key is already a buffer', function (done) {
209 | const ms = Metalsmith(__dirname)
210 | .source('./fixture')
211 | .env('DEBUG', process.env.DEBUG)
212 | .use(
213 | plugin({
214 | pattern: 'file2',
215 | defaults: { contents: 'Lorem ipsum' }
216 | })
217 | )
218 |
219 | ms.process((err, files) => {
220 | if (err) done(err)
221 | try {
222 | assert(Buffer.isBuffer(files.file2.contents))
223 | assert.strictEqual(files.file2.contents.toString(), 'Lorem ipsum')
224 | done()
225 | } catch (err) {
226 | done(err)
227 | }
228 | })
229 | })
230 |
231 | describe('set_defaults', function () {
232 | it('initialisation returns a function', function () {
233 | const actual = set_defaults_lib()
234 |
235 | assert.strictEqual(typeof actual, 'function', 'Function returned after initialisation')
236 | })
237 |
238 | it('sets a key when not present', function () {
239 | const defaults = {
240 | default_val: true
241 | }
242 | const set_defaults = set_defaults_lib(Object.entries(defaults))
243 | assert.strictEqual(typeof set_defaults, 'function', 'Function returned after initialisation')
244 | const actual = set_defaults({
245 | initial: 'yes'
246 | })
247 | const expected = {
248 | default_val: true
249 | }
250 |
251 | assert.deepStrictEqual(actual, expected)
252 | })
253 |
254 | it('overwrites a key when strategy is "overwrite"', function () {
255 | const defaults = {
256 | initial: 'no',
257 | default_val: true
258 | }
259 | const set_defaults = set_defaults_lib(Object.entries(defaults), 'overwrite')
260 | assert.strictEqual(typeof set_defaults, 'function', 'Function returned after initialisation')
261 | const actual = set_defaults({
262 | initial: 'yes'
263 | })
264 | const expected = {
265 | initial: 'no',
266 | default_val: true
267 | }
268 |
269 | assert.deepStrictEqual(actual, expected)
270 | })
271 |
272 | it('sets a default computed from additional metadata and returns the delta', function () {
273 | const defaults = {
274 | default_val: true,
275 | buildVersion(file, globalMeta) {
276 | return globalMeta.buildVersion
277 | }
278 | }
279 | const set_defaults = set_defaults_lib(Object.entries(defaults))
280 | const actual = set_defaults({ initial: 'yes' }, { buildVersion: '1.0.0' })
281 | const expected = {
282 | default_val: true,
283 | buildVersion: '1.0.0'
284 | }
285 |
286 | assert.deepStrictEqual(actual, expected)
287 | })
288 | })
289 |
290 | // this is essential for CLI flows to be able to set default values in JSON
291 | it('sets a default at a key path ', function () {
292 | const defaults = {
293 | 'some.nested.def.value': true
294 | }
295 | const set_defaults = set_defaults_lib(Object.entries(defaults))
296 | const actual = set_defaults({ initial: 'yes' })
297 | const expected = {
298 | some: {
299 | nested: {
300 | def: {
301 | value: true
302 | }
303 | }
304 | }
305 | }
306 |
307 | assert.deepStrictEqual(actual, expected)
308 | })
309 | })
310 |
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | import Metalsmith from 'metalsmith'
2 | import defaultValues from '../lib'
3 |
4 | type File = Metalsmith.File<{
5 | layout?: string
6 | draft?: boolean
7 | }>
8 |
9 | defaultValues({
10 | strategy: 'overwrite',
11 | pattern: '**/*.html',
12 | defaults: {
13 | excerpt(file) {
14 | return file.contents.toString().slice(0, 250) + '...'
15 | },
16 | buildVersion(_, meta) {
17 | return meta.buildVersion
18 | },
19 | draft(file) {
20 | return file.draft
21 | },
22 | layout: 'default.njk'
23 | }
24 | })
--------------------------------------------------------------------------------