Skip to content

Commit

Permalink
fix: Deeply merge configuration schema defaults (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
about-code committed Dec 5, 2020
1 parent 3a8b108 commit 1583ff0
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 58 deletions.
9 changes: 8 additions & 1 deletion bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const optsDefault = Object
return obj;
}, {});

let opts = Object.assign(optsDefault, optsFile);
let opts = optsFile;

// --deep
if (argv.deep) {
Expand All @@ -96,6 +96,13 @@ if (argv.shallow) {
proc.exit(1);
}
}
opts = merge(optsDefault, opts, {
clone: false
, arrayMerge: (_default, curOpts) => {
return curOpts && curOpts.length > 0 ? curOpts : _default;
}
});

// Resolve 2nd arg paths relative to 1st arg paths...
opts.baseDir = path.resolve(confDir, opts.baseDir);
opts.outDir = path.resolve(opts.baseDir, opts.outDir);
Expand Down
30 changes: 18 additions & 12 deletions conf.schema.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://raw.githubusercontent.com/about-code/glossarify-md/v3.4.0/conf.schema.json",
"$id": "https://raw.githubusercontent.com/about-code/glossarify-md/v5.0.0/conf.schema.json",
"type": "object",
"properties": {
"baseDir": {
Expand Down Expand Up @@ -33,7 +33,9 @@
"generateFiles": {
"description": "File generation options.",
"$ref": "#/$defs/GenerateFilesOpts",
"default": {}
"default": {
"listOf": []
}
},
"glossaries": {
"description": "An array of glossaries. Allows for different kinds of glossaries and definitions.",
Expand Down Expand Up @@ -64,12 +66,16 @@
"indexing": {
"description": "Path or glob patterns of files to include for linking to glossaries.",
"$ref": "#/$defs/IndexingOpts",
"default": {}
"default": {
"groupByHeadingDepth": 6
}
},
"i18n": {
"description": "Internationalization and collation options. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator/Collator.",
"$ref": "#/$defs/IntlOpts",
"default": {}
"default": {
"locale": "en"
}
},
"keepRawFiles": {
"description": "Glob patterns for (markdown) files to copy from 'baseDir' to 'outDir' but to ignore by the linker. Non-markdown files will be ignored anyways.",
Expand Down Expand Up @@ -121,8 +127,7 @@
"indexFile": {
"description": "Generate a file with a list of glossary terms and where they have been used.",
"type": "object",
"$ref": "#/$defs/IndexFileOpts",
"default": {}
"$ref": "#/$defs/IndexFileOpts"
},
"listOf": {
"description": "Generate an arbitrary list of links into your documents. For example, to generate a List of code samples configure a class 'listing' and add anchors <a class='listing' title='My Sample 1' id='sample-1'/> before your sample code blocks.",
Expand All @@ -134,14 +139,12 @@
"listOfFigures": {
"description": "Generate a file with a list of figures and where they can be found.",
"type": "object",
"$ref": "#/$defs/IndexFileOpts",
"default": ""
"$ref": "#/$defs/IndexFileOpts"
},
"listOfTables": {
"description": "Generate a file with a list of tables and where they can be found.",
"type": "object",
"$ref": "#/$defs/IndexFileOpts",
"default": ""
"$ref": "#/$defs/IndexFileOpts"
}
}
},
Expand Down Expand Up @@ -169,8 +172,7 @@
"description": "Level of detail by which to group occurrences of terms or syntactic elements in generated files (Range [min, max]: [0, 6]). For example, use 0 to not group at all; 1 to group things at the level of document titles, etc. Configures the indexer. The option affects any files generated from the internal AST node index.",
"type": "number",
"minimum": 0,
"maximum": 6,
"default": 0
"maximum": 6
}
}
},
Expand Down Expand Up @@ -251,6 +253,10 @@
"termsFile": {
"description": "File where to write term book to. Enables testing the term extraction results of the 'terminator' component.",
"type": "string"
},
"effectiveConfFile": {
"description": "File where to write the configuration that is applied effectively after merging config file, cli opts and schema defaults.",
"type": "string"
}
}
}
Expand Down
25 changes: 1 addition & 24 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,6 @@ function prepare(context) {
opts.outDir
= toForwardSlash(path.resolve(baseDir, opts.outDir));

if (! opts.indexing ) {
opts.indexing = {};
}
if (opts.indexing.groupByHeadingDepth === undefined) {
opts.indexing.groupByHeadingDepth = 6;
}
if (! opts.generateFiles ) {
opts.generateFiles = {};
}
if (! opts.generateFiles.listOf) {
opts.generateFiles.listOf = [];
}
if (opts.generateFiles.listOfFigures) {
opts.generateFiles.listOfFigures = Object.assign({ class: "figure", title: "Figures"}, opts.generateFiles.listOfFigures);
opts.generateFiles.listOf.push(opts.generateFiles.listOfFigures);
Expand All @@ -85,18 +73,7 @@ function prepare(context) {
opts.generateFiles.listOfTables = Object.assign({ class: "table", title: "Tables"}, opts.generateFiles.listOfTables);
opts.generateFiles.listOf.push(opts.generateFiles.listOfTables);
}
if (! opts.glossaries ) {
opts.glossaries = {};
}
if (! opts.i18n ) {
opts.i18n = {};
}
if (! opts.i18n.locale) {
opts.i18n.locale = "en";
}
if (! opts.i18n ) {
opts.i18n = {};
}

collator.init(opts.i18n);
return Promise.resolve(context);
}
Expand Down
14 changes: 10 additions & 4 deletions lib/writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const remark_autolink_headings = require("remark-autolink-headings");
const remark_footnotes = require("remark-footnotes");
const remark_stringify = require("remark-stringify");
const {TermDefinition} = require("./ast/with/term-definition");
const {toSystemSlash} = require("./path/tools");
const {toSystemSlash, toReproducablePath} = require("./path/tools");
const {getIndex} = require("./indexer");
const {getAST: getIndexerAST} = require("./index/terms");
const {getAST: getListOfAnchorsAST} = require("./index/anchors");
Expand Down Expand Up @@ -167,9 +167,15 @@ api.writeReport = function(context) {
*/
api.writeTestOutput = function (context) {
const {report, opts} = context;
const {termsFile, reportsFile} = opts.dev;
const {termsFile, reportsFile, effectiveConfFile} = opts.dev;
const indexedTerms = getIndex("terms")[0];
const promises = [];
if (effectiveConfFile) {
const snapshot = Object.assign({}, opts);
snapshot.baseDir = toReproducablePath(opts.baseDir, "{CWD}");
snapshot.outDir = toReproducablePath(opts.outDir, "{CWD}");
promises.push(writeTextFile(context, effectiveConfFile, JSON.stringify(snapshot, null, 2)));
}
if (termsFile && indexedTerms) {
// Important! Write terms in defined order to get reliable diff.
const terms = indexedTerms
Expand All @@ -185,11 +191,11 @@ api.writeTestOutput = function (context) {
.then(() => context);
};

function writeTextFile(context, filename, data) {
function writeTextFile(context, filename, strData) {
const {baseDir} = context.opts;
const filename_ = toSystemSlash(path.resolve(baseDir, filename));
return new Promise((resolve, reject) => {
const output = `${data}`
const output = `${strData}`
.replace("\r", "") /* [1] */
+ "\n"; /* [2] */

Expand Down
13 changes: 13 additions & 0 deletions test/input/config-cli/deep-defaults/glossarify-md.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../conf.schema.json",
"baseUrl": "file://localhost",
"baseDir": ".",
"outDir": "../../../output-actual/config-cli/deep-defaults",
"includeFiles": ["."],
"indexing": {},
"glossaries": [],
"linking": "relative",
"dev": {
"effectiveConfFile": "./glossarify-md-effective.conf.json"
}
}
44 changes: 44 additions & 0 deletions test/input/config-cli/deep-defaults/glossary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Glossary

## Test Case

- GIVEN a configuration schema WITH a complex option `glossaries` WITH a complex `default` value

*./node_modules/glossarify-md/conf.schema.json*:
~~~json
{
"$id": "...",
"properties": {
"glossaries": {
"default": [
{ "file": "./glossary.md", "termHint": ""}
],
"...": "...",
},
"...": "..."
}
}
~~~
- AND a configuration file with an incomplete *partial* definition of the complex object `glossaries`

*Some partial user configuration*
~~~json
{
"$schema": "./node_modules/glossarify-md/conf.schema.json",
"glossaries": [],
"...": "..."
}
~~~

- THEN the default values MUST be *deep-merged* into the configuration file such that the actual configuration applied is identical to a configuration file

*Expected config to apply*
~~~json
{
"$schema": "./node_modules/glossarify-md/conf.schema.json",
"glossaries": [
{ "file": "./glossary.md", "termHint": ""}
],
"...": "..."
}
~~~
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"baseDir": "{CWD}/output-actual/config-cli/deep-defaults",
"baseUrl": "file://localhost",
"excludeFiles": [
"node_modules",
".git"
],
"force": false,
"generateFiles": {
"listOf": []
},
"glossaries": [
{
"file": "./glossary.md",
"termHint": "",
"basePath": "/{CWD}/output-actual/config-cli/deep-defaults/glossary.md",
"outPath": "/{CWD}/output-actual/config-cli/deep-defaults/glossary.md"
}
],
"ignoreCase": false,
"includeFiles": [
"."
],
"indexing": {
"groupByHeadingDepth": 6
},
"i18n": {
"locale": "en"
},
"keepRawFiles": [],
"linking": "relative",
"outDir": "{CWD}/output-actual/config-cli/deep-defaults",
"outDirDropOld": true,
"reportNotMentioned": false,
"dev": {
"effectiveConfFile": "./glossarify-md-effective.conf.json"
},
"$schema": "../../../../conf.schema.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../conf.schema.json",
"baseUrl": "file://localhost",
"baseDir": ".",
"outDir": "../../../output-actual/config-cli/deep-defaults",
"includeFiles": ["."],
"indexing": {},
"glossaries": [],
"linking": "relative",
"dev": {
"effectiveConfFile": "./glossarify-md-effective.conf.json"
}
}
48 changes: 48 additions & 0 deletions test/output-expected/config-cli/deep-defaults/glossary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# [Glossary](#glossary)

## [Test Case](#test-case)

- GIVEN a configuration schema WITH a complex option `glossaries` WITH a complex `default` value

_./node_modules/glossarify-md/conf.schema.json_:

```json
{
"$id": "...",
"properties": {
"glossaries": {
"default": [
{ "file": "./glossary.md", "termHint": ""}
],
"...": "...",
},
"...": "..."
}
}
```

- AND a configuration file with an incomplete _partial_ definition of the complex object `glossaries`

_Some partial user configuration_

```json
{
"$schema": "./node_modules/glossarify-md/conf.schema.json",
"glossaries": [],
"...": "..."
}
```

- THEN the default values MUST be _deep-merged_ into the configuration file such that the actual configuration applied is identical to a configuration file

_Expected config to apply_

```json
{
"$schema": "./node_modules/glossarify-md/conf.schema.json",
"glossaries": [
{ "file": "./glossary.md", "termHint": ""}
],
"...": "..."
}
```
35 changes: 18 additions & 17 deletions test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,24 @@
"test_20": "npx . --shallow \"{'baseDir':'./input/config-cli/arg-config-skip', 'outDir':'../../../output-actual/config-cli/arg-config-skip', 'includeFiles':['.'], 'glossaries':[{'file':'./glossary.md'}] }\"",
"test_21": "npx . --config ./input/config-cli/arg-shallow/glossarify-md.conf.json --shallow \"{'baseUrl': 'cli://localhost', 'linking': 'absolute', 'glossaries':[{'file':'./glossary2.md'}] }\"",
"test_22": "npx . --config ./input/config-cli/arg-deep/glossarify-md.conf.json --deep \"{'glossaries':[{'file':'./glossary2.md'}]}\"",
"test_23": "npx . --config ./input/config-indexFile/glossary-in-subdir/glossarify-md.conf.json",
"test_24": "npx . --config ./input/config-indexFile/index-in-subdir/glossarify-md.conf.json",
"test_25": "npx . --config ./input/config-indexFile/term-link-to-section/glossarify-md.conf.json",
"test_26": "npx . --config ./input/config-indexFile/multiple-glossaries/glossarify-md.conf.json",
"test_27": "npx . --config ./input/config-indexFile/config-title/glossarify-md.conf.json",
"test_28": "npx . --config ./input/count-term-occurrences/glossarify-md.conf.json",
"test_29": "npx . --config ./input/glossary-crosslinks/glossarify-md.conf.json",
"test_30": "npx . --config ./input/config-indexing/groupByHeadingDepth-missing/glossarify-md.conf.json",
"test_31": "npx . --config ./input/config-indexing/groupByHeadingDepth-0/glossarify-md.conf.json",
"test_32": "npx . --config ./input/config-indexing/groupByHeadingDepth-1/glossarify-md.conf.json",
"test_33": "npx . --config ./input/config-indexing/groupByHeadingDepth-2/glossarify-md.conf.json",
"test_34": "npx . --config ./input/config-listOfFigures/image-reference/glossarify-md.conf.json",
"test_35": "npx . --config ./input/config-listOfFigures/option-title-missing/glossarify-md.conf.json",
"test_36": "npx . --config ./input/config-listOfFigures/option-with-listOf-combined/glossarify-md.conf.json",
"test_37": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json",
"test_38": "npx . --config ./input/config-listOf/glossarify-md.conf.json",
"test_39": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json",
"test_23": "npx . --config ./input/config-cli/deep-defaults/glossarify-md.conf.json",
"test_24": "npx . --config ./input/config-indexFile/glossary-in-subdir/glossarify-md.conf.json",
"test_25": "npx . --config ./input/config-indexFile/index-in-subdir/glossarify-md.conf.json",
"test_26": "npx . --config ./input/config-indexFile/term-link-to-section/glossarify-md.conf.json",
"test_27": "npx . --config ./input/config-indexFile/multiple-glossaries/glossarify-md.conf.json",
"test_28": "npx . --config ./input/config-indexFile/config-title/glossarify-md.conf.json",
"test_29": "npx . --config ./input/count-term-occurrences/glossarify-md.conf.json",
"test_30": "npx . --config ./input/glossary-crosslinks/glossarify-md.conf.json",
"test_31": "npx . --config ./input/config-indexing/groupByHeadingDepth-missing/glossarify-md.conf.json",
"test_32": "npx . --config ./input/config-indexing/groupByHeadingDepth-0/glossarify-md.conf.json",
"test_33": "npx . --config ./input/config-indexing/groupByHeadingDepth-1/glossarify-md.conf.json",
"test_34": "npx . --config ./input/config-indexing/groupByHeadingDepth-2/glossarify-md.conf.json",
"test_35": "npx . --config ./input/config-listOfFigures/image-reference/glossarify-md.conf.json",
"test_36": "npx . --config ./input/config-listOfFigures/option-title-missing/glossarify-md.conf.json",
"test_37": "npx . --config ./input/config-listOfFigures/option-with-listOf-combined/glossarify-md.conf.json",
"test_38": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json",
"test_39": "npx . --config ./input/config-listOf/glossarify-md.conf.json",
"test_40": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json",
"postsuite": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js",
"postat": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js",
"new-baseline": "rm -r ./output-expected && mv ./output-actual ./output-expected",
Expand Down

0 comments on commit 1583ff0

Please sign in to comment.