diff --git a/.gitignore b/.gitignore index ac208343158..17893a700a5 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,5 @@ internal/documentation/.vitepress/dist internal/documentation/.vitepress/cache internal/documentation/dist internal/documentation/schema/* -internal/documentation/tmp +internal/documentation/docs/api +internal/documentation/jsdoc/docdash \ No newline at end of file diff --git a/REUSE.toml b/REUSE.toml index d24ecb5ecce..44c2c39857c 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -9,4 +9,3 @@ path = "**" precedence = "aggregate" SPDX-FileCopyrightText = "2026 SAP SE or an SAP affiliate company and UI5 CLI contributors" SPDX-License-Identifier = "Apache-2.0" - diff --git a/internal/documentation/.vitepress/config.ts b/internal/documentation/.vitepress/config.ts index ab2c702f67f..48ede26c4e7 100644 --- a/internal/documentation/.vitepress/config.ts +++ b/internal/documentation/.vitepress/config.ts @@ -5,6 +5,10 @@ import { defineConfig } from "vitepress"; // markdown import MarkdownItImplicitFigures from "markdown-it-implicit-figures"; +// api docs +import * as path from "node:path"; +import * as fs from "node:fs"; + export default defineConfig({ // Would be set in CI job via CLI arguments. For local development, it's just root. @@ -36,30 +40,30 @@ export default defineConfig({ ] ], - themeConfig: { + themeConfig: { - logo: { - light: "/images/Logo_B_RGB.png", - dark: "/images/Logo_O_RGB.png" - }, - externalLinkIcon: false, - outline: [1, 3], + logo: { + light: "/images/Logo_B_RGB.png", + dark: "/images/Logo_O_RGB.png" + }, + externalLinkIcon: false, + outline: [1, 3], - nav: nav(), + nav: nav(), - sidebar: { - "/": guide(), - }, + sidebar: { + "/": guide(), + }, - socialLinks: [ + socialLinks: [ - { icon: "github", link: "https://github.com/UI5/cli" }, - ], + { icon: "github", link: "https://github.com/UI5/cli" }, + ], - footer: { + footer: { - message: ` + message: ` © Copyright ${new Date().getFullYear()}, SAP SE and UI5 CLI Contributors
Legal Disclosure Terms of Use @@ -68,222 +72,304 @@ export default defineConfig({ `, - }, + }, - search: { - provider: "local", - //hotKeys: [], // disable hotkeys to avoid search while using UI5 web components input - }, - - - - }, + search: { + provider: "local", + //hotKeys: [], // disable hotkeys to avoid search while using UI5 web components input + }, + }, - markdown: { - // Configure the Markdown-it instance - config: (md) => { - // https://www.npmjs.com/package/markdown-it-implicit-figures - md.use(MarkdownItImplicitFigures, { - figcaption: true, - }); - }, - }, + markdown: { + // Configure the Markdown-it instance + config: (md) => { + // https://www.npmjs.com/package/markdown-it-implicit-figures + md.use(MarkdownItImplicitFigures, { + figcaption: true, + }); + }, + }, - vite: { - build: { - chunkSizeWarningLimit: 4000, // chunk for local search index dominates - } - } + vite: { + build: { + chunkSizeWarningLimit: 4000, // chunk for local search index dominates + }, + } }); function nav() { - return [ - { - - text: 'V5', - items: [ - { - text: 'V4', - link: `/../v4/`, - target: "_self" - }, - { - text: 'V3', - link: `/../v3/`, - target: "_self" - }, - { - text: 'V2', - link: `/../v2/`, - target: "_self" - } - ] - }, - ]; + return [ + { + + text: 'V5', + items: [ + { + text: 'V4', + link: `/../v4/`, + target: "_self" + }, + { + text: 'V3', + link: `/../v3/`, + target: "_self" + }, + { + text: 'V2', + link: `/../v2/`, + target: "_self" + } + ] + }, + ]; } function guide() { - return [ - - { - text: "Introduction", - collapsed: false, - - items: [ - - { - text: "Home", - link: "/", - }, - { - text: "Getting Started", - link: "/pages/GettingStarted", - }, - - ], - - }, - { - text: "UI5 CLI", - collapsed: true, - link: "/pages/CLI", - - - }, - { - text: "Configuration", - collapsed: true, - - link: "/pages/Configuration", - - }, - { - text: "Development", - collapsed: false, - items: [ - { - text: "Overview", - link: "/pages/Overview", - }, - { - text: "OpenUI5", - link: "/pages/OpenUI5", - }, - { - text: "SAPUI5", - link: "/pages/SAPUI5", - }, - { - text: "Workspace", - link: "/pages/Workspace", - }, - - ], - }, - - { - text: "Extensibility", - collapsed: false, - items: [ - { - text: "Custom Tasks", - link: "/pages/extensibility/CustomTasks", - }, - { - text: "Custom Server Middleware", - link: "/pages/extensibility/CustomServerMiddleware", - }, - { - text: "Project Shims", - link: "/pages/extensibility/ProjectShims", - }, - ], - }, - { - text: "Modules", - collapsed: false, - items: [ - { - text: "Server", - link: "/pages/Server", - }, - { - text: "Builder", - link: "/pages/Builder", - }, - { - text: "Project", - link: "/pages/Project", - }, - { - text: "File System", - link: "/pages/FileSystem", - }, - ], - }, - { - text: "FAQ", - collapsed: false, - link: "/pages/FAQ", - - }, - { - text: "Upgrade Guides", - collapsed: false, - items: [ - { - text: "Migrate to v5", - link: "/updates/migrate-v5", - }, - { - text: "Migrate to v4", - link: "/updates/migrate-v4", - }, - { - text: "Migrate to v3", - link: "/updates/migrate-v3", - }, - { - text: "Migrate to v2", - link: "/updates/migrate-v2", - }, - { - text: "Migrate to v1", - link: "/updates/migrate-v1", - }, - ], - }, - { - text: "Miscellaneous", - collapsed: false, - items: [ - { - text: "Troubleshooting", - link: "/pages/Troubleshooting", - }, - { - text: "Benchmarking", - link: "/pages/Benchmarking", - }, - { - text: "ECMAScript Support", - link: "/pages/ESSupport", - }, - { - text: "Code Analysis", - link: "/pages/CodeAnalysis", - }, - ], - }, - { - text: "API Reference", - link: "/api/index.html", - target: "_blank" - - }, - - ]; + return [ + + { + text: "Introduction", + collapsed: false, + + items: [ + + { + text: "Home", + link: "/", + }, + { + text: "Getting Started", + link: "/pages/GettingStarted", + }, + + ], + + }, + { + text: "UI5 CLI", + collapsed: true, + link: "/pages/CLI", + + + }, + { + text: "Configuration", + collapsed: true, + + link: "/pages/Configuration", + + }, + { + text: "Development", + collapsed: false, + items: [ + { + text: "Overview", + link: "/pages/Overview", + }, + { + text: "OpenUI5", + link: "/pages/OpenUI5", + }, + { + text: "SAPUI5", + link: "/pages/SAPUI5", + }, + { + text: "Workspace", + link: "/pages/Workspace", + }, + + ], + }, + + { + text: "Extensibility", + collapsed: false, + items: [ + { + text: "Custom Tasks", + link: "/pages/extensibility/CustomTasks", + }, + { + text: "Custom Server Middleware", + link: "/pages/extensibility/CustomServerMiddleware", + }, + { + text: "Project Shims", + link: "/pages/extensibility/ProjectShims", + }, + ], + }, + { + text: "Modules", + collapsed: false, + items: [ + { + text: "Server", + link: "/pages/Server", + }, + { + text: "Builder", + link: "/pages/Builder", + }, + { + text: "Project", + link: "/pages/Project", + }, + { + text: "File System", + link: "/pages/FileSystem", + }, + ], + }, + { + text: "FAQ", + collapsed: false, + link: "/pages/FAQ", + + }, + { + text: "Upgrade Guides", + collapsed: false, + items: [ + { + text: "Migrate to v5", + link: "/updates/migrate-v5", + }, + { + text: "Migrate to v4", + link: "/updates/migrate-v4", + }, + { + text: "Migrate to v3", + link: "/updates/migrate-v3", + }, + { + text: "Migrate to v2", + link: "/updates/migrate-v2", + }, + { + text: "Migrate to v1", + link: "/updates/migrate-v1", + }, + ], + }, + { + text: "Miscellaneous", + collapsed: false, + items: [ + { + text: "Troubleshooting", + link: "/pages/Troubleshooting", + }, + { + text: "Benchmarking", + link: "/pages/Benchmarking", + }, + { + text: "ECMAScript Support", + link: "/pages/ESSupport", + }, + { + text: "Code Analysis", + link: "/pages/CodeAnalysis", + }, + ], + }, + (() => { + // This function builds the tree for the api docs + const tree = { + text: "API", + collapsed: false, + items: [{ + text: "@ui5", + items: [] + }] + } + + for (let file of fs.readdirSync(path.join("docs", "api"))) { + file = file.replace(".md", ""); + const treePath = file.replace("module-", "").split("_"); + appendToTree(tree, file, treePath, 0); + } + + function appendToTree(tree, file, treePath, index) { + // If it's the last leaf + if (treePath.length - 1 === index) { + tree.items.push({ + text: treePath[index].replace("module-", ""), + link: "/api/" + file + }); + return; + } + + // All functions below call appendToTree recursively to create the tree structure + let found = false; + // Checks if the leaf does already exist and adds new leafs to it + for (const treeItem of tree.items) { + if (treeItem.text === treePath[index]) { + appendToTree(treeItem, file, treePath, index+1); + found = true; + break; + } + } + // Creates a new leaf for the entry and adds leafs inside of it + if (!found) { + let newItem = { + text: treePath[index].replace("module-", ""), + collapsed: treePath[index] !== "@ui5", + items: [] + } + appendToTree(newItem, file, treePath, index+1); + tree.items.push(newItem); + } + } + + // Display items inside @ui5 as root + tree.items = tree.items[0].items; + + const moveIndex = []; + + for (let index = 0; index < tree.items.length; index++) { + const treeItem = tree.items[index]; + + // Adds @ui5 prefix to all leafs in the first level + if (!treeItem.link) treeItem.text = "@ui5/" + treeItem.text; + + // Finds leafs that have a similar name in first level e.g. @ui5/sever and server + // It adds all found items into moveIndex so that they can later be moved into the corresponding package leaf as main + if (treeItem.link) { + let to; + for (let index2 = 0; index2 < tree.items.length; index2++) { + const item = tree.items[index2]; + if (!item.link && item.text.replace("@ui5/", "") === treeItem.text.replace("@ui5/", "")) { + to = index2; + break; + } + } + + if (to !== undefined && to !== null) { + moveIndex.push({ + from: index, + to: to + }); + } + } + } + + // Iterates through the moveIndex and moves the items + // Reverse is that it adds main to the beginning instead of the end + for (const moveItem of moveIndex) { + const item = tree.items[moveItem.from]; + item.text = "main"; + tree.items[moveItem.to].items.unshift(item); + delete tree.items[moveItem.from]; + } + + return tree; + })() + ]; } diff --git a/internal/documentation/.vitepress/theme/apidocs.css b/internal/documentation/.vitepress/theme/apidocs.css new file mode 100644 index 00000000000..ea5211085d9 --- /dev/null +++ b/internal/documentation/.vitepress/theme/apidocs.css @@ -0,0 +1,19 @@ +/** + JSDoc Function Highlighting + */ +.jsdoc-object { + background-color: var(--vp-c-bg-soft); + padding: 15px; +} + +.jsdoc-object .type-signature { + color: var(--vp-c-brand-2); +} + +.jsdoc-object .signature { + color: var(--vp-c-brand-1); +} + +.jsdoc-object .signature .signature-attributes { + font-size: 11px; +} diff --git a/internal/documentation/.vitepress/theme/custom.css b/internal/documentation/.vitepress/theme/custom.css index e666cba1d66..d7cac3bfd3b 100644 --- a/internal/documentation/.vitepress/theme/custom.css +++ b/internal/documentation/.vitepress/theme/custom.css @@ -14,14 +14,14 @@ /* Water */ --ui5-water-main: #1873b4; /* denim-600 */ - --ui5-water-secondary: #53b8de; /* viking-400 */ + --ui5-water-secondary: #53b8de; /* viking-400 */ --ui5-water-background: #ffffff; /* white */ /* Tailwind CSS Color Generator ** https://uicolors.app/create */ - /* VP */ + /* VP */ /* The most solid color used mainly for colored text. */ --vp-c-brand-1: #1873b4; /* lochmara-600 */ /* The color used mainly for hover state of the button. */ @@ -32,7 +32,14 @@ /* The soft color must be semi transparent alpha channel. */ /*--vp-c-brand-soft: rgba(12, 72, 120, 0.14);*/ /* --brand-dark-blue */ --vp-c-brand-soft: rgba(3, 103, 161, 0.14); /* lochmara-700 */ + + /* Makes the page wider for the api docs */ + --vp-layout-max-width: 80%; + + /* Makes the sidebar wider */ + --vp-sidebar-width: 300px; } + .dark { /* The most solid color used mainly for colored text. */ --vp-c-brand-1: #ff5a37; /* lochmara-600 */ @@ -44,15 +51,15 @@ /* The bg color used for main screen */ --vp-c-bg: #000000; /* The alternative bg color used in places such as "sidebar" or "code block". */ - + /* The elevated bg color. This is used at parts where it "floats", such as "dialog". */ /*--vp-c-bg-elv: red;*/ /* #1d2025;*/ - /* The bg color to slightly ditinguish some components from the page. - ** Used for things like "carbon ads" or "table". + /* The bg color to slightly ditinguish some components from the page. + ** Used for things like "carbon ads" or "table". */ --vp-c-bg-soft: #2b313a; /* 202127 */ - /* This is used for separators. This is used to divide sections within the same components, - ** such as having separator on "h2" heading. + /* This is used for separators. This is used to divide sections within the same components, + ** such as having separator on "h2" heading. */ --vp-c-divider: rgba(82,82,89,0.32); /*#2e2e32;*/ /* This is designed for borders on interactive components. @@ -86,7 +93,7 @@ } /* Default KBD - ** https://flowbite.com/docs/components/kbd/ + ** https://flowbite.com/docs/components/kbd/ */ .u-kbd { @apply px-2 py-1 text-xs font-semibold text-gray-800 bg-gray-50 border border-gray-300 rounded-lg dark:bg-gray-600 dark:text-gray-100 dark:border-gray-500; @@ -142,7 +149,7 @@ * Custom Block * -------------------------------------------------------------------------- */ .vp-doc .custom-block { - padding: 16px; + padding: 16px; } .vp-doc .custom-block.tip { @@ -301,3 +308,23 @@ li .learn-more { margin-right: 5px; vertical-align: middle; } + +/** +* Vitepress content width fix +* This expands the content to fit more stuff +* -------------------------------------------------------------------------- */ +.VPDoc.has-aside .content-container { + max-width: 100% !important; +} + +/** +* This makes the header anchor appear left next to the method names +* again + */ +.jsdoc-object + .header-anchor { + padding: 15px; +} + +.VPSidebarItem p { + overflow-wrap: anywhere !important; +} diff --git a/internal/documentation/.vitepress/theme/index.ts b/internal/documentation/.vitepress/theme/index.ts index 82c2a17338e..5bb7828edd7 100644 --- a/internal/documentation/.vitepress/theme/index.ts +++ b/internal/documentation/.vitepress/theme/index.ts @@ -5,6 +5,7 @@ import { onMounted, watch, nextTick } from "vue"; // custom css import "./custom.css"; +import "./apidocs.css"; // global components import Badgen from "@theme/components/Badgen.vue"; @@ -25,7 +26,7 @@ export default { }, setup() { - // this function will be executed inside VitePressApp's setup hook. + // this function will be executed inside VitePressApp's setup hook. // all composition APIs are available here. const route = useRoute(); let initZoom: () => void; diff --git a/internal/documentation/jsdoc/jsdoc-workspace.json b/internal/documentation/jsdoc/jsdoc-workspace.json index 92340614658..f0eccb0489d 100644 --- a/internal/documentation/jsdoc/jsdoc-workspace.json +++ b/internal/documentation/jsdoc/jsdoc-workspace.json @@ -18,7 +18,7 @@ ], "opts": { "encoding": "utf8", - "destination": "dist/api/", + "destination": "docs/api/", "recurse": true, "verbose": true, "access": "public" @@ -27,11 +27,7 @@ "cleverLinks": false, "monospaceLinks": false, "default": { - "useLongnameInNav": true, - "layoutFile": "jsdoc/templates/layout.tmpl", - "staticFiles": { - "include": ["jsdoc/templates/custom.css"] - } + "useLongnameInNav": true } }, "openGraph": { @@ -66,6 +62,7 @@ "class": "menu-item", "id": "github_link" } - } + }, + "githubSourceBaseUrl": "https://github.com/UI5/cli/blob/main/packages" } } diff --git a/internal/documentation/jsdoc/jsdoc.json b/internal/documentation/jsdoc/jsdoc.json index ab5fdc7dfee..3a8af30993d 100644 --- a/internal/documentation/jsdoc/jsdoc.json +++ b/internal/documentation/jsdoc/jsdoc.json @@ -17,7 +17,7 @@ ], "opts": { "encoding": "utf8", - "destination": "dist/api/", + "destination": "docs/api/", "recurse": true, "verbose": true, "access": "public" @@ -26,11 +26,7 @@ "cleverLinks": false, "monospaceLinks": false, "default": { - "useLongnameInNav": true, - "layoutFile": "jsdoc/templates/layout.tmpl", - "staticFiles": { - "include": ["jsdoc/templates/custom.css"] - } + "useLongnameInNav": true } }, "openGraph": { @@ -65,6 +61,7 @@ "class": "menu-item", "id": "github_link" } - } + }, + "githubSourceBaseUrl": "https://github.com/UI5/cli/blob/main/packages/" } } diff --git a/internal/documentation/jsdoc/patches/publish.js.patch b/internal/documentation/jsdoc/patches/publish.js.patch new file mode 100644 index 00000000000..49dc45aa69c --- /dev/null +++ b/internal/documentation/jsdoc/patches/publish.js.patch @@ -0,0 +1,1398 @@ +diff --git a/internal/documentation/jsdoc/docdash/publish.js b/internal/documentation/jsdoc/docdash/publish.js +index 5894d8327..22e75d348 100644 +--- a/internal/documentation/jsdoc/docdash/publish.js ++++ b/internal/documentation/jsdoc/docdash/publish.js +@@ -4,281 +4,237 @@ + var doop = require('jsdoc/util/doop'); + var fs = require('jsdoc/fs'); + var helper = require('jsdoc/util/templateHelper'); +-var logger = require('jsdoc/util/logger'); + var path = require('jsdoc/path'); + var taffy = require('@jsdoc/salty').taffy; + var template = require('jsdoc/template'); +-var util = require('util'); ++var util = require('node:util'); + + var htmlsafe = helper.htmlsafe; +-var linkto = helper.linkto; + var resolveAuthorLinks = helper.resolveAuthorLinks; +-var scopeToPunc = helper.scopeToPunc; +-var hasOwnProp = Object.prototype.hasOwnProperty; + + var data; + var view; + +-var outdir = path.normalize(env.opts.destination); ++// Modified to be able to link source files to GitHub ++var githubSourceBaseUrl; + +-function copyFile(source, target, cb) { +- var cbCalled = false; +- +- var rd = fs.createReadStream(source); +- rd.on("error", function(err) { +- done(err); +- }); +- var wr = fs.createWriteStream(target); +- wr.on("error", function(err) { +- done(err); +- }); +- wr.on("close", function(ex) { +- done(); +- }); +- rd.pipe(wr); +- +- function done(err) { +- if (!cbCalled) { +- cb(err); +- cbCalled = true; +- } +- } +-} ++var outdir = path.normalize(env.opts.destination); + + function find(spec) { +- return helper.find(data, spec); ++ return helper.find(data, spec); + } + + function tutoriallink(tutorial) { +- return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); ++ return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: '' }); + } + + function getAncestorLinks(doclet) { +- return helper.getAncestorLinks(data, doclet); ++ return helper.getAncestorLinks(data, doclet); + } + ++// Modified to output Markdown style links + function hashToLink(doclet, hash) { +- if ( !/^(#.+)/.test(hash) ) { return hash; } ++ if ( !/^(#.+)/.test(hash) ) { return hash; } + +- var url = helper.createLink(doclet); ++ var url = helper.createLink(doclet); + +- url = url.replace(/(#.+|$)/, hash); +- return '' + hash + ''; ++ url = url.replace(/(#.+|$)/, hash); ++ return '[' + hash + '](' + url + ')'; + } + + function needsSignature(doclet) { +- var needsSig = false; +- +- // function and class definitions always get a signature +- if (doclet.kind === 'function' || doclet.kind === 'class' && !doclet.hideconstructor) { +- needsSig = true; +- } +- // typedefs that contain functions get a signature, too +- else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && +- doclet.type.names.length) { +- for (var i = 0, l = doclet.type.names.length; i < l; i++) { +- if (doclet.type.names[i].toLowerCase() === 'function') { +- needsSig = true; +- break; +- } +- } +- } +- // and namespaces that are functions get a signature (but finding them is a +- // bit messy) +- else if (doclet.kind === 'namespace' && doclet.meta && doclet.meta.code && +- doclet.meta.code.type && doclet.meta.code.type.match(/[Ff]unction/)) { +- needsSig = true; +- } +- +- return needsSig; ++ var needsSig = false; ++ ++ // function and class definitions always get a signature ++ if (doclet.kind === 'function' || doclet.kind === 'class') { ++ needsSig = true; ++ } ++ // typedefs that contain functions get a signature, too ++ else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && ++ doclet.type.names.length) { ++ for (var i = 0, l = doclet.type.names.length; i < l; i++) { ++ if (doclet.type.names[i].toLowerCase() === 'function') { ++ needsSig = true; ++ break; ++ } ++ } ++ } ++ ++ return needsSig; + } + + function getSignatureAttributes(item) { +- var attributes = []; ++ var attributes = []; + +- if (item.optional) { +- attributes.push('opt'); +- } ++ if (item.optional) { ++ attributes.push('opt'); ++ } + +- if (item.nullable === true) { +- attributes.push('nullable'); +- } +- else if (item.nullable === false) { +- attributes.push('non-null'); +- } ++ if (item.nullable === true) { ++ attributes.push('nullable'); ++ } ++ else if (item.nullable === false) { ++ attributes.push('non-null'); ++ } + +- return attributes; ++ return attributes; + } + + function updateItemName(item) { +- var attributes = getSignatureAttributes(item); +- var itemName = item.name || ''; ++ var attributes = getSignatureAttributes(item); ++ var itemName = item.name || ''; + +- if (item.variable) { +- itemName = '…' + itemName; +- } ++ if (item.variable) { ++ itemName = '…' + itemName; ++ } + +- if (attributes && attributes.length) { +- itemName = util.format( '%s%s', itemName, +- attributes.join(', ') ); +- } ++ if (attributes && attributes.length) { ++ itemName = util.format( '%s%s', itemName, ++ attributes.join(', ') ); ++ } + +- return itemName; ++ return itemName; + } + + function addParamAttributes(params) { +- return params.filter(function(param) { +- return param.name && param.name.indexOf('.') === -1; +- }).map(updateItemName); ++ return params.filter(function(param) { ++ return param.name && param.name.indexOf('.') === -1; ++ }).map(updateItemName); + } + + function buildItemTypeStrings(item) { +- var types = []; ++ var types = []; + +- if (item && item.type && item.type.names) { +- item.type.names.forEach(function(name) { +- types.push( linkto(name, htmlsafe(name)) ); +- }); +- } ++ if (item && item.type && item.type.names) { ++ item.type.names.forEach(function(name) { ++ types.push( linkTo(name, htmlsafe(name)) ); ++ }); ++ } + +- return types; ++ return types; + } + + function buildAttribsString(attribs) { +- var attribsString = ''; ++ var attribsString = ''; + +- if (attribs && attribs.length) { +- attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); +- } ++ if (attribs && attribs.length) { ++ attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); ++ } + +- return attribsString; ++ return attribsString; + } + + function addNonParamAttributes(items) { +- var types = []; ++ var types = []; + +- items.forEach(function(item) { +- types = types.concat( buildItemTypeStrings(item) ); +- }); ++ items.forEach(function(item) { ++ types = types.concat( buildItemTypeStrings(item) ); ++ }); + +- return types; ++ return types; + } + + function addSignatureParams(f) { +- var params = f.params ? addParamAttributes(f.params) : []; +- f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') ); ++ var params = f.params ? addParamAttributes(f.params) : []; ++ f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') ); + } + + function addSignatureReturns(f) { +- var attribs = []; +- var attribsString = ''; +- var returnTypes = []; +- var returnTypesString = ''; +- var source = f.yields || f.returns; +- +- // jam all the return-type attributes into an array. this could create odd results (for example, +- // if there are both nullable and non-nullable return types), but let's assume that most people +- // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. +- if (source) { +- source.forEach(function(item) { +- helper.getAttribs(item).forEach(function(attrib) { +- if (attribs.indexOf(attrib) === -1) { +- attribs.push(attrib); +- } +- }); +- }); +- +- attribsString = buildAttribsString(attribs); +- } +- +- if (source) { +- returnTypes = addNonParamAttributes(source); +- } +- if (returnTypes.length) { +- returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); +- } +- +- f.signature = '' + (f.signature || '') + '' + +- '' + returnTypesString + ''; ++ var attribs = []; ++ var attribsString = ''; ++ var returnTypes = []; ++ var returnTypesString = ''; ++ ++ // jam all the return-type attributes into an array. this could create odd results (for example, ++ // if there are both nullable and non-nullable return types), but let's assume that most people ++ // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. ++ if (f.returns) { ++ f.returns.forEach(function(item) { ++ helper.getAttribs(item).forEach(function(attrib) { ++ if (attribs.indexOf(attrib) === -1) { ++ attribs.push(attrib); ++ } ++ }); ++ }); ++ ++ attribsString = buildAttribsString(attribs); ++ } ++ ++ if (f.returns) { ++ returnTypes = addNonParamAttributes(f.returns); ++ } ++ if (returnTypes.length) { ++ returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); ++ } ++ ++ // Modified to support coloring in Vitepress ++ f.signature = '' + (f.signature || '') + '' + ++ '' + returnTypesString + ''; + } + ++// Modified to support coloring in Vitepress + function addSignatureTypes(f) { +- var types = f.type ? buildItemTypeStrings(f) : []; ++ var types = f.type ? buildItemTypeStrings(f) : []; + +- f.signature = (f.signature || '') + '' + +- (types.length ? ' :' + types.join('|') : '') + ''; ++ f.signature = (f.signature || '') + '' + ++ (types.length ? ' :' + types.join('|') : '') + ''; + } + + function addAttribs(f) { +- var attribs = helper.getAttribs(f); +- var attribsString = buildAttribsString(attribs); +- if (attribsString && attribsString.length) { +- f.attribs = util.format('%s', attribsString); +- } +- else { +- f.attribs = util.format('%s', attribsString); +- } ++ var attribs = helper.getAttribs(f); ++ var attribsString = buildAttribsString(attribs); ++ ++ f.attribs = util.format('%s', attribsString); + } + + function shortenPaths(files, commonPrefix) { +- Object.keys(files).forEach(function(file) { +- files[file].shortened = files[file].resolved.replace(commonPrefix, '') +- // always use forward slashes +- .replace(/\\/g, '/'); +- }); ++ Object.keys(files).forEach(function(file) { ++ files[file].shortened = files[file].resolved.replace(commonPrefix, '') ++ // always use forward slashes ++ .replace(/\\/g, '/'); ++ }); + +- return files; ++ return files; + } + + function getPathFromDoclet(doclet) { +- if (!doclet.meta) { +- return null; +- } ++ if (!doclet.meta) { ++ return null; ++ } + +- return doclet.meta.path && doclet.meta.path !== 'null' ? +- path.join(doclet.meta.path, doclet.meta.filename) : +- doclet.meta.filename; ++ return doclet.meta.path && doclet.meta.path !== 'null' ? ++ path.join(doclet.meta.path, doclet.meta.filename) : ++ doclet.meta.filename; + } + + function generate(type, title, docs, filename, resolveLinks) { +- resolveLinks = resolveLinks === false ? false : true; ++ resolveLinks = resolveLinks === false ? false : true; + +- var docData = { +- type: type, +- title: title, +- docs: docs +- }; ++ var docData = { ++ type: type, ++ title: title, ++ docs: docs ++ }; + +- var outpath = path.join(outdir, filename), +- html = view.render('container.tmpl', docData); ++ var outpath = path.join(outdir, filename + ".md"), ++ html = view.render('container.tmpl', docData); + +- if (resolveLinks) { +- html = helper.resolveLinks(html); // turn {@link foo} into foo +- } ++ if (resolveLinks) { ++ html = helper.resolveLinks(html); // turn {@link foo} into foo ++ } + +- fs.writeFileSync(outpath, html, 'utf8'); ++ // Modified: replaceAll fixes pipe escaping ++ fs.writeFileSync(outpath, html.replaceAll("\\|", "|"), 'utf8'); + } + ++// Modified: Don't write source files + function generateSourceFiles(sourceFiles, encoding) { +- encoding = encoding || 'utf8'; +- Object.keys(sourceFiles).forEach(function(file) { +- var source; +- // links are keyed to the shortened path in each doclet's `meta.shortpath` property +- var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); +- helper.registerLink(sourceFiles[file].shortened, sourceOutfile); +- +- try { +- source = { +- kind: 'source', +- code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) ) +- }; +- } +- catch(e) { +- logger.error('Error while generating source file %s: %s', file, e.message); +- } +- +- generate('Source', sourceFiles[file].shortened, [source], sourceOutfile, false); +- }); ++ encoding = encoding || 'utf8'; ++ Object.keys(sourceFiles).forEach(function(file) { ++ // links are keyed to the shortened path in each doclet's `meta.shortpath` property ++ var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); ++ helper.registerLink(sourceFiles[file].shortened, sourceOutfile); ++ }); + } + + /** +@@ -293,539 +249,442 @@ function generateSourceFiles(sourceFiles, encoding) { + * @param {Array.} modules - The array of module doclets to search. + */ + function attachModuleSymbols(doclets, modules) { +- var symbols = {}; +- +- // build a lookup table +- doclets.forEach(function(symbol) { +- symbols[symbol.longname] = symbols[symbol.longname] || []; +- symbols[symbol.longname].push(symbol); +- }); +- +- return modules.map(function(module) { +- if (symbols[module.longname]) { +- module.modules = symbols[module.longname] +- // Only show symbols that have a description. Make an exception for classes, because +- // we want to show the constructor-signature heading no matter what. +- .filter(function(symbol) { +- return symbol.description || symbol.kind === 'class'; +- }) +- .map(function(symbol) { +- symbol = doop(symbol); +- +- if (symbol.kind === 'class' || symbol.kind === 'function' && !symbol.hideconstructor) { +- symbol.name = symbol.name.replace('module:', '(require("') + '"))'; +- } +- +- return symbol; +- }); +- } +- }); ++ var symbols = {}; ++ ++ // build a lookup table ++ doclets.forEach(function(symbol) { ++ symbols[symbol.longname] = symbols[symbol.longname] || []; ++ symbols[symbol.longname].push(symbol); ++ }); ++ ++ return modules.map(function(module) { ++ if (symbols[module.longname]) { ++ module.modules = symbols[module.longname] ++ // Only show symbols that have a description. Make an exception for classes, because ++ // we want to show the constructor-signature heading no matter what. ++ .filter(function(symbol) { ++ return symbol.description || symbol.kind === 'class'; ++ }) ++ .map(function(symbol) { ++ symbol = doop(symbol); ++ ++ if (symbol.kind === 'class' || symbol.kind === 'function') { ++ symbol.name = symbol.name.replace('module:', '(require("') + '"))'; ++ } ++ ++ return symbol; ++ }); ++ } ++ }); + } + +-function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) { +- var nav = ''; +- +- if (items && items.length) { +- var itemsNav = ''; +- var docdash = env && env.conf && env.conf.docdash || {}; +- var level = typeof docdash.navLevel === 'number' && docdash.navLevel >= 0 ? +- docdash.navLevel : +- Infinity; +- +- items.forEach(function(item) { +- var displayName; +- var methods = find({kind:'function', memberof: item.longname}); +- var members = find({kind:'member', memberof: item.longname}); +- var conf = env && env.conf || {}; +- var classes = ''; +- +- // show private class? +- if (docdash.private === false && item.access === 'private') return; +- +- // depth to show? +- if (item.ancestors && item.ancestors.length > level) { +- classes += 'level-hide'; +- } +- +- classes = classes ? ' class="'+ classes + '"' : ''; +- itemsNav += ''; +- if ( !hasOwnProp.call(item, 'longname') ) { +- itemsNav += linktoFn('', item.name); +- } else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { +- if (conf.templates.default.useLongnameInNav) { +- displayName = item.longname; +- } else { +- displayName = item.name; +- } +- itemsNav += linktoFn(item.longname, displayName.replace(/\b(module|event):/g, '')); +- +- if (docdash.static && members.find(function (m) { return m.scope === 'static'; } )) { +- itemsNav += "