@mandolin/jsdoc-theme-hia 0.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/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-07-05
4
+
5
+ ### Added
6
+
7
+ - Independent JSDoc theme entry.
8
+ - Standard doclet rendering for common JSDoc kinds.
9
+ - Navigation, search data and local filtering.
10
+ - Parameters, returns, properties and examples rendering.
11
+ - Source references with file links, line links and source preview.
12
+ - Runtime language switching from `doclet.hia.i18n`.
13
+ - Per-locale HTML output and `i18n-index.json`.
14
+ - Release checklist and third-party notices.
15
+ - Field-level multilingual rendering from `doclet.hia.i18n.fields`.
16
+ - Separate `Source` and `Source References` sections for definition source and explicit source references.
17
+ - Relative `Defined in` paths from HIA source metadata.
18
+ - Built-in English and Simplified Chinese UI labels with runtime switching support.
19
+ - Collapsible doclet cards and documentation sections.
20
+ - Theme UI options for collapse defaults and language control mode.
21
+ - Optional language select control for projects with more locales.
22
+ - Built-in theme skins: `classic`, `lumen` and `graphite`.
23
+ - Configurable source code display defaults and runtime controls.
24
+ - Release metadata declares public scoped publishing and records the publish strategy/checklist.
25
+
26
+ ### Notes
27
+
28
+ - This is an early public package for standalone JSDoc theme usage and HIA metadata experiments.
29
+ - Layout and API are still expected to evolve.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HIA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # @mandolin/jsdoc-theme-hia
2
+
3
+ Independent HIA theme for JSDoc.
4
+
5
+ `@mandolin/jsdoc-theme-hia` renders JSDoc output as a compact API documentation site with navigation, search data, source references, source preview and multilingual display support. It is designed to work as a normal JSDoc theme, and can also consume metadata produced by `@mandolin/jsdoc-plugin-hia-sys`.
6
+
7
+ GitHub: <https://github.com/mandolin/jsdoc-theme-hia>
8
+
9
+ ## Features
10
+
11
+ - Renders common JSDoc doclet kinds: module, class, function, member, constant and typedef.
12
+ - Displays function signatures, params, returns, properties and examples.
13
+ - Provides sidebar navigation and local search data.
14
+ - Reads `doclet.hia.source.definedIn` and `doclet.hia.source.primaryBlock` for definition source links and previews.
15
+ - Reads `doclet.hia.source.references` for explicit source references such as `@coderef`.
16
+ - Reads `doclet.hia.i18n.fields` for field-level multilingual descriptions.
17
+ - Includes built-in English and Simplified Chinese UI labels for runtime language switching and per-locale HTML output.
18
+ - Provides collapsible doclet cards and collapsible sections for params, returns, examples, source and metadata.
19
+ - Supports button or select language controls, with an automatic select mode for larger locale lists.
20
+ - Provides built-in theme skins: `classic`, `lumen` and `graphite`.
21
+ - Provides configurable source code display controls for font, size, line height, tab size and wrapping.
22
+ - Writes `search-index.json`, `i18n-index.json` and `hia-metadata.json`.
23
+ - Includes basic responsive layout and keyboard focus styles.
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ npm install --save-dev jsdoc @mandolin/jsdoc-theme-hia
29
+ ```
30
+
31
+ For HIA metadata support:
32
+
33
+ ```bash
34
+ npm install --save-dev jsdoc @mandolin/jsdoc-plugin-hia-sys @mandolin/jsdoc-theme-hia
35
+ ```
36
+
37
+ ## Basic Usage
38
+
39
+ Configure JSDoc to use the theme:
40
+
41
+ ```json
42
+ {
43
+ "source": {
44
+ "include": ["src"]
45
+ },
46
+ "opts": {
47
+ "template": "node_modules/@mandolin/jsdoc-theme-hia",
48
+ "destination": "docs/api",
49
+ "recurse": true
50
+ }
51
+ }
52
+ ```
53
+
54
+ To consume HIA metadata, load the companion plugin as well:
55
+
56
+ ```json
57
+ {
58
+ "plugins": ["node_modules/@mandolin/jsdoc-plugin-hia-sys/src/index.cjs"],
59
+ "source": {
60
+ "include": ["src"]
61
+ },
62
+ "opts": {
63
+ "template": "node_modules/@mandolin/jsdoc-theme-hia",
64
+ "destination": "docs/api",
65
+ "recurse": true,
66
+ "hia": {
67
+ "mode": "standalone",
68
+ "source": {
69
+ "link": {
70
+ "enabled": true,
71
+ "rootUrl": "https://github.com/example/project/blob/main"
72
+ },
73
+ "preview": {
74
+ "enabled": true,
75
+ "defaultExpanded": false
76
+ }
77
+ },
78
+ "i18n": {
79
+ "enabled": true,
80
+ "defaultLocale": "zh-CN",
81
+ "fallbackLocale": "en",
82
+ "locales": ["zh-CN", "en"],
83
+ "mode": "runtimeSwitch"
84
+ },
85
+ "theme": {
86
+ "skin": "classic",
87
+ "collapse": {
88
+ "docletsDefaultExpanded": true,
89
+ "sectionsDefaultExpanded": true,
90
+ "metadataDefaultExpanded": true
91
+ },
92
+ "languageControls": {
93
+ "mode": "auto",
94
+ "dropdownThreshold": 4
95
+ },
96
+ "code": {
97
+ "controls": true,
98
+ "fontFamily": "cascadia",
99
+ "fontSize": 12,
100
+ "lineHeight": 1.55,
101
+ "tabSize": 2,
102
+ "wrap": false
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ ## Generated Files
111
+
112
+ The theme writes the following files to the configured destination:
113
+
114
+ - `index.html`
115
+ - `index.{locale}.html`, such as `index.zh-CN.html`
116
+ - `hia-theme.css`
117
+ - `hia-theme.js`
118
+ - `search-index.json`
119
+ - `i18n-index.json`
120
+ - `hia-metadata.json`
121
+
122
+ ## Source Preview
123
+
124
+ When used with `@mandolin/jsdoc-plugin-hia-sys`, definition source metadata is rendered in a `Source` section using relative paths. Explicit `@coderef` metadata is rendered separately in a `Source References` section. Both sections can display file links, line links, range hints and collapsible source previews.
125
+
126
+ ## Multilingual Rendering
127
+
128
+ The theme supports two output styles from plugin metadata:
129
+
130
+ - `runtimeSwitch`: `index.html` includes language controls and switches localized blocks in the browser.
131
+ - `perLocale`: additional `index.{locale}.html` files are generated for individual locales.
132
+
133
+ The theme consumes field-level translations for descriptions, params, returns, properties and examples when available. Missing translations fall back to the configured fallback locale or to the original JSDoc text.
134
+
135
+ ## UI Options
136
+
137
+ Theme UI behavior can be configured under `opts.hia.theme`:
138
+
139
+ - `skin`: built-in skin name, currently `classic`, `lumen` or `graphite`.
140
+ - `collapse.docletsDefaultExpanded`: whether doclet cards are expanded by default.
141
+ - `collapse.sectionsDefaultExpanded`: whether content sections are expanded by default.
142
+ - `collapse.metadataDefaultExpanded`: whether metadata sections are expanded by default.
143
+ - `languageControls.mode`: `auto`, `buttons` or `select`.
144
+ - `languageControls.dropdownThreshold`: locale count at which `auto` switches from buttons to a select control.
145
+ - `code.controls`: whether generated pages include runtime code display controls.
146
+ - `code.fontFamily`: default source code font preset, currently `cascadia`, `consolas`, `mono` or `system`.
147
+ - `code.fontSize`: default source code font size in pixels.
148
+ - `code.lineHeight`: default source code line height.
149
+ - `code.tabSize`: default source code tab size.
150
+ - `code.wrap`: whether source code wraps by default.
151
+
152
+ ## Scripts
153
+
154
+ ```bash
155
+ npm run check:syntax
156
+ npm test
157
+ npm run test:jsdoc
158
+ npm run release:check
159
+ npm run test:all
160
+ ```
161
+
162
+ `npm test` checks renderer fixtures. `npm run test:jsdoc` builds the bundled example with real JSDoc. `npm run release:check` validates package metadata and required release files.
163
+
164
+ ## Compatibility
165
+
166
+ - Node.js 18 or newer.
167
+ - JSDoc 4.x.
168
+ - CommonJS theme entry.
169
+
170
+ ## Stability
171
+
172
+ Version `0.1.0` is an early public package. The theme is usable for small JSDoc projects and metadata experiments, but the rendering contract may evolve before a stable release.
173
+
174
+ ## License
175
+
176
+ MIT
@@ -0,0 +1,43 @@
1
+ # Release Checklist
2
+
3
+ ## Scope
4
+
5
+ Package: `@mandolin/jsdoc-theme-hia`
6
+
7
+ Version: `0.1.0`
8
+
9
+ ## Required Checks
10
+
11
+ - [ ] `npm run check:syntax`
12
+ - [ ] `npm test`
13
+ - [ ] `npm run test:jsdoc`
14
+ - [ ] `npm run clean:examples`
15
+ - [ ] `npm run release:check`
16
+ - [ ] `npm run test:all`
17
+ - [ ] `npm pack --dry-run --json`
18
+
19
+ ## Manual Review
20
+
21
+ - [ ] README describes standard JSDoc rendering, source preview and i18n.
22
+ - [ ] `examples/basic/README.md` explains the example.
23
+ - [ ] Desktop layout is usable.
24
+ - [ ] Mobile layout is usable.
25
+ - [ ] Keyboard focus is visible.
26
+ - [ ] `THIRD_PARTY_NOTICES.md` is current.
27
+ - [ ] `CHANGELOG.md` has the target version.
28
+ - [ ] `package.json` keeps `publishConfig.access` as `public`.
29
+ - [ ] Dry-run artifact contents are limited to theme sources, static assets, examples and release docs.
30
+ - [ ] `examples/basic/out` is not present.
31
+ - [ ] No `.tgz` dry-run tarball remains.
32
+
33
+ ## Publish Strategy
34
+
35
+ - Keep version `0.1.0` for the first public package unless registry preflight shows it is already published.
36
+ - Use `npm publish --access public` for the scoped package.
37
+ - If publishing before W-P3.5 HIA Integration hardening, publish with `--tag next` and avoid promoting to `latest` until the integration producer contract is confirmed.
38
+
39
+ ## Current Boundaries
40
+
41
+ - This is a single-page theme with per-locale HTML variants.
42
+ - Search is local filtering, not a full search engine.
43
+ - The theme is optimized for the JPHS metadata contract first.
@@ -0,0 +1,23 @@
1
+ # Third Party Notices
2
+
3
+ ## Runtime Dependencies
4
+
5
+ This theme has no bundled runtime dependency besides Node.js built-ins and browser APIs.
6
+
7
+ ## Peer Dependencies
8
+
9
+ - `jsdoc` `^4.0.0` (`Apache-2.0`)
10
+
11
+ `jsdoc` is expected to be installed by the consuming project or used through this package's development environment.
12
+
13
+ ## Development Dependencies
14
+
15
+ - `jsdoc` `^4.0.5` (`Apache-2.0`)
16
+
17
+ ## Assets
18
+
19
+ No third-party images, icon sets, fonts, copied Docdash code, or external CSS frameworks are bundled.
20
+
21
+ ## Legacy Material
22
+
23
+ Older `docdash-hia` ideas were used as design reference only. This theme is a new implementation and does not copy source files from Docdash or the old repository.
@@ -0,0 +1,29 @@
1
+ # Basic Example
2
+
3
+ This example shows the core theme features:
4
+
5
+ - JSDoc theme loading.
6
+ - Standard JSDoc API rendering.
7
+ - Source references from `jsdoc-plugin-hia-sys`.
8
+ - Runtime language switching.
9
+ - Per-locale HTML output.
10
+ - Search data and local filtering.
11
+
12
+ Run:
13
+
14
+ ```bash
15
+ npm run test:jsdoc
16
+ ```
17
+
18
+ Expected generated files under `examples/basic/out`:
19
+
20
+ - `index.html`
21
+ - `index.zh-CN.html`
22
+ - `index.en.html`
23
+ - `search-index.json`
24
+ - `i18n-index.json`
25
+ - `hia-metadata.json`
26
+ - `hia-theme.css`
27
+ - `hia-theme.js`
28
+
29
+ Generated files are test artifacts and should not be committed.
@@ -0,0 +1,52 @@
1
+ {
2
+ "plugins": ["../jsdoc-plugin-hia-sys/src/index.cjs"],
3
+ "source": {
4
+ "include": ["examples/basic/src"]
5
+ },
6
+ "opts": {
7
+ "template": ".",
8
+ "destination": "examples/basic/out",
9
+ "recurse": true,
10
+ "hia": {
11
+ "mode": "standalone",
12
+ "source": {
13
+ "link": {
14
+ "enabled": true,
15
+ "rootUrl": "https://example.invalid/hia-docs",
16
+ "openMode": "new-tab"
17
+ },
18
+ "preview": {
19
+ "enabled": true,
20
+ "defaultExpanded": false
21
+ }
22
+ },
23
+ "i18n": {
24
+ "enabled": true,
25
+ "defaultLocale": "zh-CN",
26
+ "fallbackLocale": "en",
27
+ "locales": ["zh-CN", "en"],
28
+ "mode": "runtimeSwitch"
29
+ },
30
+ "theme": {
31
+ "skin": "classic",
32
+ "collapse": {
33
+ "docletsDefaultExpanded": true,
34
+ "sectionsDefaultExpanded": true,
35
+ "metadataDefaultExpanded": true
36
+ },
37
+ "languageControls": {
38
+ "mode": "auto",
39
+ "dropdownThreshold": 4
40
+ },
41
+ "code": {
42
+ "controls": true,
43
+ "fontFamily": "cascadia",
44
+ "fontSize": 12,
45
+ "lineHeight": 1.55,
46
+ "tabSize": 2,
47
+ "wrap": false
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Theme demo module.
5
+ *
6
+ * @module theme
7
+ */
8
+
9
+ /**
10
+ * Theme rendering options.
11
+ *
12
+ * @typedef {Object} ThemeOptions
13
+ * @property {string} [locale=en] Locale code.
14
+ * @property {boolean} [excited=false] Adds punctuation to the rendered text.
15
+ */
16
+
17
+ /**
18
+ * Stateful theme renderer.
19
+ *
20
+ * @class
21
+ * @classdesc Wraps the demo rendering function for class rendering coverage.
22
+ * @param {ThemeOptions} [options] Default rendering options.
23
+ */
24
+ class ThemeRenderer {
25
+ constructor(options = {}) {
26
+ this.options = options;
27
+ }
28
+
29
+ /**
30
+ * Render a message.
31
+ *
32
+ * @param {string} name Display name.
33
+ * @returns {string} Rendered message.
34
+ */
35
+ render(name) {
36
+ return themeDemo(name, this.options);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Theme demo function.
42
+ *
43
+ * @function themeDemo
44
+ * @param {string} name Display name.
45
+ * @param {ThemeOptions} [options] Rendering options.
46
+ * @returns {string} Demo text.
47
+ * @example <caption>Basic rendering</caption>
48
+ * // @coderef THEME_DEMO_BODY
49
+ * @coderef THEME_DEMO_BODY
50
+ * @hiaKey theme.demo
51
+ * @hiaText zh-CN 主题演示函数。
52
+ * @hiaText en Theme demo function.
53
+ */
54
+ function themeDemo(name, options = {}) {
55
+ /* @codeblock THEME_DEMO_BODY */
56
+ const locale = options.locale || "en";
57
+ const message = locale === "zh-CN" ? `你好,${name}` : `Hello, ${name}`;
58
+ return options.excited ? `${message}!` : message;
59
+ /* @codeblockend THEME_DEMO_BODY */
60
+ }
61
+
62
+ module.exports = {
63
+ ThemeRenderer,
64
+ themeDemo
65
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@mandolin/jsdoc-theme-hia",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Independent HIA theme for JSDoc.",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/mandolin/jsdoc-theme-hia.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/mandolin/jsdoc-theme-hia/issues"
13
+ },
14
+ "homepage": "https://github.com/mandolin/jsdoc-theme-hia#readme",
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "main": "publish.js",
19
+ "files": [
20
+ "publish.js",
21
+ "src",
22
+ "static",
23
+ "examples/basic/jsdoc.conf.json",
24
+ "examples/basic/README.md",
25
+ "examples/basic/src",
26
+ "README.md",
27
+ "CHANGELOG.md",
28
+ "RELEASE_CHECKLIST.md",
29
+ "THIRD_PARTY_NOTICES.md",
30
+ "LICENSE"
31
+ ],
32
+ "scripts": {
33
+ "check:syntax": "node --check publish.js && node --check src/metadata-reader.cjs && node --check src/render.cjs && node --check static/hia-theme.js && node --check test/render-fixture.cjs && node --check scripts/clean-generated.cjs && node --check scripts/release-check.cjs",
34
+ "clean:examples": "node scripts/clean-generated.cjs",
35
+ "release:check": "node scripts/release-check.cjs && npm pack --dry-run",
36
+ "test": "node test/render-fixture.cjs",
37
+ "test:jsdoc": "npx --yes jsdoc@4.0.5 -c examples/basic/jsdoc.conf.json",
38
+ "test:all": "npm run check:syntax && npm test && npm run test:jsdoc && npm run clean:examples && npm run release:check"
39
+ },
40
+ "keywords": [
41
+ "jsdoc",
42
+ "jsdoc-theme",
43
+ "theme",
44
+ "hia",
45
+ "documentation",
46
+ "source-preview",
47
+ "i18n"
48
+ ],
49
+ "peerDependencies": {
50
+ "jsdoc": "^4.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "jsdoc": "^4.0.5"
54
+ },
55
+ "engines": {
56
+ "node": ">=18"
57
+ }
58
+ }
package/publish.js ADDED
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const {
6
+ buildI18nPageData,
7
+ buildSearchIndex,
8
+ renderPage
9
+ } = require("./src/render.cjs");
10
+ const {
11
+ collectPageI18n,
12
+ summarizeHiaMetadata
13
+ } = require("./src/metadata-reader.cjs");
14
+
15
+ function getDoclets(data) {
16
+ if (typeof data !== "function") {
17
+ return [];
18
+ }
19
+
20
+ const seen = new Set();
21
+
22
+ return data()
23
+ .get()
24
+ .filter((doclet) => doclet.kind && doclet.kind !== "package" && !doclet.undocumented)
25
+ .filter((doclet) => {
26
+ const key = `${doclet.kind}:${doclet.longname || doclet.name || ""}`;
27
+
28
+ if (seen.has(key)) {
29
+ return false;
30
+ }
31
+
32
+ seen.add(key);
33
+ return true;
34
+ });
35
+ }
36
+
37
+ function writeFile(filePath, content) {
38
+ fs.mkdirSync(path.dirname(filePath), {
39
+ recursive: true
40
+ });
41
+ fs.writeFileSync(filePath, content, "utf8");
42
+ }
43
+
44
+ function copyStatic(destination) {
45
+ const css = fs.readFileSync(path.resolve(__dirname, "static/hia-theme.css"), "utf8");
46
+ const js = fs.readFileSync(path.resolve(__dirname, "static/hia-theme.js"), "utf8");
47
+
48
+ writeFile(path.join(destination, "hia-theme.css"), css);
49
+ writeFile(path.join(destination, "hia-theme.js"), js);
50
+ }
51
+
52
+ function getThemeOptions(opts) {
53
+ return opts && opts.hia && opts.hia.theme && typeof opts.hia.theme === "object"
54
+ ? opts.hia.theme
55
+ : {};
56
+ }
57
+
58
+ function publish(data, opts) {
59
+ const destination = path.resolve(opts.destination || "out");
60
+ const doclets = getDoclets(data);
61
+ const pageI18n = collectPageI18n(doclets);
62
+ const searchIndex = buildSearchIndex(doclets);
63
+ const theme = getThemeOptions(opts);
64
+ const page = renderPage({
65
+ title: "HIA JSDoc",
66
+ doclets,
67
+ theme
68
+ });
69
+
70
+ fs.mkdirSync(destination, {
71
+ recursive: true
72
+ });
73
+
74
+ copyStatic(destination);
75
+ writeFile(path.join(destination, "index.html"), page);
76
+ if (pageI18n.enabled) {
77
+ for (const locale of pageI18n.locales) {
78
+ writeFile(
79
+ path.join(destination, `index.${locale}.html`),
80
+ renderPage({
81
+ title: "HIA JSDoc",
82
+ doclets,
83
+ locale,
84
+ theme
85
+ })
86
+ );
87
+ }
88
+
89
+ writeFile(
90
+ path.join(destination, "i18n-index.json"),
91
+ JSON.stringify(buildI18nPageData(pageI18n), null, 2)
92
+ );
93
+ }
94
+ writeFile(path.join(destination, "search-index.json"), JSON.stringify(searchIndex, null, 2));
95
+ writeFile(
96
+ path.join(destination, "hia-metadata.json"),
97
+ JSON.stringify(
98
+ doclets.map((doclet) => ({
99
+ name: doclet.name || "",
100
+ longname: doclet.longname || "",
101
+ kind: doclet.kind || "",
102
+ hia: summarizeHiaMetadata(doclet)
103
+ })),
104
+ null,
105
+ 2
106
+ )
107
+ );
108
+ }
109
+
110
+ exports.publish = publish;