spec-up-t 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +13 -0
- package/assets/compiled/body.js +18 -12
- package/assets/compiled/head.css +8 -6
- package/assets/css/collapse-definitions.css +0 -1
- package/assets/css/counter.css +10 -22
- package/assets/css/create-pdf.css +4 -2
- package/assets/css/create-term-filter.css +4 -4
- package/assets/css/definition-buttons-container.css +60 -0
- package/assets/css/{pdf-download.css → download-pdf-docx.css} +9 -5
- package/assets/css/insert-trefs.css +7 -0
- package/assets/css/sidebar-toc.css +2 -1
- package/assets/css/terms-and-definitions.css +73 -22
- package/assets/js/add-href-to-snapshot-link.js +16 -9
- package/assets/js/addAnchorsToTerms.js +2 -2
- package/assets/js/charts.js +10 -0
- package/assets/js/collapse-definitions.js +13 -2
- package/assets/js/collapse-meta-info.js +11 -9
- package/assets/js/definition-button-container-utils.js +82 -0
- package/assets/js/download-pdf-docx.js +68 -0
- package/assets/js/edit-term-buttons.js +77 -20
- package/assets/js/github-issues.js +35 -0
- package/assets/js/github-repo-info.js +144 -0
- package/assets/js/highlight-heading-plus-sibling-nodes.test.js +18 -0
- package/assets/js/insert-trefs.js +62 -13
- package/assets/js/mermaid-diagrams.js +11 -0
- package/assets/js/terminology-section-utility-container/README.md +107 -0
- package/assets/js/terminology-section-utility-container/create-alphabet-index.js +17 -0
- package/assets/js/{create-term-filter.js → terminology-section-utility-container/create-term-filter.js} +11 -44
- package/assets/js/terminology-section-utility-container/hide-show-utility-container.js +21 -0
- package/assets/js/terminology-section-utility-container/search.js +203 -0
- package/assets/js/terminology-section-utility-container.js +203 -0
- package/assets/js/tooltips.js +283 -0
- package/config/asset-map.json +26 -18
- package/index.js +57 -390
- package/package.json +5 -2
- package/src/add-remove-xref-source.js +20 -21
- package/src/collect-external-references.js +8 -337
- package/src/collect-external-references.test.js +440 -33
- package/src/configure.js +8 -109
- package/src/create-docx.js +7 -6
- package/src/create-pdf.js +15 -14
- package/src/freeze-spec-data.js +46 -0
- package/src/git-info.test.js +76 -0
- package/src/health-check/destination-gitignore-checker.js +5 -3
- package/src/health-check/external-specs-checker.js +5 -4
- package/src/health-check/specs-configuration-checker.js +2 -1
- package/src/health-check/term-references-checker.js +5 -3
- package/src/health-check/terms-intro-checker.js +2 -1
- package/src/health-check/tref-term-checker.js +8 -7
- package/src/health-check.js +8 -7
- package/src/init.js +3 -2
- package/src/install-from-boilerplate/add-gitignore-entries.js +3 -2
- package/src/install-from-boilerplate/add-scripts-keys.js +5 -4
- package/src/install-from-boilerplate/boilerplate/.github/workflows/menu.yml +74 -97
- package/src/install-from-boilerplate/boilerplate/README.md +1 -1
- package/src/install-from-boilerplate/boilerplate/spec/example-markup-in-markdown.md +1 -1
- package/src/install-from-boilerplate/boilerplate/spec/spec-head.md +2 -2
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/composability.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/compost.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/fertilizer.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/mulch.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/pruning.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/seedling.md +3 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/soil.md +11 -0
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/watering.md +3 -0
- package/src/install-from-boilerplate/boilerplate/specs.json +24 -10
- package/src/install-from-boilerplate/config-scripts-keys.js +3 -3
- package/src/install-from-boilerplate/config-system-files.js +0 -1
- package/src/install-from-boilerplate/copy-boilerplate.js +2 -1
- package/src/install-from-boilerplate/copy-system-files.js +4 -3
- package/src/install-from-boilerplate/custom-update.js +12 -1
- package/src/install-from-boilerplate/help.txt +1 -1
- package/src/install-from-boilerplate/menu.sh +6 -6
- package/src/json-key-validator.js +17 -11
- package/src/markdown-it/README.md +207 -0
- package/src/markdown-it/definition-lists.js +397 -0
- package/src/markdown-it/index.js +83 -0
- package/src/markdown-it/link-enhancement.js +98 -0
- package/src/markdown-it/plugins.js +118 -0
- package/src/markdown-it/table-enhancement.js +97 -0
- package/src/markdown-it/template-tag-syntax.js +152 -0
- package/src/parsers/index.js +16 -0
- package/src/parsers/spec-parser.js +152 -0
- package/src/parsers/spec-parser.test.js +109 -0
- package/src/parsers/template-tag-parser.js +277 -0
- package/src/parsers/template-tag-parser.test.js +107 -0
- package/src/pipeline/configuration/configure-starterpack.js +200 -0
- package/src/{create-external-specs-list.js → pipeline/configuration/create-external-specs-list.js} +13 -12
- package/src/{create-term-index.js → pipeline/configuration/create-term-index.js} +19 -18
- package/src/{create-versions-index.js → pipeline/configuration/create-versions-index.js} +4 -3
- package/src/{insert-term-index.js → pipeline/configuration/insert-term-index.js} +2 -2
- package/src/pipeline/configuration/prepare-spec-configuration.js +70 -0
- package/src/pipeline/parsing/apply-markdown-it-extensions.js +35 -0
- package/src/pipeline/parsing/create-markdown-parser.js +94 -0
- package/src/pipeline/parsing/create-markdown-parser.test.js +49 -0
- package/src/{html-dom-processor.js → pipeline/postprocessing/definition-list-postprocessor.js} +69 -10
- package/src/{escape-handler.js → pipeline/preprocessing/escape-processor.js} +3 -1
- package/src/{fix-markdown-files.js → pipeline/preprocessing/normalize-terminology-markdown.js} +41 -31
- package/src/pipeline/references/collect-external-references.js +307 -0
- package/src/pipeline/references/external-references-service.js +231 -0
- package/src/pipeline/references/fetch-terms-from-index.js +198 -0
- package/src/pipeline/references/match-term.js +34 -0
- package/src/{collectExternalReferences/matchTerm.test.js → pipeline/references/match-term.test.js} +8 -2
- package/src/pipeline/references/process-xtrefs-data.js +94 -0
- package/src/pipeline/references/xtref-utils.js +166 -0
- package/src/pipeline/rendering/render-spec-document.js +146 -0
- package/src/pipeline/rendering/render-utils.js +154 -0
- package/src/utils/LOGGER.md +81 -0
- package/src/utils/{doesUrlExist.js → does-url-exist.js} +4 -3
- package/src/utils/fetch.js +5 -4
- package/src/utils/file-opener.js +3 -2
- package/src/utils/git-info.js +77 -0
- package/src/utils/logger.js +74 -0
- package/src/utils/regex-patterns.js +471 -0
- package/src/utils/regex-patterns.test.js +281 -0
- package/templates/template.html +56 -21
- package/assets/js/create-alphabet-index.js +0 -60
- package/assets/js/hide-show-utility-container.js +0 -16
- package/assets/js/index.js +0 -87
- package/assets/js/pdf-download.js +0 -46
- package/assets/js/search.js +0 -365
- package/src/collectExternalReferences/fetchTermsFromIndex.js +0 -284
- package/src/collectExternalReferences/matchTerm.js +0 -32
- package/src/collectExternalReferences/processXTrefsData.js +0 -108
- package/src/freeze.js +0 -90
- package/src/install-from-boilerplate/boilerplate/.github/workflows/fetch-and-push-xrefs.yml.old +0 -42
- package/src/install-from-boilerplate/boilerplate/.github/workflows/render-specs.yml +0 -47
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/term-1.md +0 -13
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/term-2.md +0 -3
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/term-3.md +0 -3
- package/src/install-from-boilerplate/boilerplate/spec/terms-definitions/term-4.md +0 -3
- package/src/markdown-it-extensions.js +0 -395
- package/src/references.js +0 -114
- /package/assets/css/{bootstrap.min.css → embedded-libraries/bootstrap.min.css} +0 -0
- /package/assets/css/{prism.css → embedded-libraries/prism.css} +0 -0
- /package/assets/css/{prism.dark.css → embedded-libraries/prism.dark.css} +0 -0
- /package/assets/css/{prism.default.css → embedded-libraries/prism.default.css} +0 -0
- /package/assets/js/{bootstrap.bundle.min.js → embedded-libraries/bootstrap.bundle.min.js} +0 -0
- /package/assets/js/{chart.js → embedded-libraries/chart.js} +0 -0
- /package/assets/js/{diff.min.js → embedded-libraries/diff.min.js} +0 -0
- /package/assets/js/{font-awesome.js → embedded-libraries/font-awesome.js} +0 -0
- /package/assets/js/{mermaid.js → embedded-libraries/mermaid.js} +0 -0
- /package/assets/js/{notyf.js → embedded-libraries/notyf.js} +0 -0
- /package/assets/js/{popper.js → embedded-libraries/popper.js} +0 -0
- /package/assets/js/{prism.dark.js → embedded-libraries/prism.dark.js} +0 -0
- /package/assets/js/{prism.default.js → embedded-libraries/prism.default.js} +0 -0
- /package/assets/js/{prism.js → embedded-libraries/prism.js} +0 -0
- /package/assets/js/{tippy.js → embedded-libraries/tippy.js} +0 -0
- /package/src/{escape-mechanism.js → pipeline/preprocessing/escape-placeholder-utils.js} +0 -0
- /package/src/utils/{isLineWithDefinition.js → is-line-with-definition.js} +0 -0
package/config/asset-map.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"head": {
|
|
3
3
|
"css": [
|
|
4
4
|
"assets/css/theme-vars.css",
|
|
5
|
-
"assets/css/bootstrap.min.css",
|
|
5
|
+
"assets/css/embedded-libraries/bootstrap.min.css",
|
|
6
6
|
"assets/css/custom-elements.css",
|
|
7
|
-
"assets/css/prism.css",
|
|
7
|
+
"assets/css/embedded-libraries/prism.css",
|
|
8
8
|
"assets/css/chart.css",
|
|
9
9
|
"assets/css/header-navbar.css",
|
|
10
10
|
"assets/css/sidebar-toc.css",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"assets/css/backToTop.css",
|
|
16
16
|
"assets/css/notyf.css",
|
|
17
17
|
"assets/css/collapse-definitions.css",
|
|
18
|
+
"assets/css/definition-buttons-container.css",
|
|
18
19
|
"assets/css/create-term-filter.css",
|
|
19
20
|
"assets/css/modal.css",
|
|
20
21
|
"assets/css/create-alphabet-index.css",
|
|
21
|
-
"assets/css/pdf-
|
|
22
|
+
"assets/css/download-pdf-docx.css",
|
|
22
23
|
"assets/css/loader.css",
|
|
23
24
|
"assets/css/external-links.css",
|
|
24
25
|
"assets/css/repo-issues.css",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"assets/css/horizontal-scroll-hint.css",
|
|
29
30
|
"assets/css/highlight-heading-plus-sibling-nodes.css",
|
|
30
31
|
"assets/css/counter.css",
|
|
32
|
+
"assets/css/insert-trefs.css",
|
|
31
33
|
"assets/css/index.css"
|
|
32
34
|
],
|
|
33
35
|
"js": [
|
|
@@ -41,41 +43,47 @@
|
|
|
41
43
|
"node_modules/markdown-it/dist/markdown-it.min.js",
|
|
42
44
|
"node_modules/markdown-it-deflist/dist/markdown-it-deflist.min.js",
|
|
43
45
|
"assets/js/declare-markdown-it.js",
|
|
44
|
-
"assets/js/prism.js",
|
|
45
|
-
"assets/js/mermaid.js",
|
|
46
|
-
"assets/js/chart.js",
|
|
47
|
-
"assets/js/font-awesome.js",
|
|
48
|
-
"assets/js/popper.js",
|
|
49
|
-
"assets/js/tippy.js",
|
|
50
|
-
"assets/js/diff.min.js",
|
|
46
|
+
"assets/js/embedded-libraries/prism.js",
|
|
47
|
+
"assets/js/embedded-libraries/mermaid.js",
|
|
48
|
+
"assets/js/embedded-libraries/chart.js",
|
|
49
|
+
"assets/js/embedded-libraries/font-awesome.js",
|
|
50
|
+
"assets/js/embedded-libraries/popper.js",
|
|
51
|
+
"assets/js/embedded-libraries/tippy.js",
|
|
52
|
+
"assets/js/embedded-libraries/diff.min.js",
|
|
51
53
|
"assets/js/edit-term-buttons.js",
|
|
52
|
-
"assets/js/hide-show-utility-container.js",
|
|
53
|
-
"assets/js/create-alphabet-index.js",
|
|
54
|
-
"assets/js/
|
|
54
|
+
"assets/js/terminology-section-utility-container/hide-show-utility-container.js",
|
|
55
|
+
"assets/js/terminology-section-utility-container/create-alphabet-index.js",
|
|
56
|
+
"assets/js/terminology-section-utility-container/create-term-filter.js",
|
|
57
|
+
"assets/js/terminology-section-utility-container/search.js",
|
|
58
|
+
"assets/js/terminology-section-utility-container.js",
|
|
55
59
|
"assets/js/highlightMenuItems.js",
|
|
56
60
|
"assets/js/collapsibleMenu.js",
|
|
57
61
|
"assets/js/backToTop.js",
|
|
58
62
|
"assets/js/addAnchorsToTerms.js",
|
|
59
63
|
"assets/js/copyAnchorToCliboard.js",
|
|
60
|
-
"assets/js/notyf.js",
|
|
64
|
+
"assets/js/embedded-libraries/notyf.js",
|
|
61
65
|
"assets/js/modal.js",
|
|
62
66
|
"assets/js/token-input.js",
|
|
63
|
-
"assets/js/pdf-
|
|
67
|
+
"assets/js/download-pdf-docx.js",
|
|
64
68
|
"assets/js/insert-trefs.js",
|
|
69
|
+
"assets/js/definition-button-container-utils.js",
|
|
65
70
|
"assets/js/collapse-definitions.js",
|
|
66
|
-
"assets/js/create-term-filter.js",
|
|
67
71
|
"assets/js/collapse-meta-info.js",
|
|
68
72
|
"assets/js/fix-last-dd.js",
|
|
69
73
|
"assets/js/add-href-to-snapshot-link.js",
|
|
70
74
|
"assets/js/adjust-font-size.js",
|
|
71
75
|
"assets/js/toggle-dense-info.js",
|
|
72
76
|
"assets/js/close-off-canvas-menu.js",
|
|
73
|
-
"assets/js/
|
|
77
|
+
"assets/js/github-repo-info.js",
|
|
78
|
+
"assets/js/github-issues.js",
|
|
79
|
+
"assets/js/mermaid-diagrams.js",
|
|
80
|
+
"assets/js/charts.js",
|
|
81
|
+
"assets/js/tooltips.js",
|
|
74
82
|
"assets/js/horizontal-scroll-hint.js",
|
|
75
83
|
"assets/js/add-bootstrap-classes-to-images.js",
|
|
76
84
|
"assets/js/image-full-size.js",
|
|
77
85
|
"assets/js/highlight-heading-plus-sibling-nodes.js",
|
|
78
|
-
"assets/js/bootstrap.bundle.min.js"
|
|
86
|
+
"assets/js/embedded-libraries/bootstrap.bundle.min.js"
|
|
79
87
|
]
|
|
80
88
|
}
|
|
81
89
|
}
|
package/index.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
const { initialize } = require('./src/init');
|
|
2
|
+
const Logger = require('./src/utils/logger');
|
|
2
3
|
|
|
3
4
|
module.exports = async function (options = {}) {
|
|
4
5
|
try {
|
|
5
|
-
|
|
6
|
+
const { initializeConfig } = require('./src/pipeline/configuration/prepare-spec-configuration.js');
|
|
7
|
+
let toc = '';
|
|
8
|
+
global.toc = '';
|
|
9
|
+
const setToc = (html) => { toc = html || ''; global.toc = toc; };
|
|
10
|
+
let {
|
|
11
|
+
config,
|
|
12
|
+
externalSpecsList,
|
|
13
|
+
template,
|
|
14
|
+
assets,
|
|
15
|
+
externalReferences,
|
|
16
|
+
references,
|
|
17
|
+
definitions,
|
|
18
|
+
specGroups,
|
|
19
|
+
noticeTitles
|
|
20
|
+
} = await initializeConfig(options);
|
|
21
|
+
|
|
22
|
+
global.definitions = definitions;
|
|
23
|
+
global.references = references;
|
|
24
|
+
global.specGroups = specGroups;
|
|
25
|
+
global.noticeTitles = noticeTitles;
|
|
6
26
|
|
|
7
27
|
const fs = require('fs-extra');
|
|
8
28
|
const path = require('path');
|
|
@@ -11,390 +31,37 @@ module.exports = async function (options = {}) {
|
|
|
11
31
|
const {
|
|
12
32
|
fetchExternalSpecs,
|
|
13
33
|
validateReferences,
|
|
14
|
-
findExternalSpecByKey
|
|
15
|
-
|
|
34
|
+
findExternalSpecByKey,
|
|
35
|
+
mergeXrefTermsIntoAllXTrefs
|
|
36
|
+
} = require('./src/pipeline/references/external-references-service.js');
|
|
16
37
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const {
|
|
21
|
-
createTermIndex();
|
|
22
|
-
|
|
23
|
-
const { processWithEscapes } = require('./src/escape-handler.js');
|
|
24
|
-
|
|
25
|
-
const { insertTermIndex } = require('./src/insert-term-index.js');
|
|
26
|
-
insertTermIndex();
|
|
38
|
+
const { processWithEscapes } = require('./src/pipeline/preprocessing/escape-processor.js');
|
|
39
|
+
const { processEscapedTags, restoreEscapedTags } = require('./src/pipeline/preprocessing/escape-placeholder-utils.js');
|
|
40
|
+
const { sortDefinitionTermsInHtml, fixDefinitionListStructure } = require('./src/pipeline/postprocessing/definition-list-postprocessor.js');
|
|
41
|
+
const { getGithubRepoInfo } = require('./src/utils/git-info.js');
|
|
27
42
|
|
|
28
43
|
const findPkgDir = require('find-pkg-dir');
|
|
29
44
|
const modulePath = findPkgDir(__dirname);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
let
|
|
46
|
-
let references = [];
|
|
47
|
-
let definitions = [];
|
|
48
|
-
let toc;
|
|
49
|
-
let specGroups = {};
|
|
50
|
-
let noticeTitles = {};
|
|
51
|
-
|
|
52
|
-
const noticeTypes = {
|
|
53
|
-
note: 1,
|
|
54
|
-
issue: 1,
|
|
55
|
-
example: 1,
|
|
56
|
-
warning: 1,
|
|
57
|
-
todo: 1
|
|
58
|
-
};
|
|
59
|
-
const spaceRegex = /\s+/g;
|
|
60
|
-
const specNameRegex = /^spec$|^spec-*\w+$/i;
|
|
61
|
-
const terminologyRegex = /^def$|^ref$|^xref|^tref$/i;
|
|
62
|
-
const specCorpus = fs.readJsonSync(modulePath + '/assets/compiled/refs.json');
|
|
63
|
-
const containers = require('markdown-it-container');
|
|
64
|
-
|
|
65
|
-
/*
|
|
66
|
-
`const md` is assigned an instance of the markdown-it parser configured with various plugins and extensions. This instance (md) is intended to be used later to parse and render Markdown strings.
|
|
67
|
-
|
|
68
|
-
The md function (which is an instance of the markdown-it parser) takes a Markdown string as its primary argument. It is called elsewhere as follows: `md.render(doc)`
|
|
69
|
-
*/
|
|
70
|
-
const md = require('markdown-it')({
|
|
71
|
-
html: true,
|
|
72
|
-
linkify: true,
|
|
73
|
-
typographer: true
|
|
74
|
-
})
|
|
75
|
-
/*
|
|
76
|
-
Configures a Markdown-it plugin by passing it an array of extension objects, each responsible for handling specific custom syntax in Markdown documents.
|
|
77
|
-
*/
|
|
78
|
-
.use(require('./src/markdown-it-extensions.js'), [
|
|
79
|
-
/*
|
|
80
|
-
The first extension (= the first configuration object = the first element of the array) focuses on terminology-related constructs, using a filter to match types against a regular expression (terminologyRegex).
|
|
81
|
-
*/
|
|
82
|
-
{
|
|
83
|
-
filter: type => type.match(terminologyRegex),
|
|
84
|
-
parse(token, type, primary) {
|
|
85
|
-
if (!primary) return;
|
|
86
|
-
if (type === 'def') {
|
|
87
|
-
definitions.push(token.info.args);
|
|
88
|
-
return token.info.args.reduce((acc, syn) => {
|
|
89
|
-
return `<span id="term:${syn.replace(spaceRegex, '-').toLowerCase()}">${acc}</span>`;
|
|
90
|
-
}, primary);
|
|
91
|
-
}
|
|
92
|
-
else if (type === 'xref') {
|
|
93
|
-
// Get the URL for the external specification reference, or default to '#' if not found
|
|
94
|
-
const externalSpec = findExternalSpecByKey(config, token.info.args[0]);
|
|
95
|
-
const url = externalSpec?.gh_page || '#';
|
|
96
|
-
|
|
97
|
-
const term = token.info.args[1].replace(spaceRegex, '-').toLowerCase();
|
|
98
|
-
return `<a class="x-term-reference term-reference" data-local-href="#term:${token.info.args[0]}:${term}"
|
|
99
|
-
href="${url}#term:${term}">${token.info.args[1]}</a>`;
|
|
100
|
-
}
|
|
101
|
-
else if (type === 'tref') {
|
|
102
|
-
// Support tref with optional alias: [[tref: spec, term, alias]]
|
|
103
|
-
const termName = token.info.args[1];
|
|
104
|
-
const alias = token.info.args[2]; // Optional alias
|
|
105
|
-
|
|
106
|
-
// Create IDs for both the original term and the alias to enable referencing by either
|
|
107
|
-
const termId = `term:${termName.replace(spaceRegex, '-').toLowerCase()}`;
|
|
108
|
-
const aliasId = alias ? `term:${alias.replace(spaceRegex, '-').toLowerCase()}` : '';
|
|
109
|
-
|
|
110
|
-
// Return the term structure similar to def, so it can be processed by markdown-it's definition list parser
|
|
111
|
-
if (aliasId && alias !== termName) {
|
|
112
|
-
return `<span class="transcluded-xref-term" id="${termId}"><span id="${aliasId}">${termName}</span></span>`;
|
|
113
|
-
} else {
|
|
114
|
-
return `<span class="transcluded-xref-term" id="${termId}">${termName}</span>`;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
references.push(primary);
|
|
119
|
-
return `<a class="term-reference" href="#term:${primary.replace(spaceRegex, '-').toLowerCase()}">${primary}</a>`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
/*
|
|
124
|
-
The second extension is designed for handling specification references.
|
|
125
|
-
*/
|
|
126
|
-
{
|
|
127
|
-
filter: type => type.match(specNameRegex),
|
|
128
|
-
parse(token, type, name) {
|
|
129
|
-
if (name) {
|
|
130
|
-
let _name = name.replace(spaceRegex, '-').toUpperCase();
|
|
131
|
-
let spec = specCorpus[_name] ||
|
|
132
|
-
specCorpus[_name.toLowerCase()] ||
|
|
133
|
-
specCorpus[name.toLowerCase()] ||
|
|
134
|
-
specCorpus[name];
|
|
135
|
-
if (spec) {
|
|
136
|
-
spec._name = _name;
|
|
137
|
-
let group = specGroups[type] = specGroups[type] || {};
|
|
138
|
-
token.info.spec = group[_name] = spec;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
render(token, type, name) {
|
|
143
|
-
if (name) {
|
|
144
|
-
let spec = token.info.spec;
|
|
145
|
-
if (spec) return `[<a class="spec-reference" href="#ref:${spec._name}">${spec._name}</a>]`;
|
|
146
|
-
}
|
|
147
|
-
else return renderRefGroup(type);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
])
|
|
151
|
-
.use(require('markdown-it-attrs'))
|
|
152
|
-
.use(require('markdown-it-chart').default)
|
|
153
|
-
.use(require('markdown-it-deflist'))
|
|
154
|
-
.use(require('markdown-it-references'))
|
|
155
|
-
.use(require('markdown-it-icons').default, 'font-awesome')
|
|
156
|
-
.use(require('markdown-it-ins'))
|
|
157
|
-
.use(require('markdown-it-mark'))
|
|
158
|
-
.use(require('markdown-it-textual-uml'))
|
|
159
|
-
.use(require('markdown-it-sub'))
|
|
160
|
-
.use(require('markdown-it-sup'))
|
|
161
|
-
.use(require('markdown-it-task-lists'))
|
|
162
|
-
.use(require('markdown-it-multimd-table'), {
|
|
163
|
-
multiline: true,
|
|
164
|
-
rowspan: true,
|
|
165
|
-
headerless: true
|
|
166
|
-
})
|
|
167
|
-
.use(containers, 'notice', {
|
|
168
|
-
validate: function (params) {
|
|
169
|
-
let matches = params.match(/(\w+)\s?(.*)?/);
|
|
170
|
-
return matches && noticeTypes[matches[1]];
|
|
171
|
-
},
|
|
172
|
-
render: function (tokens, idx) {
|
|
173
|
-
let matches = tokens[idx].info.match(/(\w+)\s?(.*)?/);
|
|
174
|
-
if (matches && tokens[idx].nesting === 1) {
|
|
175
|
-
let id;
|
|
176
|
-
let type = matches[1];
|
|
177
|
-
if (matches[2]) {
|
|
178
|
-
id = matches[2].trim().replace(/\s+/g, '-').toLowerCase();
|
|
179
|
-
if (noticeTitles[id]) id += '-' + noticeTitles[id]++;
|
|
180
|
-
else noticeTitles[id] = 1;
|
|
181
|
-
}
|
|
182
|
-
else id = type + '-' + noticeTypes[type]++;
|
|
183
|
-
return `<div id="${id}" class="notice ${type}"><a class="notice-link" href="#${id}">${type.toUpperCase()}</a>`;
|
|
184
|
-
}
|
|
185
|
-
else return '</div>\n';
|
|
186
|
-
}
|
|
187
|
-
})
|
|
188
|
-
.use(require('markdown-it-prism'))
|
|
189
|
-
.use(require('markdown-it-toc-and-anchor').default, {
|
|
190
|
-
tocClassName: 'toc',
|
|
191
|
-
tocFirstLevel: 2,
|
|
192
|
-
tocLastLevel: 4,
|
|
193
|
-
tocCallback: (_md, _tokens, html) => toc = html,
|
|
194
|
-
anchorLinkSymbol: '#', // was: §
|
|
195
|
-
anchorClassName: 'toc-anchor d-print-none'
|
|
196
|
-
})
|
|
197
|
-
.use(require('@traptitech/markdown-it-katex'))
|
|
198
|
-
|
|
199
|
-
const katexRules = ['math_block', 'math_inline'];
|
|
200
|
-
const replacerRegex = /\[\[\s*([^\s[\]:]+):?\s*([^\]\n]+)?\]\]/img;
|
|
201
|
-
const replacerArgsRegex = /\s*,+\s*/;
|
|
202
|
-
const replacers = [
|
|
203
|
-
{
|
|
204
|
-
test: 'insert',
|
|
205
|
-
transform: function (originalMatch, type, path) {
|
|
206
|
-
if (!path) return '';
|
|
207
|
-
return fs.readFileSync(path, 'utf8');
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
];
|
|
211
|
-
|
|
212
|
-
// Synchronously process markdown files
|
|
213
|
-
fixMarkdownFiles(path.join(config.specs[0].spec_directory, config.specs[0].spec_terms_directory));
|
|
214
|
-
|
|
215
|
-
function createScriptElementWithXTrefDataForEmbeddingInHtml() {
|
|
216
|
-
// Test if xtrefs-data.js exists, else make it an empty string
|
|
217
|
-
const inputPath = path.join('.cache', 'xtrefs-data.js');
|
|
218
|
-
|
|
219
|
-
let xtrefsData = '';
|
|
220
|
-
if (fs.existsSync(inputPath)) {
|
|
221
|
-
xtrefsData = '<script>' + fs.readFileSync(inputPath, 'utf8') + '</script>';
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return xtrefsData;
|
|
225
|
-
}
|
|
45
|
+
const { configurePlugins } = require('./src/markdown-it/plugins');
|
|
46
|
+
const {
|
|
47
|
+
katexRules,
|
|
48
|
+
replacerRegex,
|
|
49
|
+
replacerArgsRegex,
|
|
50
|
+
replacers,
|
|
51
|
+
createScriptElementWithXTrefDataForEmbeddingInHtml,
|
|
52
|
+
lookupXrefTerm,
|
|
53
|
+
applyReplacers,
|
|
54
|
+
normalizePath,
|
|
55
|
+
renderRefGroup,
|
|
56
|
+
findKatexDist
|
|
57
|
+
} = require('./src/pipeline/rendering/render-utils.js');
|
|
58
|
+
|
|
59
|
+
const { createMarkdownParser } = require('./src/pipeline/parsing/create-markdown-parser.js');
|
|
60
|
+
let md = createMarkdownParser(config, setToc);
|
|
226
61
|
|
|
227
62
|
const xtrefsData = createScriptElementWithXTrefDataForEmbeddingInHtml();
|
|
228
63
|
|
|
229
|
-
|
|
230
|
-
* Processes custom tag patterns in markdown content and applies transformation functions.
|
|
231
|
-
*
|
|
232
|
-
* This function scans the document for special tag patterns like [[tref:spec,term]]
|
|
233
|
-
* and replaces them with the appropriate HTML using the matching replacer.
|
|
234
|
-
*
|
|
235
|
-
* For tref tags, this is where the magic happens - we intercept them before
|
|
236
|
-
* the markdown parser even sees them, and convert them directly to HTML structure
|
|
237
|
-
* that will integrate properly with definition lists.
|
|
238
|
-
*
|
|
239
|
-
* @param {string} doc - The markdown document to process
|
|
240
|
-
* @returns {string} - The processed document with tags replaced by their HTML equivalents
|
|
241
|
-
*/
|
|
242
|
-
function applyReplacers(doc) {
|
|
243
|
-
// Use the escape handler for three-phase processing
|
|
244
|
-
return processWithEscapes(doc, function(content) {
|
|
245
|
-
return content.replace(replacerRegex, function (match, type, args) {
|
|
246
|
-
let replacer = replacers.find(r => type.trim().match(r.test));
|
|
247
|
-
if (replacer) {
|
|
248
|
-
let argsArray = args ? args.trim().split(replacerArgsRegex) : [];
|
|
249
|
-
return replacer.transform(match, type, ...argsArray);
|
|
250
|
-
}
|
|
251
|
-
return match;
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function normalizePath(path) {
|
|
257
|
-
return path.trim().replace(/\/$/g, '') + '/';
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function renderRefGroup(type) {
|
|
261
|
-
let group = specGroups[type];
|
|
262
|
-
if (!group) return '';
|
|
263
|
-
|
|
264
|
-
/*
|
|
265
|
-
The key advantage of localeCompare over simple comparison operators (<, >) is that it:
|
|
266
|
-
|
|
267
|
-
- Properly handles language-specific sorting rules (via locale settings)
|
|
268
|
-
- Correctly compares strings containing special characters or accents
|
|
269
|
-
- Can be configured to be case-insensitive
|
|
270
|
-
*/
|
|
271
|
-
let html = Object.keys(group).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).reduce((html, name) => {
|
|
272
|
-
let ref = group[name];
|
|
273
|
-
return html += `
|
|
274
|
-
<dt id="ref:${name}">${name}</dt>
|
|
275
|
-
<dd>
|
|
276
|
-
<cite><a href="${ref.href}">${ref.title}</a></cite>.
|
|
277
|
-
${ref.authors.join('; ')}; ${ref.rawDate}. <span class="reference-status">Status: ${ref.status}</span>.
|
|
278
|
-
</dd>
|
|
279
|
-
`;
|
|
280
|
-
}, '<dl class="reference-list">');
|
|
281
|
-
return `\n${html}\n</dl>\n`;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function findKatexDist() {
|
|
285
|
-
const relpath = "node_modules/katex/dist";
|
|
286
|
-
const paths = [
|
|
287
|
-
path.join(process.cwd(), relpath),
|
|
288
|
-
path.join(__dirname, relpath),
|
|
289
|
-
];
|
|
290
|
-
for (const abspath of paths) {
|
|
291
|
-
if (fs.existsSync(abspath)) {
|
|
292
|
-
return abspath
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
throw Error("katex distribution could not be located");
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
async function render(spec, assets) {
|
|
299
|
-
try {
|
|
300
|
-
noticeTitles = {};
|
|
301
|
-
specGroups = {};
|
|
302
|
-
console.log('ℹ️ Rendering: ' + spec.title);
|
|
303
|
-
|
|
304
|
-
function interpolate(template, variables) {
|
|
305
|
-
return template.replace(/\${(.*?)}/g, (match, p1) => variables[p1.trim()]);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Add current date in 'DD Month YYYY' format for template injection
|
|
309
|
-
const date = new Date();
|
|
310
|
-
const day = String(date.getDate()).padStart(2, '0');
|
|
311
|
-
const month = date.toLocaleString('en-US', { month: 'long' });
|
|
312
|
-
const year = date.getFullYear();
|
|
313
|
-
const currentDate = `${day} ${month} ${year}`;
|
|
314
|
-
|
|
315
|
-
const docs = await Promise.all(
|
|
316
|
-
(spec.markdown_paths || ['spec.md']).map(_path =>
|
|
317
|
-
fs.readFile(spec.spec_directory + _path, 'utf8')
|
|
318
|
-
)
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
const features = (({ source, logo }) => ({ source, logo }))(spec);
|
|
322
|
-
if (spec.external_specs && !externalReferences) {
|
|
323
|
-
externalReferences = await fetchExternalSpecs(spec);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Find the index of the terms-and-definitions-intro.md file
|
|
327
|
-
const termsIndex = (spec.markdown_paths || ['spec.md']).indexOf('terms-and-definitions-intro.md');
|
|
328
|
-
if (termsIndex !== -1) {
|
|
329
|
-
// Append the HTML string to the content of terms-and-definitions-intro.md. This string is used to create a div that is used to insert an alphabet index, and a div that is used as the starting point of the terminology index. The newlines are essential for the correct rendering of the markdown.
|
|
330
|
-
docs[termsIndex] += '\n\n<div id="terminology-section-start"></div>\n\n';
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
let doc = docs.join("\n");
|
|
334
|
-
|
|
335
|
-
// Handles backslash escape mechanism for substitution tags
|
|
336
|
-
// Phase 1: Pre-processing - Handle escaped tags
|
|
337
|
-
doc = processEscapedTags(doc);
|
|
338
|
-
|
|
339
|
-
// Handles backslash escape mechanism for substitution tags
|
|
340
|
-
// Phase 2: Tag Processing - Apply normal substitution logic
|
|
341
|
-
doc = applyReplacers(doc);
|
|
342
|
-
|
|
343
|
-
md[spec.katex ? "enable" : "disable"](katexRules);
|
|
344
|
-
|
|
345
|
-
// `render` is the rendered HTML
|
|
346
|
-
let renderedHtml = md.render(doc);
|
|
347
|
-
|
|
348
|
-
// Apply the fix for broken definition list structures
|
|
349
|
-
renderedHtml = fixDefinitionListStructure(renderedHtml);
|
|
350
|
-
|
|
351
|
-
// Sort definition terms case-insensitively before final rendering
|
|
352
|
-
renderedHtml = sortDefinitionTermsInHtml(renderedHtml);
|
|
353
|
-
|
|
354
|
-
// Handles backslash escape mechanism for substitution tags
|
|
355
|
-
// Phase 3: Post-processing - Restore escaped sequences as literals
|
|
356
|
-
renderedHtml = restoreEscapedTags(renderedHtml);
|
|
357
|
-
|
|
358
|
-
// Process external references to ensure they are inserted as raw HTML, not as JSON string
|
|
359
|
-
const externalReferencesHtml = Array.isArray(externalReferences)
|
|
360
|
-
? externalReferences.join('')
|
|
361
|
-
: (externalReferences || '');
|
|
362
|
-
|
|
363
|
-
const templateInterpolated = interpolate(template, {
|
|
364
|
-
title: spec.title,
|
|
365
|
-
description: spec.description,
|
|
366
|
-
author: spec.author,
|
|
367
|
-
toc: toc,
|
|
368
|
-
render: renderedHtml,
|
|
369
|
-
assetsHead: assets.head,
|
|
370
|
-
assetsBody: assets.body,
|
|
371
|
-
assetsSvg: assets.svg,
|
|
372
|
-
features: Object.keys(features).join(' '),
|
|
373
|
-
externalReferences: externalReferencesHtml,
|
|
374
|
-
xtrefsData: xtrefsData,
|
|
375
|
-
specLogo: spec.logo,
|
|
376
|
-
specFavicon: spec.favicon,
|
|
377
|
-
specLogoLink: spec.logo_link,
|
|
378
|
-
spec: JSON.stringify(spec),
|
|
379
|
-
externalSpecsList: externalSpecsList,
|
|
380
|
-
currentDate: currentDate
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
const outputPath = path.join(spec.destination, 'index.html');
|
|
384
|
-
console.log('ℹ️ Attempting to write to:', outputPath);
|
|
385
|
-
|
|
386
|
-
// Use promisified version instead of callback
|
|
387
|
-
await fs.promises.writeFile(outputPath, templateInterpolated, 'utf8');
|
|
388
|
-
console.log(`✅ Successfully wrote ${outputPath}`);
|
|
389
|
-
|
|
390
|
-
validateReferences(references, definitions, renderedHtml);
|
|
391
|
-
references = [];
|
|
392
|
-
definitions = [];
|
|
393
|
-
} catch (e) {
|
|
394
|
-
console.error("❌ Render error: " + e.message);
|
|
395
|
-
throw e;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
64
|
+
const { render } = require('./src/pipeline/rendering/render-spec-document.js');
|
|
398
65
|
|
|
399
66
|
try {
|
|
400
67
|
config.specs.forEach(spec => {
|
|
@@ -404,20 +71,20 @@ module.exports = async function (options = {}) {
|
|
|
404
71
|
if (!fs.existsSync(spec.destination)) {
|
|
405
72
|
try {
|
|
406
73
|
fs.mkdirSync(spec.destination, { recursive: true });
|
|
407
|
-
|
|
74
|
+
Logger.success(`Created directory: ${spec.destination}`);
|
|
408
75
|
} catch (error) {
|
|
409
|
-
|
|
76
|
+
Logger.error(`Failed to create directory ${spec.destination}: ${error.message}`);
|
|
410
77
|
throw error;
|
|
411
78
|
}
|
|
412
79
|
} else {
|
|
413
|
-
|
|
80
|
+
Logger.info(`Directory already exists: ${spec.destination}`);
|
|
414
81
|
}
|
|
415
82
|
|
|
416
83
|
try {
|
|
417
84
|
fs.ensureDirSync(spec.destination);
|
|
418
|
-
|
|
85
|
+
Logger.success(`Ensured directory is ready: ${spec.destination}`);
|
|
419
86
|
} catch (error) {
|
|
420
|
-
|
|
87
|
+
Logger.error(`Failed to ensure directory ${spec.destination}: ${error.message}`);
|
|
421
88
|
throw error;
|
|
422
89
|
}
|
|
423
90
|
|
|
@@ -469,33 +136,33 @@ module.exports = async function (options = {}) {
|
|
|
469
136
|
}
|
|
470
137
|
|
|
471
138
|
// Run render and wait for it
|
|
472
|
-
render(spec, assetTags)
|
|
139
|
+
render(spec, assetTags, { externalReferences, references, definitions, specGroups, noticeTitles }, config, template, assets, Logger, md, externalSpecsList)
|
|
473
140
|
.then(() => {
|
|
474
|
-
|
|
141
|
+
Logger.info('Render completed for:', spec.destination);
|
|
475
142
|
if (options.nowatch) {
|
|
476
|
-
|
|
143
|
+
Logger.info('Exiting with nowatch');
|
|
477
144
|
process.exit(0);
|
|
478
145
|
}
|
|
479
146
|
})
|
|
480
147
|
.catch((e) => {
|
|
481
|
-
|
|
148
|
+
Logger.error('Render failed:', e.message);
|
|
482
149
|
process.exit(1);
|
|
483
150
|
});
|
|
484
151
|
|
|
485
152
|
if (!options.nowatch) {
|
|
486
153
|
gulp.watch(
|
|
487
154
|
[spec.spec_directory + '**/*', '!' + path.join(spec.destination, 'index.html')],
|
|
488
|
-
render.bind(null, spec, assetTags)
|
|
155
|
+
render.bind(null, spec, assetTags, { externalReferences, references, definitions, specGroups, noticeTitles }, config, template, assets, Logger, md, externalSpecsList)
|
|
489
156
|
);
|
|
490
157
|
}
|
|
491
158
|
|
|
492
159
|
});
|
|
493
160
|
} catch (error) {
|
|
494
|
-
|
|
161
|
+
Logger.error(`Error during initialization or module execution: ${error.message}`);
|
|
495
162
|
throw error; // Re-throw to let the caller handle the error
|
|
496
163
|
}
|
|
497
164
|
} catch (error) {
|
|
498
|
-
|
|
165
|
+
Logger.error(`Error during initialization: ${error.message}`);
|
|
499
166
|
throw error; // Re-throw to let the caller handle the error
|
|
500
167
|
}
|
|
501
168
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-up-t",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Technical specification drafting tool that generates rich specification documents from markdown. Forked from https://github.com/decentralized-identity/spec-up by Daniel Buchner (https://github.com/csuwildcat)",
|
|
5
5
|
"main": "./index",
|
|
6
6
|
"repository": {
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
"@octokit/plugin-throttling": "^9.4.0",
|
|
27
27
|
"@traptitech/markdown-it-katex": "^3.3.0",
|
|
28
28
|
"axios": "^1.7.7",
|
|
29
|
+
"chalk": "^4.1.2",
|
|
30
|
+
"cheerio": "^1.1.2",
|
|
29
31
|
"dedent": "^1.5.3",
|
|
30
32
|
"diff": "^7.0.0",
|
|
31
33
|
"docx": "^8.5.0",
|
|
@@ -69,7 +71,8 @@
|
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"jest": "^29.7.0",
|
|
72
|
-
"jest-environment-jsdom": "^30.0.5"
|
|
74
|
+
"jest-environment-jsdom": "^30.0.5",
|
|
75
|
+
"unimported": "^1.31.0"
|
|
73
76
|
},
|
|
74
77
|
"scripts": {
|
|
75
78
|
"test": "jest",
|