sourcey 3.5.7 → 3.5.9

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 CHANGED
@@ -54,32 +54,28 @@ npx sourcey init
54
54
 
55
55
  ## Install
56
56
 
57
- ### Sourcey
57
+ ### Sourcey CLI
58
58
 
59
- ```bash
60
- npm install -g sourcey
61
- npx sourcey init
62
- ```
59
+ The full Sourcey binary handles OpenAPI, Doxygen, godoc, MCP, and Markdown sources.
63
60
 
64
- ### Go docs generator
65
-
66
- ```bash
67
- go install github.com/sourcey/sourcey/go/sourcey-godoc/cmd/sourcey-godoc@latest
68
- ```
61
+ | Path | Command | Requires |
62
+ |----------|----------------------------------------------------|-------------------|
63
+ | npm | `npm install -g sourcey` | Node 20+ |
64
+ | Homebrew | `brew tap sourcey/tap && brew install sourcey` | macOS / Linuxbrew |
65
+ | Docker | `docker run -v "$PWD":/docs sourcey/sourcey` | Docker |
66
+ | Nix | `nix run github:sourcey/sourcey` | Nix (flakes) |
69
67
 
70
- ### Homebrew (Go docs generator)
68
+ Then `sourcey init` to scaffold a new project, or `sourcey build` against an existing one. See [docs/install.md](docs/install.md) for full Docker invocations (`init` / `dev` / `build`), the `--host` flag for containerized dev, Linuxbrew notes, and Nix profile install.
71
69
 
72
- ```bash
73
- brew tap sourcey/tap
74
- brew install sourcey-godoc
75
- ```
70
+ ### Standalone Go docs generator
76
71
 
77
- ### Scoop (Go docs generator)
72
+ For Go-only consumers without a JavaScript toolchain, `sourcey-godoc` ships as a separate native binary. It produces static Go docs sites or portable `godoc.json` snapshots.
78
73
 
79
- ```powershell
80
- scoop bucket add sourcey https://github.com/sourcey/scoop-bucket
81
- scoop install sourcey-godoc
82
- ```
74
+ | Path | Command |
75
+ |----------|---------|
76
+ | Go | `go install github.com/sourcey/sourcey/go/sourcey-godoc/cmd/sourcey-godoc@latest` |
77
+ | Homebrew | `brew install sourcey/tap/sourcey-godoc` |
78
+ | Scoop | `scoop bucket add sourcey https://github.com/sourcey/scoop-bucket && scoop install sourcey-godoc` |
83
79
 
84
80
  ## Quick start
85
81
 
