@backstage/plugin-techdocs-node 0.0.0-nightly-20260925022940 → 0.0.0-nightly-20260927023342
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
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# @backstage/plugin-techdocs-node
|
|
2
2
|
|
|
3
|
-
## 0.0.0-nightly-
|
|
3
|
+
## 0.0.0-nightly-20260927023342
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- 9fc5387: Improved handling of mapping-style Markdown extension configuration.
|
|
7
8
|
- Updated dependencies
|
|
8
|
-
- @backstage/integration@0.0.0-nightly-
|
|
9
|
-
- @backstage/config@0.0.0-nightly-
|
|
10
|
-
- @backstage/errors@0.0.0-nightly-
|
|
11
|
-
- @backstage/backend-plugin-api@0.0.0-nightly-
|
|
12
|
-
- @backstage/integration-aws-node@0.0.0-nightly-
|
|
13
|
-
- @backstage/catalog-model@0.0.0-nightly-
|
|
14
|
-
- @backstage/plugin-search-common@0.0.0-nightly-
|
|
9
|
+
- @backstage/integration@0.0.0-nightly-20260927023342
|
|
10
|
+
- @backstage/config@0.0.0-nightly-20260927023342
|
|
11
|
+
- @backstage/errors@0.0.0-nightly-20260927023342
|
|
12
|
+
- @backstage/backend-plugin-api@0.0.0-nightly-20260927023342
|
|
13
|
+
- @backstage/integration-aws-node@0.0.0-nightly-20260927023342
|
|
14
|
+
- @backstage/catalog-model@0.0.0-nightly-20260927023342
|
|
15
|
+
- @backstage/plugin-search-common@0.0.0-nightly-20260927023342
|
|
15
16
|
- @backstage/plugin-techdocs-common@0.1.1
|
|
16
17
|
|
|
17
18
|
## 2.0.1-next.0
|
|
@@ -241,21 +241,40 @@ const sanitizeMkdocsYml = async (mkdocsYmlPath, logger, additionalAllowedKeys, a
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
const extensions = sanitized.markdown_extensions;
|
|
244
|
+
const removedEntries = [];
|
|
245
|
+
const extensionMapping = isPlainObject(extensions) ? extensions : void 0;
|
|
246
|
+
let normalizedExtensions;
|
|
244
247
|
if (Array.isArray(extensions)) {
|
|
245
|
-
|
|
246
|
-
|
|
248
|
+
normalizedExtensions = extensions;
|
|
249
|
+
} else if (extensionMapping) {
|
|
250
|
+
normalizedExtensions = Object.entries(extensionMapping).map(
|
|
251
|
+
([name, config]) => ({
|
|
252
|
+
[name]: config
|
|
253
|
+
})
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (extensions instanceof helpers.UnknownTag) {
|
|
257
|
+
removedEntries.push("dynamically configured extension");
|
|
258
|
+
sanitized.markdown_extensions = [];
|
|
259
|
+
} else if (normalizedExtensions) {
|
|
260
|
+
const sanitizedExtensions = normalizedExtensions.flatMap((ext) => {
|
|
261
|
+
if (ext instanceof helpers.UnknownTag) {
|
|
262
|
+
removedEntries.push("dynamically configured extension");
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
247
265
|
if (typeof ext === "string") {
|
|
248
266
|
if (isPymdownxSnippetsExtension(ext)) {
|
|
249
|
-
return
|
|
267
|
+
return [ext];
|
|
250
268
|
}
|
|
251
269
|
if (ext.includes(":")) {
|
|
252
270
|
removedEntries.push(ext);
|
|
253
|
-
return
|
|
271
|
+
return [];
|
|
254
272
|
}
|
|
255
|
-
return
|
|
273
|
+
return [ext];
|
|
256
274
|
}
|
|
257
|
-
if (!
|
|
258
|
-
|
|
275
|
+
if (!isPlainObject(ext)) {
|
|
276
|
+
removedEntries.push("malformed extension declaration");
|
|
277
|
+
return [];
|
|
259
278
|
}
|
|
260
279
|
const extensionEntries = Object.entries(ext);
|
|
261
280
|
const dangerousNames = extensionEntries.map(([extensionName]) => extensionName).filter(
|
|
@@ -263,36 +282,47 @@ const sanitizeMkdocsYml = async (mkdocsYmlPath, logger, additionalAllowedKeys, a
|
|
|
263
282
|
);
|
|
264
283
|
if (dangerousNames.length > 0) {
|
|
265
284
|
removedEntries.push(...dangerousNames);
|
|
266
|
-
return
|
|
285
|
+
return [];
|
|
267
286
|
}
|
|
287
|
+
const sanitizedExtension = {};
|
|
268
288
|
for (const [extensionName, extensionConfig] of extensionEntries) {
|
|
269
|
-
if (
|
|
289
|
+
if (extensionConfig instanceof helpers.UnknownTag) {
|
|
290
|
+
removedEntries.push(
|
|
291
|
+
`dynamically configured ${extensionName} extension`
|
|
292
|
+
);
|
|
270
293
|
continue;
|
|
271
294
|
}
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
295
|
+
if (isPymdownxSnippetsExtension(extensionName)) {
|
|
296
|
+
if (extensionConfig !== null && (typeof extensionConfig !== "object" || Object.keys(extensionConfig).length > 0)) {
|
|
297
|
+
removedEntries.push(`${extensionName} configuration`);
|
|
298
|
+
}
|
|
299
|
+
sanitizedExtension[extensionName] = {};
|
|
300
|
+
} else if (isPlainObject(extensionConfig)) {
|
|
301
|
+
const sanitizedConfig = { ...extensionConfig };
|
|
279
302
|
for (const dangerousKey of helpers.DANGEROUS_EXTENSION_CONFIG_KEYS) {
|
|
280
|
-
if (dangerousKey in
|
|
281
|
-
delete
|
|
303
|
+
if (dangerousKey in sanitizedConfig) {
|
|
304
|
+
delete sanitizedConfig[dangerousKey];
|
|
282
305
|
removedEntries.push(dangerousKey);
|
|
283
306
|
}
|
|
284
307
|
}
|
|
308
|
+
sanitizedExtension[extensionName] = sanitizedConfig;
|
|
309
|
+
} else {
|
|
310
|
+
sanitizedExtension[extensionName] = extensionConfig;
|
|
285
311
|
}
|
|
286
312
|
}
|
|
287
|
-
return
|
|
313
|
+
return Object.keys(sanitizedExtension).length > 0 ? [sanitizedExtension] : [];
|
|
288
314
|
});
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
315
|
+
sanitized.markdown_extensions = extensionMapping ? Object.assign({}, ...sanitizedExtensions) : sanitizedExtensions;
|
|
316
|
+
} else if (extensions !== void 0) {
|
|
317
|
+
removedEntries.push("malformed extension declaration");
|
|
318
|
+
sanitized.markdown_extensions = [];
|
|
319
|
+
}
|
|
320
|
+
if (removedEntries.length > 0) {
|
|
321
|
+
logger.warn(
|
|
322
|
+
`Removed the following dangerous entries from markdown_extensions in mkdocs.yml: ${removedEntries.join(
|
|
323
|
+
", "
|
|
324
|
+
)}.`
|
|
325
|
+
);
|
|
296
326
|
}
|
|
297
327
|
if ("plugins" in sanitized) {
|
|
298
328
|
const allowedPlugins = new Set(DEFAULT_ALLOWED_MKDOCS_PLUGINS);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mkdocsPatchers.cjs.js","sources":["../../../src/stages/generate/mkdocsPatchers.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport fs from 'fs-extra';\nimport yaml from 'js-yaml';\nimport { ParsedLocationAnnotation } from '../../helpers';\nimport {\n ALLOWED_MKDOCS_KEYS,\n ALLOWED_THEME_KEYS,\n DANGEROUS_EXTENSION_CONFIG_KEYS,\n getRepoUrlFromLocationAnnotation,\n MKDOCS_SCHEMA,\n UnknownTag,\n} from './helpers';\nimport { toError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst MATERIAL_THEME = 'material';\nconst PYMDOWNX_SNIPPETS_EXTENSION = 'pymdownx.snippets';\n\nconst DEFAULT_ALLOWED_MKDOCS_PLUGINS = new Set([\n 'techdocs-core',\n 'search',\n 'material/search',\n 'redirects',\n 'group',\n 'material/group',\n]);\nconst MKDOCS_PLUGIN_GROUPS = new Set(['group', 'material/group']);\n\nfunction isPymdownxSnippetsExtension(extensionName: string): boolean {\n return (\n extensionName === PYMDOWNX_SNIPPETS_EXTENSION ||\n extensionName === `${PYMDOWNX_SNIPPETS_EXTENSION}:SnippetExtension`\n );\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n value instanceof UnknownTag\n ) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction normalizeMkdocsPlugins(plugins: unknown): unknown[] | undefined {\n if (Array.isArray(plugins)) {\n return plugins;\n }\n if (isPlainObject(plugins)) {\n return Object.entries(plugins).map(([name, config]) => ({\n [name]: config,\n }));\n }\n return undefined;\n}\n\nfunction sanitizeMkdocsPlugins(\n plugins: unknown,\n allowedPlugins: Set<string>,\n removedPlugins: Set<string>,\n): unknown[] {\n if (plugins instanceof UnknownTag) {\n removedPlugins.add('dynamically configured plugin name');\n return [];\n }\n\n const normalizedPlugins = normalizeMkdocsPlugins(plugins);\n if (!normalizedPlugins) {\n removedPlugins.add('malformed plugin declaration');\n return [];\n }\n\n const sanitizedPlugins: unknown[] = [];\n for (const plugin of normalizedPlugins) {\n if (plugin instanceof UnknownTag) {\n removedPlugins.add('dynamically configured plugin name');\n continue;\n }\n\n let pluginName: string;\n if (typeof plugin === 'string' && plugin.length > 0) {\n pluginName = plugin;\n } else if (isPlainObject(plugin) && Object.keys(plugin).length === 1) {\n [pluginName] = Object.keys(plugin);\n const config = plugin[pluginName];\n if (config !== null && !isPlainObject(config)) {\n removedPlugins.add('malformed plugin declaration');\n continue;\n }\n } else {\n removedPlugins.add('malformed plugin declaration');\n continue;\n }\n\n if (!allowedPlugins.has(pluginName)) {\n removedPlugins.add(pluginName);\n continue;\n }\n\n let sanitizedPlugin = plugin;\n if (isPlainObject(plugin)) {\n const config = plugin[pluginName];\n if (MKDOCS_PLUGIN_GROUPS.has(pluginName) && isPlainObject(config)) {\n sanitizedPlugin = {\n ...plugin,\n [pluginName]: {\n ...config,\n plugins: sanitizeMkdocsPlugins(\n config.plugins,\n allowedPlugins,\n removedPlugins,\n ),\n },\n };\n }\n }\n\n sanitizedPlugins.push(sanitizedPlugin);\n }\n\n return sanitizedPlugins;\n}\n\ntype MkDocsThemeObject = {\n name?: string;\n font?: boolean;\n};\n\nfunction isThemeObject(theme: unknown): theme is MkDocsThemeObject {\n return typeof theme === 'object' && theme !== null && !Array.isArray(theme);\n}\n\ntype MkDocsObject = {\n plugins?: string[];\n docs_dir: string;\n repo_url?: string;\n edit_uri?: string;\n theme?: MkDocsThemeObject;\n};\n\nconst patchMkdocsFile = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n updateAction: (mkdocsYml: MkDocsObject) => boolean,\n options?: { failOnError?: boolean },\n) => {\n // We only want to override the mkdocs.yml if it has actually changed. This is relevant if\n // used with a 'dir' location on the file system as this would permanently update the file.\n let didEdit = false;\n\n let mkdocsYmlFileString;\n try {\n mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8');\n } catch (error) {\n logger.warn(\n `Could not read MkDocs YAML config file ${mkdocsYmlPath} before running the generator: ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n\n let mkdocsYml: any;\n try {\n mkdocsYml = yaml.load(mkdocsYmlFileString, { schema: MKDOCS_SCHEMA });\n\n // mkdocsYml should be an object type after successful parsing.\n // But based on its type definition, it can also be a string or undefined, which we don't want.\n if (typeof mkdocsYml === 'string' || typeof mkdocsYml === 'undefined') {\n throw new Error('Bad YAML format.');\n }\n } catch (error) {\n logger.warn(\n `Error in parsing YAML at ${mkdocsYmlPath} before running the generator. ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n\n didEdit = updateAction(mkdocsYml);\n\n try {\n if (didEdit) {\n await fs.writeFile(\n mkdocsYmlPath,\n yaml.dump(mkdocsYml, { schema: MKDOCS_SCHEMA }),\n 'utf8',\n );\n }\n } catch (error) {\n logger.warn(\n `Could not write to ${mkdocsYmlPath} after updating it before running the generator. ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n};\n\nconst patchMkdocsFileOrThrow = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n updateAction: (mkdocsYml: MkDocsObject) => boolean,\n) =>\n patchMkdocsFile(mkdocsYmlPath, logger, updateAction, {\n failOnError: true,\n });\n\n/**\n * Update the mkdocs.yml file before TechDocs generator uses it to generate docs site.\n *\n * List of tasks:\n * - Add repo_url or edit_uri if it does not exists\n * If mkdocs.yml has a repo_url, the generated docs site gets an Edit button on the pages by default.\n * If repo_url is missing in mkdocs.yml, we will use techdocs annotation of the entity to possibly get\n * the repository URL.\n *\n * This function will not throw an error since this is not critical to the whole TechDocs pipeline.\n * Instead it will log warnings if there are any errors in reading, parsing or writing YAML.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param parsedLocationAnnotation - Object with location url and type\n * @param scmIntegrations - the scmIntegration to do url transformations\n */\nexport const patchMkdocsYmlPreBuild = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n parsedLocationAnnotation: ParsedLocationAnnotation,\n scmIntegrations: ScmIntegrationRegistry,\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n if (!('repo_url' in mkdocsYml) || !('edit_uri' in mkdocsYml)) {\n // Add edit_uri and/or repo_url to mkdocs.yml if it is missing.\n // This will enable the Page edit button generated by MkDocs.\n // If the either has been set, keep the original value\n const result = getRepoUrlFromLocationAnnotation(\n parsedLocationAnnotation,\n scmIntegrations,\n mkdocsYml.docs_dir,\n );\n\n if (result.repo_url || result.edit_uri) {\n mkdocsYml.repo_url = mkdocsYml.repo_url || result.repo_url;\n mkdocsYml.edit_uri = mkdocsYml.edit_uri || result.edit_uri;\n\n logger.info(\n `Set ${JSON.stringify(\n result,\n )}. You can disable this feature by manually setting 'repo_url' or 'edit_uri' according to the MkDocs documentation at https://www.mkdocs.org/user-guide/configuration/#repo_url`,\n );\n return true;\n }\n }\n return false;\n });\n};\n\n/**\n * Update the mkdocs.yml file before TechDocs generator uses it to generate docs site.\n *\n * List of tasks:\n * - Add all provided default plugins\n *\n * This function will not throw an error since this is not critical to the whole TechDocs pipeline.\n * Instead it will log warnings if there are any errors in reading, parsing or writing YAML.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param defaultPlugins - List of default mkdocs plugins\n */\nexport const patchMkdocsYmlWithPlugins = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n defaultPlugins: string[] = ['techdocs-core'],\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n // Modify mkdocs.yaml to contain the required default plugins.\n // If no plugins are defined we can just return the defaults.\n if (!('plugins' in mkdocsYml)) {\n mkdocsYml.plugins = defaultPlugins;\n return true;\n }\n\n // Otherwise, check each default plugin and include it if necessary.\n let changesMade = false;\n\n defaultPlugins.forEach(dp => {\n // if the plugin isn't there as a string, and isn't there as an object (which may itself contain extra config)\n // then we need to add it\n if (\n !(\n mkdocsYml.plugins!.includes(dp) ||\n mkdocsYml.plugins!.some(p => p.hasOwnProperty(dp))\n )\n ) {\n mkdocsYml.plugins = [...new Set([...mkdocsYml.plugins!, dp])];\n changesMade = true;\n }\n });\n\n return changesMade;\n });\n};\n\n/**\n * Disable external font download for the material theme.\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger\n */\nexport const patchMkdocsYmlWithFontDisabled = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n if (!('theme' in mkdocsYml)) {\n // No theme section exists, create it with font disabled\n mkdocsYml.theme = {\n name: MATERIAL_THEME,\n font: false,\n };\n return true;\n }\n\n const theme = mkdocsYml.theme;\n if (isThemeObject(theme)) {\n // Theme section exists. Only modify it when the configured theme is Material\n if (theme.name === MATERIAL_THEME && !('font' in theme)) {\n theme.font = false;\n return true;\n }\n if (theme.name !== MATERIAL_THEME) {\n logger.debug(\n 'mkdocs.yml theme is not \"material\"; skipping font disabling patch',\n );\n }\n }\n\n return false;\n });\n};\n\n/**\n * Sanitize mkdocs.yml by keeping only allowed configuration keys.\n *\n * TechDocs only supports a subset of MkDocs configuration options.\n * This function reconstructs the config with only allowed keys,\n * discarding everything else. This approach ensures that any unknown\n * or potentially dangerous configuration options are not passed to MkDocs.\n *\n * The file is always rewritten to ensure YAML features like merge keys\n * and anchors are resolved into plain configuration.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param additionalAllowedKeys - Optional array of additional keys to allow beyond the default allowlist\n * @param additionalAllowedPlugins - Optional array of additional plugins to allow beyond the default set\n */\nexport const sanitizeMkdocsYml = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n additionalAllowedKeys?: string[],\n additionalAllowedPlugins?: string[],\n) => {\n await patchMkdocsFileOrThrow(mkdocsYmlPath, logger, mkdocsYml => {\n // Combine default allowed keys with additional keys\n const allowedKeys = new Set(ALLOWED_MKDOCS_KEYS);\n if (additionalAllowedKeys && additionalAllowedKeys.length > 0) {\n logger.warn(\n `DANGEROUS: Allowing additional MkDocs configuration keys beyond the default safe allowlist: ${additionalAllowedKeys.join(\n ', ',\n )}. This may introduce security vulnerabilities. Only use in trusted environments.`,\n );\n additionalAllowedKeys.forEach(key => allowedKeys.add(key));\n }\n\n // Identify keys that will be removed for logging\n const removedKeys = Object.keys(mkdocsYml).filter(\n key => !allowedKeys.has(key),\n );\n\n if (removedKeys.length > 0) {\n logger.warn(\n `Removed the following unsupported configuration keys from mkdocs.yml: ${removedKeys.join(\n ', ',\n )}. ` +\n `TechDocs only supports a subset of MkDocs configuration options.`,\n );\n }\n\n // Build a new object with only allowed keys\n const sanitized: Record<string, unknown> = {};\n for (const key of allowedKeys) {\n if (key in mkdocsYml) {\n sanitized[key] = (mkdocsYml as Record<string, unknown>)[key];\n }\n }\n\n // Sanitize markdown_extensions\n const extensions = sanitized.markdown_extensions;\n if (Array.isArray(extensions)) {\n const removedEntries: string[] = [];\n\n sanitized.markdown_extensions = extensions.filter(ext => {\n if (typeof ext === 'string') {\n if (isPymdownxSnippetsExtension(ext)) {\n return true;\n }\n\n if (ext.includes(':')) {\n removedEntries.push(ext);\n return false;\n }\n return true;\n }\n\n if (!ext || typeof ext !== 'object' || Array.isArray(ext)) {\n return true;\n }\n\n // Check every key, not just the first, so that a multi-key mapping\n // cannot smuggle a dangerous name past the filter.\n const extensionEntries = Object.entries(ext as Record<string, unknown>);\n const dangerousNames = extensionEntries\n .map(([extensionName]) => extensionName)\n .filter(\n extensionName =>\n extensionName.includes(':') &&\n !isPymdownxSnippetsExtension(extensionName),\n );\n if (dangerousNames.length > 0) {\n removedEntries.push(...dangerousNames);\n return false;\n }\n\n for (const [extensionName, extensionConfig] of extensionEntries) {\n if (!isPymdownxSnippetsExtension(extensionName)) {\n continue;\n }\n\n if (\n extensionConfig !== null &&\n (typeof extensionConfig !== 'object' ||\n Object.keys(extensionConfig).length > 0)\n ) {\n removedEntries.push(`${extensionName} configuration`);\n }\n Object.assign(ext, { [extensionName]: {} });\n }\n\n // Strip dangerous keys from the extension's own configuration.\n for (const extConfig of Object.values(ext as Record<string, unknown>)) {\n if (\n extConfig &&\n typeof extConfig === 'object' &&\n !Array.isArray(extConfig)\n ) {\n for (const dangerousKey of DANGEROUS_EXTENSION_CONFIG_KEYS) {\n if (dangerousKey in extConfig) {\n delete (extConfig as Record<string, unknown>)[dangerousKey];\n removedEntries.push(dangerousKey);\n }\n }\n }\n }\n\n return true;\n });\n\n if (removedEntries.length > 0) {\n logger.warn(\n `Removed the following dangerous entries from markdown_extensions in mkdocs.yml: ${removedEntries.join(\n ', ',\n )}.`,\n );\n }\n }\n\n if ('plugins' in sanitized) {\n const allowedPlugins = new Set(DEFAULT_ALLOWED_MKDOCS_PLUGINS);\n additionalAllowedPlugins?.forEach(plugin => allowedPlugins.add(plugin));\n\n const removedPlugins = new Set<string>();\n sanitized.plugins = sanitizeMkdocsPlugins(\n sanitized.plugins,\n allowedPlugins,\n removedPlugins,\n );\n\n if (removedPlugins.size > 0) {\n logger.warn(\n `Removed unsupported MkDocs plugins from mkdocs.yml: ${Array.from(\n removedPlugins,\n ).join(\n ', ',\n )}. To allow additional plugins, configure 'techdocs.generator.mkdocs.dangerouslyAllowAdditionalPlugins' in your Backstage app-config. When using the TechDocs CLI, use '--defaultPlugin' instead.`,\n );\n }\n }\n\n // Clear the original object and copy sanitized values back\n for (const key of Object.keys(mkdocsYml)) {\n delete (mkdocsYml as Record<string, unknown>)[key];\n }\n Object.assign(mkdocsYml, sanitized);\n\n // Sanitize theme sub-keys\n const theme = (mkdocsYml as Record<string, unknown>).theme;\n if (isThemeObject(theme)) {\n const removedThemeKeys = Object.keys(theme).filter(\n key => !ALLOWED_THEME_KEYS.has(key),\n );\n if (removedThemeKeys.length > 0) {\n for (const key of removedThemeKeys) {\n delete (theme as Record<string, unknown>)[key];\n }\n logger.warn(\n `Removed the following unsupported keys from theme configuration in mkdocs.yml: ${removedThemeKeys.join(\n ', ',\n )}.`,\n );\n }\n }\n\n // Always rewrite to ensure clean YAML output (resolves merge keys, anchors, etc.)\n return true;\n });\n};\n"],"names":["UnknownTag","fs","toError","yaml","MKDOCS_SCHEMA","getRepoUrlFromLocationAnnotation","ALLOWED_MKDOCS_KEYS","DANGEROUS_EXTENSION_CONFIG_KEYS","ALLOWED_THEME_KEYS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mkdocsPatchers.cjs.js","sources":["../../../src/stages/generate/mkdocsPatchers.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport fs from 'fs-extra';\nimport yaml from 'js-yaml';\nimport { ParsedLocationAnnotation } from '../../helpers';\nimport {\n ALLOWED_MKDOCS_KEYS,\n ALLOWED_THEME_KEYS,\n DANGEROUS_EXTENSION_CONFIG_KEYS,\n getRepoUrlFromLocationAnnotation,\n MKDOCS_SCHEMA,\n UnknownTag,\n} from './helpers';\nimport { toError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst MATERIAL_THEME = 'material';\nconst PYMDOWNX_SNIPPETS_EXTENSION = 'pymdownx.snippets';\n\nconst DEFAULT_ALLOWED_MKDOCS_PLUGINS = new Set([\n 'techdocs-core',\n 'search',\n 'material/search',\n 'redirects',\n 'group',\n 'material/group',\n]);\nconst MKDOCS_PLUGIN_GROUPS = new Set(['group', 'material/group']);\n\nfunction isPymdownxSnippetsExtension(extensionName: string): boolean {\n return (\n extensionName === PYMDOWNX_SNIPPETS_EXTENSION ||\n extensionName === `${PYMDOWNX_SNIPPETS_EXTENSION}:SnippetExtension`\n );\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n value instanceof UnknownTag\n ) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction normalizeMkdocsPlugins(plugins: unknown): unknown[] | undefined {\n if (Array.isArray(plugins)) {\n return plugins;\n }\n if (isPlainObject(plugins)) {\n return Object.entries(plugins).map(([name, config]) => ({\n [name]: config,\n }));\n }\n return undefined;\n}\n\nfunction sanitizeMkdocsPlugins(\n plugins: unknown,\n allowedPlugins: Set<string>,\n removedPlugins: Set<string>,\n): unknown[] {\n if (plugins instanceof UnknownTag) {\n removedPlugins.add('dynamically configured plugin name');\n return [];\n }\n\n const normalizedPlugins = normalizeMkdocsPlugins(plugins);\n if (!normalizedPlugins) {\n removedPlugins.add('malformed plugin declaration');\n return [];\n }\n\n const sanitizedPlugins: unknown[] = [];\n for (const plugin of normalizedPlugins) {\n if (plugin instanceof UnknownTag) {\n removedPlugins.add('dynamically configured plugin name');\n continue;\n }\n\n let pluginName: string;\n if (typeof plugin === 'string' && plugin.length > 0) {\n pluginName = plugin;\n } else if (isPlainObject(plugin) && Object.keys(plugin).length === 1) {\n [pluginName] = Object.keys(plugin);\n const config = plugin[pluginName];\n if (config !== null && !isPlainObject(config)) {\n removedPlugins.add('malformed plugin declaration');\n continue;\n }\n } else {\n removedPlugins.add('malformed plugin declaration');\n continue;\n }\n\n if (!allowedPlugins.has(pluginName)) {\n removedPlugins.add(pluginName);\n continue;\n }\n\n let sanitizedPlugin = plugin;\n if (isPlainObject(plugin)) {\n const config = plugin[pluginName];\n if (MKDOCS_PLUGIN_GROUPS.has(pluginName) && isPlainObject(config)) {\n sanitizedPlugin = {\n ...plugin,\n [pluginName]: {\n ...config,\n plugins: sanitizeMkdocsPlugins(\n config.plugins,\n allowedPlugins,\n removedPlugins,\n ),\n },\n };\n }\n }\n\n sanitizedPlugins.push(sanitizedPlugin);\n }\n\n return sanitizedPlugins;\n}\n\ntype MkDocsThemeObject = {\n name?: string;\n font?: boolean;\n};\n\nfunction isThemeObject(theme: unknown): theme is MkDocsThemeObject {\n return typeof theme === 'object' && theme !== null && !Array.isArray(theme);\n}\n\ntype MkDocsObject = {\n plugins?: string[];\n docs_dir: string;\n repo_url?: string;\n edit_uri?: string;\n theme?: MkDocsThemeObject;\n};\n\nconst patchMkdocsFile = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n updateAction: (mkdocsYml: MkDocsObject) => boolean,\n options?: { failOnError?: boolean },\n) => {\n // We only want to override the mkdocs.yml if it has actually changed. This is relevant if\n // used with a 'dir' location on the file system as this would permanently update the file.\n let didEdit = false;\n\n let mkdocsYmlFileString;\n try {\n mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8');\n } catch (error) {\n logger.warn(\n `Could not read MkDocs YAML config file ${mkdocsYmlPath} before running the generator: ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n\n let mkdocsYml: any;\n try {\n mkdocsYml = yaml.load(mkdocsYmlFileString, { schema: MKDOCS_SCHEMA });\n\n // mkdocsYml should be an object type after successful parsing.\n // But based on its type definition, it can also be a string or undefined, which we don't want.\n if (typeof mkdocsYml === 'string' || typeof mkdocsYml === 'undefined') {\n throw new Error('Bad YAML format.');\n }\n } catch (error) {\n logger.warn(\n `Error in parsing YAML at ${mkdocsYmlPath} before running the generator. ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n\n didEdit = updateAction(mkdocsYml);\n\n try {\n if (didEdit) {\n await fs.writeFile(\n mkdocsYmlPath,\n yaml.dump(mkdocsYml, { schema: MKDOCS_SCHEMA }),\n 'utf8',\n );\n }\n } catch (error) {\n logger.warn(\n `Could not write to ${mkdocsYmlPath} after updating it before running the generator. ${\n toError(error).message\n }`,\n );\n if (options?.failOnError) {\n throw error;\n }\n return;\n }\n};\n\nconst patchMkdocsFileOrThrow = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n updateAction: (mkdocsYml: MkDocsObject) => boolean,\n) =>\n patchMkdocsFile(mkdocsYmlPath, logger, updateAction, {\n failOnError: true,\n });\n\n/**\n * Update the mkdocs.yml file before TechDocs generator uses it to generate docs site.\n *\n * List of tasks:\n * - Add repo_url or edit_uri if it does not exists\n * If mkdocs.yml has a repo_url, the generated docs site gets an Edit button on the pages by default.\n * If repo_url is missing in mkdocs.yml, we will use techdocs annotation of the entity to possibly get\n * the repository URL.\n *\n * This function will not throw an error since this is not critical to the whole TechDocs pipeline.\n * Instead it will log warnings if there are any errors in reading, parsing or writing YAML.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param parsedLocationAnnotation - Object with location url and type\n * @param scmIntegrations - the scmIntegration to do url transformations\n */\nexport const patchMkdocsYmlPreBuild = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n parsedLocationAnnotation: ParsedLocationAnnotation,\n scmIntegrations: ScmIntegrationRegistry,\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n if (!('repo_url' in mkdocsYml) || !('edit_uri' in mkdocsYml)) {\n // Add edit_uri and/or repo_url to mkdocs.yml if it is missing.\n // This will enable the Page edit button generated by MkDocs.\n // If the either has been set, keep the original value\n const result = getRepoUrlFromLocationAnnotation(\n parsedLocationAnnotation,\n scmIntegrations,\n mkdocsYml.docs_dir,\n );\n\n if (result.repo_url || result.edit_uri) {\n mkdocsYml.repo_url = mkdocsYml.repo_url || result.repo_url;\n mkdocsYml.edit_uri = mkdocsYml.edit_uri || result.edit_uri;\n\n logger.info(\n `Set ${JSON.stringify(\n result,\n )}. You can disable this feature by manually setting 'repo_url' or 'edit_uri' according to the MkDocs documentation at https://www.mkdocs.org/user-guide/configuration/#repo_url`,\n );\n return true;\n }\n }\n return false;\n });\n};\n\n/**\n * Update the mkdocs.yml file before TechDocs generator uses it to generate docs site.\n *\n * List of tasks:\n * - Add all provided default plugins\n *\n * This function will not throw an error since this is not critical to the whole TechDocs pipeline.\n * Instead it will log warnings if there are any errors in reading, parsing or writing YAML.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param defaultPlugins - List of default mkdocs plugins\n */\nexport const patchMkdocsYmlWithPlugins = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n defaultPlugins: string[] = ['techdocs-core'],\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n // Modify mkdocs.yaml to contain the required default plugins.\n // If no plugins are defined we can just return the defaults.\n if (!('plugins' in mkdocsYml)) {\n mkdocsYml.plugins = defaultPlugins;\n return true;\n }\n\n // Otherwise, check each default plugin and include it if necessary.\n let changesMade = false;\n\n defaultPlugins.forEach(dp => {\n // if the plugin isn't there as a string, and isn't there as an object (which may itself contain extra config)\n // then we need to add it\n if (\n !(\n mkdocsYml.plugins!.includes(dp) ||\n mkdocsYml.plugins!.some(p => p.hasOwnProperty(dp))\n )\n ) {\n mkdocsYml.plugins = [...new Set([...mkdocsYml.plugins!, dp])];\n changesMade = true;\n }\n });\n\n return changesMade;\n });\n};\n\n/**\n * Disable external font download for the material theme.\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger\n */\nexport const patchMkdocsYmlWithFontDisabled = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n) => {\n await patchMkdocsFile(mkdocsYmlPath, logger, mkdocsYml => {\n if (!('theme' in mkdocsYml)) {\n // No theme section exists, create it with font disabled\n mkdocsYml.theme = {\n name: MATERIAL_THEME,\n font: false,\n };\n return true;\n }\n\n const theme = mkdocsYml.theme;\n if (isThemeObject(theme)) {\n // Theme section exists. Only modify it when the configured theme is Material\n if (theme.name === MATERIAL_THEME && !('font' in theme)) {\n theme.font = false;\n return true;\n }\n if (theme.name !== MATERIAL_THEME) {\n logger.debug(\n 'mkdocs.yml theme is not \"material\"; skipping font disabling patch',\n );\n }\n }\n\n return false;\n });\n};\n\n/**\n * Sanitize mkdocs.yml by keeping only allowed configuration keys.\n *\n * TechDocs only supports a subset of MkDocs configuration options.\n * This function reconstructs the config with only allowed keys,\n * discarding everything else. This approach ensures that any unknown\n * or potentially dangerous configuration options are not passed to MkDocs.\n *\n * The file is always rewritten to ensure YAML features like merge keys\n * and anchors are resolved into plain configuration.\n *\n * @param mkdocsYmlPath - Absolute path to mkdocs.yml or equivalent of a docs site\n * @param logger - A logger instance\n * @param additionalAllowedKeys - Optional array of additional keys to allow beyond the default allowlist\n * @param additionalAllowedPlugins - Optional array of additional plugins to allow beyond the default set\n */\nexport const sanitizeMkdocsYml = async (\n mkdocsYmlPath: string,\n logger: LoggerService,\n additionalAllowedKeys?: string[],\n additionalAllowedPlugins?: string[],\n) => {\n await patchMkdocsFileOrThrow(mkdocsYmlPath, logger, mkdocsYml => {\n // Combine default allowed keys with additional keys\n const allowedKeys = new Set(ALLOWED_MKDOCS_KEYS);\n if (additionalAllowedKeys && additionalAllowedKeys.length > 0) {\n logger.warn(\n `DANGEROUS: Allowing additional MkDocs configuration keys beyond the default safe allowlist: ${additionalAllowedKeys.join(\n ', ',\n )}. This may introduce security vulnerabilities. Only use in trusted environments.`,\n );\n additionalAllowedKeys.forEach(key => allowedKeys.add(key));\n }\n\n // Identify keys that will be removed for logging\n const removedKeys = Object.keys(mkdocsYml).filter(\n key => !allowedKeys.has(key),\n );\n\n if (removedKeys.length > 0) {\n logger.warn(\n `Removed the following unsupported configuration keys from mkdocs.yml: ${removedKeys.join(\n ', ',\n )}. ` +\n `TechDocs only supports a subset of MkDocs configuration options.`,\n );\n }\n\n // Build a new object with only allowed keys\n const sanitized: Record<string, unknown> = {};\n for (const key of allowedKeys) {\n if (key in mkdocsYml) {\n sanitized[key] = (mkdocsYml as Record<string, unknown>)[key];\n }\n }\n\n // Sanitize markdown_extensions\n const extensions = sanitized.markdown_extensions;\n const removedEntries: string[] = [];\n const extensionMapping = isPlainObject(extensions) ? extensions : undefined;\n let normalizedExtensions: unknown[] | undefined;\n if (Array.isArray(extensions)) {\n normalizedExtensions = extensions;\n } else if (extensionMapping) {\n normalizedExtensions = Object.entries(extensionMapping).map(\n ([name, config]) => ({\n [name]: config,\n }),\n );\n }\n if (extensions instanceof UnknownTag) {\n removedEntries.push('dynamically configured extension');\n sanitized.markdown_extensions = [];\n } else if (normalizedExtensions) {\n const sanitizedExtensions = normalizedExtensions.flatMap<unknown>(ext => {\n if (ext instanceof UnknownTag) {\n removedEntries.push('dynamically configured extension');\n return [];\n }\n\n if (typeof ext === 'string') {\n if (isPymdownxSnippetsExtension(ext)) {\n return [ext];\n }\n\n if (ext.includes(':')) {\n removedEntries.push(ext);\n return [];\n }\n return [ext];\n }\n\n if (!isPlainObject(ext)) {\n removedEntries.push('malformed extension declaration');\n return [];\n }\n\n // Check every key, not just the first, so that a multi-key mapping\n // cannot smuggle a dangerous name past the filter.\n const extensionEntries = Object.entries(ext);\n const dangerousNames = extensionEntries\n .map(([extensionName]) => extensionName)\n .filter(\n extensionName =>\n extensionName.includes(':') &&\n !isPymdownxSnippetsExtension(extensionName),\n );\n if (dangerousNames.length > 0) {\n removedEntries.push(...dangerousNames);\n return [];\n }\n\n const sanitizedExtension: Record<string, unknown> = {};\n for (const [extensionName, extensionConfig] of extensionEntries) {\n if (extensionConfig instanceof UnknownTag) {\n removedEntries.push(\n `dynamically configured ${extensionName} extension`,\n );\n continue;\n }\n\n if (isPymdownxSnippetsExtension(extensionName)) {\n if (\n extensionConfig !== null &&\n (typeof extensionConfig !== 'object' ||\n Object.keys(extensionConfig).length > 0)\n ) {\n removedEntries.push(`${extensionName} configuration`);\n }\n sanitizedExtension[extensionName] = {};\n } else if (isPlainObject(extensionConfig)) {\n const sanitizedConfig = { ...extensionConfig };\n for (const dangerousKey of DANGEROUS_EXTENSION_CONFIG_KEYS) {\n if (dangerousKey in sanitizedConfig) {\n delete sanitizedConfig[dangerousKey];\n removedEntries.push(dangerousKey);\n }\n }\n sanitizedExtension[extensionName] = sanitizedConfig;\n } else {\n sanitizedExtension[extensionName] = extensionConfig;\n }\n }\n\n return Object.keys(sanitizedExtension).length > 0\n ? [sanitizedExtension]\n : [];\n });\n\n sanitized.markdown_extensions = extensionMapping\n ? Object.assign({}, ...sanitizedExtensions)\n : sanitizedExtensions;\n } else if (extensions !== undefined) {\n removedEntries.push('malformed extension declaration');\n sanitized.markdown_extensions = [];\n }\n\n if (removedEntries.length > 0) {\n logger.warn(\n `Removed the following dangerous entries from markdown_extensions in mkdocs.yml: ${removedEntries.join(\n ', ',\n )}.`,\n );\n }\n\n if ('plugins' in sanitized) {\n const allowedPlugins = new Set(DEFAULT_ALLOWED_MKDOCS_PLUGINS);\n additionalAllowedPlugins?.forEach(plugin => allowedPlugins.add(plugin));\n\n const removedPlugins = new Set<string>();\n sanitized.plugins = sanitizeMkdocsPlugins(\n sanitized.plugins,\n allowedPlugins,\n removedPlugins,\n );\n\n if (removedPlugins.size > 0) {\n logger.warn(\n `Removed unsupported MkDocs plugins from mkdocs.yml: ${Array.from(\n removedPlugins,\n ).join(\n ', ',\n )}. To allow additional plugins, configure 'techdocs.generator.mkdocs.dangerouslyAllowAdditionalPlugins' in your Backstage app-config. When using the TechDocs CLI, use '--defaultPlugin' instead.`,\n );\n }\n }\n\n // Clear the original object and copy sanitized values back\n for (const key of Object.keys(mkdocsYml)) {\n delete (mkdocsYml as Record<string, unknown>)[key];\n }\n Object.assign(mkdocsYml, sanitized);\n\n // Sanitize theme sub-keys\n const theme = (mkdocsYml as Record<string, unknown>).theme;\n if (isThemeObject(theme)) {\n const removedThemeKeys = Object.keys(theme).filter(\n key => !ALLOWED_THEME_KEYS.has(key),\n );\n if (removedThemeKeys.length > 0) {\n for (const key of removedThemeKeys) {\n delete (theme as Record<string, unknown>)[key];\n }\n logger.warn(\n `Removed the following unsupported keys from theme configuration in mkdocs.yml: ${removedThemeKeys.join(\n ', ',\n )}.`,\n );\n }\n }\n\n // Always rewrite to ensure clean YAML output (resolves merge keys, anchors, etc.)\n return true;\n });\n};\n"],"names":["UnknownTag","fs","toError","yaml","MKDOCS_SCHEMA","getRepoUrlFromLocationAnnotation","ALLOWED_MKDOCS_KEYS","DANGEROUS_EXTENSION_CONFIG_KEYS","ALLOWED_THEME_KEYS"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-techdocs-node",
|
|
3
|
-
"version": "0.0.0-nightly-
|
|
3
|
+
"version": "0.0.0-nightly-20260927023342",
|
|
4
4
|
"description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"@aws-sdk/types": "^3.347.0",
|
|
54
54
|
"@azure/identity": "^4.0.0",
|
|
55
55
|
"@azure/storage-blob": "^12.5.0",
|
|
56
|
-
"@backstage/backend-plugin-api": "0.0.0-nightly-
|
|
57
|
-
"@backstage/catalog-model": "0.0.0-nightly-
|
|
58
|
-
"@backstage/config": "0.0.0-nightly-
|
|
59
|
-
"@backstage/errors": "0.0.0-nightly-
|
|
60
|
-
"@backstage/integration": "0.0.0-nightly-
|
|
61
|
-
"@backstage/integration-aws-node": "0.0.0-nightly-
|
|
62
|
-
"@backstage/plugin-search-common": "0.0.0-nightly-
|
|
56
|
+
"@backstage/backend-plugin-api": "0.0.0-nightly-20260927023342",
|
|
57
|
+
"@backstage/catalog-model": "0.0.0-nightly-20260927023342",
|
|
58
|
+
"@backstage/config": "0.0.0-nightly-20260927023342",
|
|
59
|
+
"@backstage/errors": "0.0.0-nightly-20260927023342",
|
|
60
|
+
"@backstage/integration": "0.0.0-nightly-20260927023342",
|
|
61
|
+
"@backstage/integration-aws-node": "0.0.0-nightly-20260927023342",
|
|
62
|
+
"@backstage/plugin-search-common": "0.0.0-nightly-20260927023342",
|
|
63
63
|
"@backstage/plugin-techdocs-common": "0.1.1",
|
|
64
64
|
"@google-cloud/storage": "^7.0.0",
|
|
65
65
|
"@smithy/node-http-handler": "^3.0.0",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"winston": "^3.2.1"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@backstage/backend-test-utils": "0.0.0-nightly-
|
|
82
|
-
"@backstage/cli": "0.0.0-nightly-
|
|
81
|
+
"@backstage/backend-test-utils": "0.0.0-nightly-20260927023342",
|
|
82
|
+
"@backstage/cli": "0.0.0-nightly-20260927023342",
|
|
83
83
|
"@types/fs-extra": "^11.0.0",
|
|
84
84
|
"@types/js-yaml": "^4.0.0",
|
|
85
85
|
"@types/mime-types": "^2.1.0",
|