@zudojs/docs 1.0.6 → 1.1.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/README.md +4 -1
- package/dist/docsTypes/documentationContent.d.ts +0 -1
- package/dist/docsTypes/documentationContent.js +0 -1
- package/dist/docsTypes/documentationDocument.d.ts +0 -1
- package/dist/docsTypes/documentationDocument.js +0 -1
- package/dist/docsTypes/documentationMetadata.d.ts +5 -2
- package/dist/docsTypes/documentationMetadata.js +0 -1
- package/dist/docsTypes/documentationNavigation.d.ts +9 -3
- package/dist/docsTypes/documentationNavigation.js +0 -1
- package/dist/docsTypes/documentationProvider.d.ts +5 -2
- package/dist/docsTypes/documentationProvider.js +0 -1
- package/dist/docsTypes/index.d.ts +0 -1
- package/dist/docsTypes/index.js +0 -1
- package/dist/document/documentBuilder.convenience.d.ts +15 -0
- package/dist/document/documentBuilder.convenience.js +28 -0
- package/dist/document/documentBuilder.core.d.ts +18 -13
- package/dist/document/documentBuilder.core.js +16 -50
- package/dist/document/documentBuilder.normalize.d.ts +5 -1
- package/dist/document/documentBuilder.normalize.js +12 -1
- package/dist/document/documentBuilder.validate.d.ts +16 -0
- package/dist/document/documentBuilder.validate.js +36 -0
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.js +2 -2
- package/dist/errors/index.d.ts +0 -1
- package/dist/errors/index.js +0 -1
- package/dist/examples/examples.core.d.ts +0 -1
- package/dist/examples/examples.core.js +0 -1
- package/dist/examples/index.d.ts +0 -1
- package/dist/examples/index.js +0 -1
- package/dist/frontmatter/frontmatter.core.d.ts +0 -1
- package/dist/frontmatter/frontmatter.core.js +0 -1
- package/dist/frontmatter/frontmatter.parser.d.ts +0 -1
- package/dist/frontmatter/frontmatter.parser.js +0 -1
- package/dist/frontmatter/frontmatter.serializer.d.ts +0 -1
- package/dist/frontmatter/frontmatter.serializer.js +0 -1
- package/dist/frontmatter/frontmatter.types.d.ts +0 -1
- package/dist/frontmatter/frontmatter.types.js +0 -1
- package/dist/frontmatter/frontmatter.values.d.ts +0 -1
- package/dist/frontmatter/frontmatter.values.js +0 -1
- package/dist/frontmatter/index.d.ts +0 -1
- package/dist/frontmatter/index.js +0 -1
- package/dist/generator/generator.types.d.ts +0 -1
- package/dist/generator/generator.types.js +0 -1
- package/dist/generator/generatorJson.core.d.ts +0 -1
- package/dist/generator/generatorJson.core.js +0 -1
- package/dist/generator/generatorMarkdown.core.d.ts +0 -1
- package/dist/generator/generatorMarkdown.core.js +0 -1
- package/dist/generator/generatorMarkdownNodes.d.ts +0 -1
- package/dist/generator/generatorMarkdownNodes.js +0 -1
- package/dist/generator/index.d.ts +0 -1
- package/dist/generator/index.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/navigation/index.d.ts +3 -2
- package/dist/navigation/index.js +2 -2
- package/dist/navigation/navigation.adjacent.d.ts +32 -0
- package/dist/navigation/navigation.adjacent.js +60 -0
- package/dist/navigation/navigation.core.d.ts +0 -13
- package/dist/navigation/navigation.core.js +0 -51
- package/dist/registry/index.d.ts +0 -1
- package/dist/registry/index.js +0 -1
- package/dist/registry/registry.core.d.ts +0 -1
- package/dist/registry/registry.core.js +0 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/utils.freeze.d.ts +0 -1
- package/dist/utils/utils.freeze.js +0 -1
- package/dist/utils/utils.helper.d.ts +0 -1
- package/dist/utils/utils.helper.js +0 -1
- package/dist/utils/utils.href.d.ts +0 -1
- package/dist/utils/utils.href.js +0 -1
- package/dist/utils/utils.markdownText.d.ts +0 -1
- package/dist/utils/utils.markdownText.js +0 -1
- package/dist/validator/index.d.ts +0 -1
- package/dist/validator/index.js +0 -1
- package/dist/validator/validator.types.d.ts +0 -1
- package/dist/validator/validator.types.js +0 -1
- package/dist/validator/validatorAll/index.d.ts +0 -1
- package/dist/validator/validatorAll/index.js +0 -1
- package/dist/validator/validatorAll/validatorAll.core.d.ts +11 -1
- package/dist/validator/validatorAll/validatorAll.core.js +6 -2
- package/dist/validator/validatorAll/validatorNavigation.core.d.ts +0 -1
- package/dist/validator/validatorAll/validatorNavigation.core.js +0 -1
- package/dist/validator/validatorDocument.core.d.ts +0 -1
- package/dist/validator/validatorDocument.core.js +0 -1
- package/dist/validator/validatorDuplicates.core.d.ts +0 -1
- package/dist/validator/validatorDuplicates.core.js +0 -1
- package/dist/validator/validatorLinks.core.d.ts +16 -6
- package/dist/validator/validatorLinks.core.js +18 -37
- package/dist/validator/validatorLinks.extract.d.ts +30 -0
- package/dist/validator/validatorLinks.extract.js +118 -0
- package/package.json +2 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts link targets from markdown in every form a renderer turns into
|
|
3
|
+
* a live link: inline `[text](target)`, reference definitions
|
|
4
|
+
* `[label]: target`, raw HTML `href` attributes and `<scheme:…>` autolinks.
|
|
5
|
+
*
|
|
6
|
+
* Every scanner is linear in the input length, so hostile documents
|
|
7
|
+
* (a 99 KB run of `[`, `(` or `<`) are scanned in milliseconds.
|
|
8
|
+
*
|
|
9
|
+
* @module validator/validatorLinks.extract
|
|
10
|
+
*/
|
|
11
|
+
/** `[text](` or `\[[^[\]\n]*\]\(/g;
|
|
13
|
+
/** `[label]: target` at line start; target is `<…>` or non-whitespace. */
|
|
14
|
+
const REFERENCE_DEFINITION = /^[ \t]{0,3}\[[^\]\n]*\]:[ \t]*(<[^<>\n]*>|\S+)/gm;
|
|
15
|
+
/** A raw HTML tag on one line. `[^<>\n]` keeps a run of `<` linear. */
|
|
16
|
+
const HTML_TAG = /<[a-zA-Z][^<>\n]*>/g;
|
|
17
|
+
/** `href=` inside a tag: double-quoted, single-quoted or bare. */
|
|
18
|
+
const HREF_ATTRIBUTE = /\bhref[ \t]*=[ \t]*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i;
|
|
19
|
+
/** A CommonMark autolink: `<scheme:rest>` with no whitespace. */
|
|
20
|
+
const AUTOLINK = /^<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^\s<>]*)>$/;
|
|
21
|
+
/**
|
|
22
|
+
* Returns every distinct link target in `source`, in order of first
|
|
23
|
+
* appearance. `source` must already have fenced code blocks and inline
|
|
24
|
+
* code spans removed. A target found by two scanners (`[x](<t>)` is both
|
|
25
|
+
* an inline link and an autolink) is returned once.
|
|
26
|
+
*/
|
|
27
|
+
export function extractLinkTargets(source) {
|
|
28
|
+
const links = [];
|
|
29
|
+
extractInlineLinks(source, links);
|
|
30
|
+
extractReferenceDefinitions(source, links);
|
|
31
|
+
extractHtmlLinks(source, links);
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
return links.filter((link) => {
|
|
34
|
+
const key = `${link.isImage ? "!" : ""}${link.target}`;
|
|
35
|
+
if (seen.has(key))
|
|
36
|
+
return false;
|
|
37
|
+
seen.add(key);
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function extractInlineLinks(source, out) {
|
|
42
|
+
INLINE_HEAD.lastIndex = 0;
|
|
43
|
+
let head;
|
|
44
|
+
while ((head = INLINE_HEAD.exec(source)) !== null) {
|
|
45
|
+
const isImage = head[1] === "!";
|
|
46
|
+
const target = readInlineTarget(source, head.index + head[0].length);
|
|
47
|
+
if (target !== "")
|
|
48
|
+
out.push({ target, isImage });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Reads the destination that follows `](`: either `<…>` wrapped, or a run
|
|
53
|
+
* of non-whitespace characters in which parentheses must balance, ending
|
|
54
|
+
* at the first unmatched `)`. A bare destination also stops at `[`, so a
|
|
55
|
+
* link nested in an unclosed one (`[a]([b](javascript:x)`) is still found
|
|
56
|
+
* on its own and no character is scanned by two heads.
|
|
57
|
+
*/
|
|
58
|
+
function readInlineTarget(source, start) {
|
|
59
|
+
let index = start;
|
|
60
|
+
while (index < source.length && (source[index] === " " || source[index] === "\t")) {
|
|
61
|
+
index += 1;
|
|
62
|
+
}
|
|
63
|
+
if (source[index] === "<") {
|
|
64
|
+
const close = source.indexOf(">", index + 1);
|
|
65
|
+
const newline = source.indexOf("\n", index + 1);
|
|
66
|
+
if (close !== -1 && (newline === -1 || close < newline)) {
|
|
67
|
+
return source.slice(index + 1, close);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let depth = 0;
|
|
71
|
+
const targetStart = index;
|
|
72
|
+
while (index < source.length) {
|
|
73
|
+
const char = source[index] ?? "";
|
|
74
|
+
if (char === "[" || /\s/.test(char))
|
|
75
|
+
break;
|
|
76
|
+
if (char === "(")
|
|
77
|
+
depth += 1;
|
|
78
|
+
if (char === ")") {
|
|
79
|
+
if (depth === 0)
|
|
80
|
+
break;
|
|
81
|
+
depth -= 1;
|
|
82
|
+
}
|
|
83
|
+
index += 1;
|
|
84
|
+
}
|
|
85
|
+
return source.slice(targetStart, index);
|
|
86
|
+
}
|
|
87
|
+
function extractReferenceDefinitions(source, out) {
|
|
88
|
+
for (const match of source.matchAll(REFERENCE_DEFINITION)) {
|
|
89
|
+
const raw = match[1] ?? "";
|
|
90
|
+
const target = raw.startsWith("<") && raw.endsWith(">") ? raw.slice(1, -1) : raw;
|
|
91
|
+
if (target !== "")
|
|
92
|
+
out.push({ target, isImage: false });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function extractHtmlLinks(source, out) {
|
|
96
|
+
for (const match of source.matchAll(HTML_TAG)) {
|
|
97
|
+
const tag = match[0];
|
|
98
|
+
const autolink = AUTOLINK.exec(tag);
|
|
99
|
+
if (autolink) {
|
|
100
|
+
out.push({ target: autolink[1] ?? "", isImage: false });
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const href = HREF_ATTRIBUTE.exec(tag);
|
|
104
|
+
if (!href)
|
|
105
|
+
continue;
|
|
106
|
+
const target = href[1] ?? href[2] ?? href[3] ?? "";
|
|
107
|
+
if (target !== "")
|
|
108
|
+
out.push({ target, isImage: false });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Blanks out inline code spans so links inside them are ignored. The
|
|
113
|
+
* lookarounds anchor each attempt at a whole backtick run, so a long run is
|
|
114
|
+
* not re-scanned from every position inside it.
|
|
115
|
+
*/
|
|
116
|
+
export function stripInlineCode(markdown) {
|
|
117
|
+
return markdown.replace(/(?<!`)(`+)(?![`\n])[\s\S]*?(?<!`)\1(?!`)/g, (m) => " ".repeat(m.length));
|
|
118
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/docs",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Documentation infrastructure with structured document model, registry, validation, navigation, and generation.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@zudojs/errors": "1.
|
|
14
|
+
"@zudojs/errors": "1.4.0"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"typescript": "7.0.2",
|