package/dist/cli.js CHANGED
@@ -110,6 +110,11 @@ const dev = defineCommand({
110
110
  description: "Port to listen on",
111
111
  default: "4400",
112
112
  },
113
+ host: {
114
+ type: "string",
115
+ description: "Address to bind to (e.g. 0.0.0.0 to expose externally; defaults to 127.0.0.1, or $HOST if set)",
116
+ required: false,
117
+ },
113
118
  config: {
114
119
  type: "string",
115
120
  alias: ["c"],
@@ -126,6 +131,7 @@ const dev = defineCommand({
126
131
  const { startDevServer } = await import("./dev-server.js");
127
132
  await startDevServer({
128
133
  port: parseInt(args.port, 10),
134
+ host: args.host ?? process.env.HOST,
129
135
  config: args.config,
130
136
  strictChangelog: args.strictChangelog,
131
137
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ChangelogPage.d.ts","sourceRoot":"","sources":["../../../src/components/changelog/ChangelogPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGxF,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,gCAyBlE"}
1
+ {"version":3,"file":"ChangelogPage.d.ts","sourceRoot":"","sources":["../../../src/components/changelog/ChangelogPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAIxF,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,gCA4BlE"}
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ import { renderMarkdownInline } from "../../utils/markdown.js";
2
3
  import { VersionCard } from "./VersionCard.js";
3
4
  export function ChangelogPage({ page }) {
4
5
  const versions = page.permalinkVersionId
5
6
  ? page.changelog.versions.filter((version) => version.id === page.permalinkVersionId)
6
7
  : page.changelog.versions;
7
- return (_jsxs("div", { class: "sourcey-changelog-page", children: [_jsxs("header", { class: "sourcey-changelog-header", children: [_jsx("div", { class: "mt-0.5 space-y-2.5", children: _jsx("h1", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] tracking-tight dark:text-[rgb(var(--color-gray-200))] font-bold", style: "overflow-wrap: anywhere", children: page.title }) }), page.description && (_jsx("p", { class: "sourcey-changelog-description", children: page.description }))] }), _jsx("div", { class: "sourcey-changelog-list", children: versions.map((version) => (_jsx(VersionCard, { version: version }, version.id))) })] }));
8
+ return (_jsxs("div", { class: "sourcey-changelog-page", children: [_jsxs("header", { class: "sourcey-changelog-header", children: [_jsx("div", { class: "mt-0.5 space-y-2.5", children: _jsx("h1", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] tracking-tight dark:text-[rgb(var(--color-gray-200))] font-bold", style: "overflow-wrap: anywhere", children: page.title }) }), page.description && (_jsx("p", { class: "sourcey-changelog-description", dangerouslySetInnerHTML: { __html: renderMarkdownInline(page.description) } }))] }), _jsx("div", { class: "sourcey-changelog-list", children: versions.map((version) => (_jsx(VersionCard, { version: version }, version.id))) })] }));
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VersionCard.d.ts","sourceRoot":"","sources":["../../../src/components/changelog/VersionCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAoBtE,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,aAAa,GACd,EAAE;IACD,OAAO,EAAE,0BAA0B,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,gCAuCA"}
1
+ {"version":3,"file":"VersionCard.d.ts","sourceRoot":"","sources":["../../../src/components/changelog/VersionCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAoBtE,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,aAAa,GACd,EAAE;IACD,OAAO,EAAE,0BAA0B,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,gCA4CA"}
@@ -21,5 +21,7 @@ export function VersionCard({ version, permalinkHref, }) {
21
21
  const href = permalinkHref ?? `#${version.id}`;
22
22
  const label = version.version ?? "Unreleased";
23
23
  const formattedDate = formatDate(version.date);
24
- return (_jsxs("article", { id: version.id, class: `sourcey-changelog-version${version.version ? "" : " sourcey-changelog-version-unreleased"}`, children: [_jsxs("header", { class: "sourcey-changelog-version-header", children: [_jsxs("div", { class: "sourcey-changelog-version-heading", children: [_jsx("a", { href: href, class: "sourcey-changelog-version-link", children: label }), version.yanked && _jsx("span", { class: "sourcey-changelog-pill sourcey-changelog-pill-yanked", children: "YANKED" }), version.prerelease && _jsx("span", { class: "sourcey-changelog-pill sourcey-changelog-pill-pre", children: "pre" })] }), _jsxs("div", { class: "sourcey-changelog-version-meta", children: [formattedDate && _jsx("time", { dateTime: version.date ?? undefined, children: formattedDate }), version.compareUrl && (_jsx("a", { href: version.compareUrl, target: "_blank", rel: "noopener noreferrer", class: "sourcey-changelog-compare-link", children: "Compare" }))] })] }), version.summary && _jsx(Markdown, { content: version.summary, class: "sourcey-changelog-summary" }), _jsx("div", { class: "sourcey-changelog-sections", children: version.sections.map((section) => (_jsxs("section", { class: "sourcey-changelog-section", children: [_jsx("div", { class: "sourcey-changelog-section-header", children: _jsx(TypeBadge, { type: section.type, label: section.label }) }), _jsx(EntryList, { entries: section.entries })] }, `${version.id}-${section.label}`))) })] }));
24
+ const isUnreleased = !version.version;
25
+ const hasMeta = isUnreleased || formattedDate || version.compareUrl;
26
+ return (_jsxs("article", { id: version.id, class: `sourcey-changelog-version${isUnreleased ? " sourcey-changelog-version-unreleased" : ""}`, children: [_jsxs("header", { class: "sourcey-changelog-version-header", children: [_jsxs("div", { class: "sourcey-changelog-version-heading", children: [_jsx("a", { href: href, class: "sourcey-changelog-version-link", children: label }), version.yanked && _jsx("span", { class: "sourcey-changelog-pill sourcey-changelog-pill-yanked", children: "YANKED" }), version.prerelease && _jsx("span", { class: "sourcey-changelog-pill sourcey-changelog-pill-pre", children: "pre" })] }), hasMeta && (_jsxs("div", { class: "sourcey-changelog-version-meta", children: [isUnreleased && _jsx("span", { class: "sourcey-changelog-pill sourcey-changelog-pill-next", children: "Next release" }), formattedDate && _jsx("time", { dateTime: version.date ?? undefined, children: formattedDate }), version.compareUrl && (_jsx("a", { href: version.compareUrl, target: "_blank", rel: "noopener noreferrer", class: "sourcey-changelog-compare-link", children: "Compare" }))] }))] }), version.summary && _jsx(Markdown, { content: version.summary, class: "sourcey-changelog-summary" }), _jsx("div", { class: "sourcey-changelog-sections", children: version.sections.map((section) => (_jsxs("section", { class: "sourcey-changelog-section", children: [_jsx("div", { class: "sourcey-changelog-section-header", children: _jsx(TypeBadge, { type: section.type, label: section.label }) }), _jsx(EntryList, { entries: section.entries })] }, `${version.id}-${section.label}`))) })] }));
25
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"changelog-normalizer.d.ts","sourceRoot":"","sources":["../../src/core/changelog-normalizer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAMV,mBAAmB,EAIpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuDD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,yBAA8B,GACtC,mBAAmB,CA4HrB"}
1
+ {"version":3,"file":"changelog-normalizer.d.ts","sourceRoot":"","sources":["../../src/core/changelog-normalizer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAMV,mBAAmB,EAIpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuDD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,yBAA8B,GACtC,mBAAmB,CA8HrB"}
@@ -36,6 +36,7 @@ export function normalizeChangelog(markdown, options = {}) {
36
36
  const descriptionParts = [];
37
37
  const rawBlocks = [];
38
38
  let currentBlock = null;
39
+ let seenFirstVersionHeading = false;
39
40
  for (const token of tokens) {
40
41
  if (token.type === "heading") {
41
42
  const heading = token;
@@ -48,6 +49,7 @@ export function normalizeChangelog(markdown, options = {}) {
48
49
  if (currentBlock)
49
50
  rawBlocks.push(currentBlock);
50
51
  currentBlock = null;
52
+ seenFirstVersionHeading = true;
51
53
  const parsed = parseVersionHeading(text);
52
54
  if (!parsed) {
53
55
  diagnostics.push({
@@ -72,7 +74,7 @@ export function normalizeChangelog(markdown, options = {}) {
72
74
  if (currentBlock) {
73
75
  appendTokenToVersion(token, currentBlock, diagnostics, options.repoUrl);
74
76
  }
75
- else if (!options.description && shouldContributeToDescription(token)) {
77
+ else if (!options.description && !seenFirstVersionHeading && shouldContributeToDescription(token)) {
76
78
  descriptionParts.push(token.raw);
77
79
  }
78
80
  }
@@ -1,5 +1,6 @@
1
1
  export interface DevServerOptions {
2
2
  port: number;
3
+ host?: string;
3
4
  config?: string;
4
5
  strictChangelog?: boolean;
5
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AA+CA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuZ7E"}
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AA+CA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyZ7E"}
@@ -37,7 +37,7 @@ function shortPath(path) {
37
37
  return relative(process.cwd(), path) || basename(path);
38
38
  }
39
39
  export async function startDevServer(options) {
40
- const { port } = options;
40
+ const { port, host } = options;
41
41
  let config = await loadConfig(options.config);
42
42
  const configPath = options.config?.endsWith(".ts")
43
43
  ? resolve(options.config)
@@ -328,6 +328,7 @@ export async function startDevServer(options) {
328
328
  root: process.cwd(),
329
329
  server: {
330
330
  port,
331
+ host,
331
332
  strictPort: true,
332
333
  hmr: true,
333
334
  fs: {
@@ -382,7 +383,8 @@ export async function startDevServer(options) {
382
383
  });
383
384
  });
384
385
  await vite.listen();
385
- console.log(`\n Sourcey dev server running at http://localhost:${port}${config.baseUrl || "/"}`);
386
+ const displayHost = !host || host === "127.0.0.1" || host === "localhost" ? "localhost" : host;
387
+ console.log(`\n Sourcey dev server running at http://${displayHost}:${port}${config.baseUrl || "/"}`);
386
388
  console.log(` Watching: ${watchPaths.length} content file${watchPaths.length === 1 ? "" : "s"} + components + CSS (HMR)`);
387
389
  console.log(` Press Ctrl+C to stop\n`);
388
390
  fullRebuild().catch((err) => {
@@ -1 +1 @@
1
- {"version":3,"file":"site-url.d.ts","sourceRoot":"","sources":["../src/site-url.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoBrE;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,SAAK,EAAE,UAAU,GAAE,UAAkB,GAAG,MAAM,CAsBrG;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,SAAK,EACZ,UAAU,GAAE,UAAkB,GAC7B,MAAM,CAER;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,MAAM,CAcnE"}
1
+ {"version":3,"file":"site-url.d.ts","sourceRoot":"","sources":["../src/site-url.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoBrE;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,SAAK,EAAE,UAAU,GAAE,UAAkB,GAAG,MAAM,CAyBrG;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,SAAK,EACZ,UAAU,GAAE,UAAkB,GAC7B,MAAM,CAER;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,MAAM,CAcnE"}
package/dist/site-url.js CHANGED
@@ -32,6 +32,9 @@ export function toPublicPath(outputPath, baseUrl = "", prettyUrls = false) {
32
32
  const prefix = normalizedBase || "/";
33
33
  const cleanOutputPath = outputPath.replace(/^\/+/, "");
34
34
  if (!cleanOutputPath || cleanOutputPath === "index.html") {
35
+ if (prettyUrls === "strip" && normalizedBase) {
36
+ return normalizedBase.slice(0, -1);
37
+ }
35
38
  return prefix;
36
39
  }
37
40
  if (cleanOutputPath.endsWith("/index.html")) {
@@ -882,12 +882,46 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
882
882
  font-size: 1.05rem;
883
883
  line-height: 1.7;
884
884
  color: rgb(var(--color-gray-600));
885
+ max-width: 65ch;
886
+ text-wrap: pretty;
885
887
  }
886
888
 
887
889
  .dark #sourcey .sourcey-changelog-description {
888
890
  color: rgb(var(--color-gray-400));
889
891
  }
890
892
 
893
+ #sourcey .sourcey-changelog-description a {
894
+ color: rgb(var(--color-primary-ink));
895
+ text-decoration: none;
896
+ border-bottom: 1px solid rgb(var(--color-primary-ink) / 0.3);
897
+ }
898
+
899
+ #sourcey .sourcey-changelog-description a:hover {
900
+ border-bottom-color: rgb(var(--color-primary-ink));
901
+ }
902
+
903
+ .dark #sourcey .sourcey-changelog-description a {
904
+ color: rgb(var(--color-primary-light));
905
+ border-bottom-color: rgb(var(--color-primary-light) / 0.3);
906
+ }
907
+
908
+ .dark #sourcey .sourcey-changelog-description a:hover {
909
+ border-bottom-color: rgb(var(--color-primary-light));
910
+ }
911
+
912
+ #sourcey .sourcey-changelog-description code {
913
+ font-size: 0.92em;
914
+ padding: 0.05rem 0.3rem;
915
+ border-radius: 0.25rem;
916
+ background: rgb(var(--color-gray-100));
917
+ color: rgb(var(--color-gray-800));
918
+ }
919
+
920
+ .dark #sourcey .sourcey-changelog-description code {
921
+ background: rgb(255 255 255 / 0.08);
922
+ color: rgb(var(--color-gray-200));
923
+ }
924
+
891
925
  #sourcey .sourcey-changelog-list {
892
926
  display: flex;
893
927
  flex-direction: column;
@@ -907,7 +941,16 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
907
941
  }
908
942
 
909
943
  #sourcey .sourcey-changelog-version-unreleased {
910
- border-style: dashed;
944
+ border-color: rgb(var(--color-primary) / 0.18);
945
+ border-left: 3px solid rgb(var(--color-primary));
946
+ padding-left: calc(1.25rem - 2px);
947
+ background: linear-gradient(180deg, rgb(var(--color-primary) / 0.04), rgb(var(--color-primary) / 0.015));
948
+ }
949
+
950
+ .dark #sourcey .sourcey-changelog-version-unreleased {
951
+ border-color: rgb(var(--color-primary-light) / 0.22);
952
+ border-left-color: rgb(var(--color-primary-light));
953
+ background: linear-gradient(180deg, rgb(var(--color-primary-light) / 0.06), rgb(var(--color-primary-light) / 0.02));
911
954
  }
912
955
 
913
956
  #sourcey .sourcey-changelog-version-header {
@@ -1001,6 +1044,19 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
1001
1044
  color: rgb(var(--color-gray-300));
1002
1045
  }
1003
1046
 
1047
+ #sourcey .sourcey-changelog-pill-next {
1048
+ background: rgb(var(--color-primary) / 0.1);
1049
+ color: rgb(var(--color-primary-ink));
1050
+ text-transform: uppercase;
1051
+ letter-spacing: 0.06em;
1052
+ font-size: 0.68rem;
1053
+ }
1054
+
1055
+ .dark #sourcey .sourcey-changelog-pill-next {
1056
+ background: rgb(var(--color-primary-light) / 0.14);
1057
+ color: rgb(var(--color-primary-light));
1058
+ }
1059
+
1004
1060
  #sourcey .sourcey-changelog-summary {
1005
1061
  margin-bottom: 1rem;
1006
1062
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sourcey",
3
- "version": "3.5.7",
3
+ "version": "3.5.9",
4
4
  "description": "Precision documentation from OpenAPI, MCP, Doxygen, godoc, and Markdown. Static HTML you own.",
5
5
  "type": "module",
6
6
  "engines": {