dogsbay 0.2.0-beta.124 → 0.2.0-beta.126
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.
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Issue, Rule } from "@dogsbay/site-check";
|
|
2
|
+
export declare const markdownSyntax: Rule;
|
|
3
|
+
/** The issues `markdown/syntax` reports on the next audit. */
|
|
4
|
+
export declare function setMarkdownSyntaxIssues(issues: Issue[]): void;
|
|
5
|
+
/** Whether a content source is Dogsbay Markdown: named so, or detected as it. */
|
|
6
|
+
export declare function isDogsbayMdSource(dir: string, from: string | undefined): boolean;
|
|
7
|
+
/** `markdown/syntax` findings for these content folders, paths relative to the site. */
|
|
8
|
+
export declare function markdownSyntaxIssues(dirs: string[], siteRoot: string): Issue[];
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `markdown/syntax` — what the Dogsbay Markdown parser recovers from without a
|
|
3
|
+
* word: an unclosed `:::` block (it takes in the rest of the page), a `:::`
|
|
4
|
+
* that closes nothing, an unknown `:::name` or inline `:name[]`, an attribute
|
|
5
|
+
* block it cannot read. Each reaches the page as literal text or a plain box,
|
|
6
|
+
* and a build passes. The findings are `dogsbayMdToTree`'s diagnostics, with
|
|
7
|
+
* the source file and line.
|
|
8
|
+
*
|
|
9
|
+
* Reads the source files of every content source in Dogsbay Markdown (`from:
|
|
10
|
+
* dogsbay-md`, or detected as it), as written: before the template engine
|
|
11
|
+
* runs, so `{% … %}` lines are protected the way the editor parses them.
|
|
12
|
+
* Other formats are left alone: their files are not Dogsbay Markdown.
|
|
13
|
+
* Warnings, so a site with findings still exits 0 unless `--strict`.
|
|
14
|
+
*/
|
|
15
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
16
|
+
import { join, relative } from "node:path";
|
|
17
|
+
import { dogsbayMdToTree } from "@dogsbay/format-dogsbay-md";
|
|
18
|
+
import { detectFormat } from "../../formats.js";
|
|
19
|
+
let pending = [];
|
|
20
|
+
export const markdownSyntax = {
|
|
21
|
+
id: "markdown/syntax",
|
|
22
|
+
category: "markdown",
|
|
23
|
+
stage: "source-corpus",
|
|
24
|
+
severity: "warning",
|
|
25
|
+
description: "Dogsbay Markdown the parser recovers from silently: an unclosed or stray `:::`, an unknown `:::name` or `:name[]`, an unreadable `{…}` attribute block.",
|
|
26
|
+
// Filled by `site check` once sources are resolved (I/O happens there, not here)
|
|
27
|
+
run: () => pending,
|
|
28
|
+
};
|
|
29
|
+
/** The issues `markdown/syntax` reports on the next audit. */
|
|
30
|
+
export function setMarkdownSyntaxIssues(issues) {
|
|
31
|
+
pending = issues;
|
|
32
|
+
}
|
|
33
|
+
/** Whether a content source is Dogsbay Markdown: named so, or detected as it. */
|
|
34
|
+
export function isDogsbayMdSource(dir, from) {
|
|
35
|
+
if (from && from !== "auto")
|
|
36
|
+
return from === "dogsbay-md";
|
|
37
|
+
return detectFormat(dir)?.name === "dogsbay-md";
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The `.md` pages under a folder, as the dogsbay-md importer walks them
|
|
41
|
+
* (`walkMdFiles`): `_`-prefixed files and folders are include fragments, not
|
|
42
|
+
* pages, and a fragment may open a block its includer closes, so they are not
|
|
43
|
+
* checked on their own. Symlinked files count. Dot folders and node_modules
|
|
44
|
+
* are skipped.
|
|
45
|
+
*/
|
|
46
|
+
function markdownFiles(dir) {
|
|
47
|
+
const out = [];
|
|
48
|
+
const walk = (d) => {
|
|
49
|
+
let entries;
|
|
50
|
+
try {
|
|
51
|
+
entries = readdirSync(d, { withFileTypes: true });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
57
|
+
if (e.name.startsWith(".") || e.name.startsWith("_") || e.name === "node_modules")
|
|
58
|
+
continue;
|
|
59
|
+
const p = join(d, e.name);
|
|
60
|
+
if (e.isDirectory())
|
|
61
|
+
walk(p);
|
|
62
|
+
else if (e.name.endsWith(".md") && (e.isFile() || (e.isSymbolicLink() && isFileTarget(p))))
|
|
63
|
+
out.push(p);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
walk(dir);
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
const isFileTarget = (path) => {
|
|
70
|
+
try {
|
|
71
|
+
return statSync(path).isFile();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** `markdown/syntax` findings for these content folders, paths relative to the site. */
|
|
78
|
+
export function markdownSyntaxIssues(dirs, siteRoot) {
|
|
79
|
+
const issues = [];
|
|
80
|
+
for (const dir of dirs) {
|
|
81
|
+
for (const file of markdownFiles(dir)) {
|
|
82
|
+
const { diagnostics = [] } = dogsbayMdToTree(readFileSync(file, "utf-8"), { diagnostics: true, directives: "preserve" });
|
|
83
|
+
for (const d of diagnostics) {
|
|
84
|
+
issues.push({ ruleId: markdownSyntax.id, severity: "warning", file: relative(siteRoot, file), line: d.line, message: d.message, context: d.code });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return issues;
|
|
89
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { registerRule } from "@dogsbay/site-check";
|
|
7
7
|
import { navTargetExists } from "./nav-target-exists.js";
|
|
8
8
|
import { topicmapValid } from "./topicmap-valid.js";
|
|
9
|
+
import { markdownSyntax } from "../markdown-syntax.js";
|
|
9
10
|
let registered = false;
|
|
10
11
|
/** Idempotent, like the shared register* functions. */
|
|
11
12
|
export function registerCliStructureRules() {
|
|
@@ -14,4 +15,5 @@ export function registerCliStructureRules() {
|
|
|
14
15
|
registered = true;
|
|
15
16
|
registerRule(navTargetExists);
|
|
16
17
|
registerRule(topicmapValid);
|
|
18
|
+
registerRule(markdownSyntax);
|
|
17
19
|
}
|
|
@@ -33,6 +33,7 @@ import { loadPlugins, collectAuditRules, runOnContentImported, runTransformNav,
|
|
|
33
33
|
import { filterRules, formatJson, formatText, registerRule, registerFrontmatterRules, registerSeoRules, registerStructureRules, reportExitCode, runAudit, } from "@dogsbay/site-check";
|
|
34
34
|
import { collectAssets, crawlDist, distFileReader } from "@dogsbay/site-check/node";
|
|
35
35
|
import { registerCliStructureRules } from "../audit/rules/structure/index.js";
|
|
36
|
+
import { isDogsbayMdSource, markdownSyntaxIssues, setMarkdownSyntaxIssues } from "../audit/rules/markdown-syntax.js";
|
|
36
37
|
import { siteReleaseComparisons } from "../release/compare.js";
|
|
37
38
|
import { frontmatterPolicyFromConfig } from "@dogsbay/types";
|
|
38
39
|
export async function siteCheck(cwd, options) {
|
|
@@ -259,6 +260,10 @@ export async function siteCheck(cwd, options) {
|
|
|
259
260
|
siteRoot,
|
|
260
261
|
})));
|
|
261
262
|
}
|
|
263
|
+
// `markdown/syntax`: the parser's diagnostics over each Dogsbay Markdown source, as written
|
|
264
|
+
setMarkdownSyntaxIssues(wantSource && rules.some((r) => r.id === "markdown/syntax")
|
|
265
|
+
? markdownSyntaxIssues(auditSources.map((a) => a.contentDir).filter((dir, i) => isDogsbayMdSource(dir, config.content.sources[i]?.from)), siteRoot)
|
|
266
|
+
: []);
|
|
262
267
|
// Asset set for `structure/asset-refs` — walks every source's
|
|
263
268
|
// content tree for files matching `copyAssets`'s extension
|
|
264
269
|
// list. Keep `collectAssets` in sync with that helper or refs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dogsbay",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.126",
|
|
4
4
|
"description": "CLI for Dogsbay — scaffold, build, and serve documentation sites with markdown / MkDocs / Obsidian / OpenAPI sources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -43,36 +43,36 @@
|
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"valibot": "1.1.0",
|
|
45
45
|
"yaml": "^2.9.0",
|
|
46
|
-
"@dogsbay/adoc2md-modular": "0.2.0-beta.
|
|
47
|
-
"@dogsbay/
|
|
48
|
-
"@dogsbay/
|
|
49
|
-
"@dogsbay/format-asciidoc": "0.2.0-beta.
|
|
50
|
-
"@dogsbay/format-astro": "0.2.0-beta.
|
|
51
|
-
"@dogsbay/format-dita": "0.2.0-beta.
|
|
52
|
-
"@dogsbay/format-docusaurus": "0.2.0-beta.
|
|
53
|
-
"@dogsbay/format-dogsbay-md": "0.2.0-beta.
|
|
54
|
-
"@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.
|
|
55
|
-
"@dogsbay/format-fluidtopics-rest": "0.2.0-beta.
|
|
56
|
-
"@dogsbay/format-gatsby": "0.2.0-beta.
|
|
57
|
-
"@dogsbay/format-gitbook": "0.2.0-beta.
|
|
58
|
-
"@dogsbay/format-hugo": "0.2.0-beta.
|
|
59
|
-
"@dogsbay/format-mdx": "0.2.0-beta.
|
|
60
|
-
"@dogsbay/format-mkdocs": "0.2.0-beta.
|
|
61
|
-
"@dogsbay/format-myst": "0.2.0-beta.
|
|
62
|
-
"@dogsbay/format-obsidian": "0.2.0-beta.
|
|
63
|
-
"@dogsbay/format-openapi": "0.2.0-beta.
|
|
64
|
-
"@dogsbay/format-
|
|
65
|
-
"@dogsbay/format-
|
|
66
|
-
"@dogsbay/format-starlight": "0.2.0-beta.
|
|
67
|
-
"@dogsbay/format-topicmap": "0.2.0-beta.
|
|
68
|
-
"@dogsbay/format-vitepress": "0.2.0-beta.
|
|
69
|
-
"@dogsbay/minja": "0.2.0-beta.
|
|
70
|
-
"@dogsbay/render": "0.2.0-beta.
|
|
71
|
-
"@dogsbay/render-html": "0.2.0-beta.
|
|
72
|
-
"@dogsbay/serialize-core": "0.2.0-beta.
|
|
73
|
-
"@dogsbay/site-check": "0.2.0-beta.
|
|
74
|
-
"@dogsbay/site-files": "0.2.0-beta.
|
|
75
|
-
"@dogsbay/types": "0.2.0-beta.
|
|
46
|
+
"@dogsbay/adoc2md-modular": "0.2.0-beta.126",
|
|
47
|
+
"@dogsbay/autodoc-python": "0.2.0-beta.126",
|
|
48
|
+
"@dogsbay/commands": "0.2.0-beta.126",
|
|
49
|
+
"@dogsbay/format-asciidoc": "0.2.0-beta.126",
|
|
50
|
+
"@dogsbay/format-astro": "0.2.0-beta.126",
|
|
51
|
+
"@dogsbay/format-dita": "0.2.0-beta.126",
|
|
52
|
+
"@dogsbay/format-docusaurus": "0.2.0-beta.126",
|
|
53
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.126",
|
|
54
|
+
"@dogsbay/format-fluidtopics-markdown": "0.2.0-beta.126",
|
|
55
|
+
"@dogsbay/format-fluidtopics-rest": "0.2.0-beta.126",
|
|
56
|
+
"@dogsbay/format-gatsby": "0.2.0-beta.126",
|
|
57
|
+
"@dogsbay/format-gitbook": "0.2.0-beta.126",
|
|
58
|
+
"@dogsbay/format-hugo": "0.2.0-beta.126",
|
|
59
|
+
"@dogsbay/format-mdx": "0.2.0-beta.126",
|
|
60
|
+
"@dogsbay/format-mkdocs": "0.2.0-beta.126",
|
|
61
|
+
"@dogsbay/format-myst": "0.2.0-beta.126",
|
|
62
|
+
"@dogsbay/format-obsidian": "0.2.0-beta.126",
|
|
63
|
+
"@dogsbay/format-openapi": "0.2.0-beta.126",
|
|
64
|
+
"@dogsbay/format-rst": "0.2.0-beta.126",
|
|
65
|
+
"@dogsbay/format-openknowledge": "0.2.0-beta.126",
|
|
66
|
+
"@dogsbay/format-starlight": "0.2.0-beta.126",
|
|
67
|
+
"@dogsbay/format-topicmap": "0.2.0-beta.126",
|
|
68
|
+
"@dogsbay/format-vitepress": "0.2.0-beta.126",
|
|
69
|
+
"@dogsbay/minja": "0.2.0-beta.126",
|
|
70
|
+
"@dogsbay/render": "0.2.0-beta.126",
|
|
71
|
+
"@dogsbay/render-html": "0.2.0-beta.126",
|
|
72
|
+
"@dogsbay/serialize-core": "0.2.0-beta.126",
|
|
73
|
+
"@dogsbay/site-check": "0.2.0-beta.126",
|
|
74
|
+
"@dogsbay/site-files": "0.2.0-beta.126",
|
|
75
|
+
"@dogsbay/types": "0.2.0-beta.126"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@mdx-js/mdx": "^3.1.1",
|