mirror of
https://github.com/Snigdha-OS/documentation.git
synced 2025-09-10 19:54:57 +02:00
295 lines
13 KiB
JavaScript
295 lines
13 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.createDocsByIdIndex = exports.toCategoryIndexMatcherParam = exports.isCategoryIndex = exports.getMainDocId = exports.addDocNavigation = exports.processDocMetadata = exports.readVersionDocs = exports.readDocFile = void 0;
|
|
const tslib_1 = require("tslib");
|
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
const utils_1 = require("@docusaurus/utils");
|
|
const lastUpdate_1 = require("./lastUpdate");
|
|
const slug_1 = tslib_1.__importDefault(require("./slug"));
|
|
const numberPrefix_1 = require("./numberPrefix");
|
|
const frontMatter_1 = require("./frontMatter");
|
|
const utils_2 = require("./sidebars/utils");
|
|
async function readLastUpdateData(filePath, options, lastUpdateFrontMatter) {
|
|
const { showLastUpdateAuthor, showLastUpdateTime } = options;
|
|
if (showLastUpdateAuthor || showLastUpdateTime) {
|
|
const frontMatterTimestamp = lastUpdateFrontMatter?.date
|
|
? new Date(lastUpdateFrontMatter.date).getTime() / 1000
|
|
: undefined;
|
|
if (lastUpdateFrontMatter?.author && lastUpdateFrontMatter.date) {
|
|
return {
|
|
lastUpdatedAt: frontMatterTimestamp,
|
|
lastUpdatedBy: lastUpdateFrontMatter.author,
|
|
};
|
|
}
|
|
// Use fake data in dev for faster development.
|
|
const fileLastUpdateData = process.env.NODE_ENV === 'production'
|
|
? await (0, lastUpdate_1.getFileLastUpdate)(filePath)
|
|
: {
|
|
author: 'Author',
|
|
timestamp: 1539502055,
|
|
};
|
|
const { author, timestamp } = fileLastUpdateData ?? {};
|
|
return {
|
|
lastUpdatedBy: showLastUpdateAuthor
|
|
? lastUpdateFrontMatter?.author ?? author
|
|
: undefined,
|
|
lastUpdatedAt: showLastUpdateTime
|
|
? frontMatterTimestamp ?? timestamp
|
|
: undefined,
|
|
};
|
|
}
|
|
return {};
|
|
}
|
|
async function readDocFile(versionMetadata, source) {
|
|
const contentPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(versionMetadata), source);
|
|
const filePath = path_1.default.join(contentPath, source);
|
|
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
return { source, content, contentPath, filePath };
|
|
}
|
|
exports.readDocFile = readDocFile;
|
|
async function readVersionDocs(versionMetadata, options) {
|
|
const sources = await (0, utils_1.Globby)(options.include, {
|
|
cwd: versionMetadata.contentPath,
|
|
ignore: options.exclude,
|
|
});
|
|
return Promise.all(sources.map((source) => readDocFile(versionMetadata, source)));
|
|
}
|
|
exports.readVersionDocs = readVersionDocs;
|
|
async function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, }) {
|
|
const { source, content, contentPath, filePath } = docFile;
|
|
const { siteDir, i18n, siteConfig: { markdown: { parseFrontMatter }, }, } = context;
|
|
const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = await (0, utils_1.parseMarkdownFile)({
|
|
filePath,
|
|
fileContent: content,
|
|
parseFrontMatter,
|
|
});
|
|
const frontMatter = (0, frontMatter_1.validateDocFrontMatter)(unsafeFrontMatter);
|
|
const { custom_edit_url: customEditURL,
|
|
// Strip number prefixes by default
|
|
// (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
|
|
// but allow to disable this behavior with front matter
|
|
parse_number_prefixes: parseNumberPrefixes = true, last_update: lastUpdateFrontMatter, } = frontMatter;
|
|
const lastUpdate = await readLastUpdateData(filePath, options, lastUpdateFrontMatter);
|
|
// E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
|
|
const sourceFileNameWithoutExtension = path_1.default.basename(source, path_1.default.extname(source));
|
|
// E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
|
|
const sourceDirName = path_1.default.dirname(source);
|
|
const { filename: unprefixedFileName, numberPrefix } = parseNumberPrefixes
|
|
? options.numberPrefixParser(sourceFileNameWithoutExtension)
|
|
: { filename: sourceFileNameWithoutExtension, numberPrefix: undefined };
|
|
const baseID = frontMatter.id ?? unprefixedFileName;
|
|
if (baseID.includes('/')) {
|
|
throw new Error(`Document id "${baseID}" cannot include slash.`);
|
|
}
|
|
// For autogenerated sidebars, sidebar position can come from filename number
|
|
// prefix or front matter
|
|
const sidebarPosition = frontMatter.sidebar_position ?? numberPrefix;
|
|
// TODO legacy retrocompatibility
|
|
// I think it's bad to affect the front matter id with the dirname?
|
|
function computeDirNameIdPrefix() {
|
|
if (sourceDirName === '.') {
|
|
return undefined;
|
|
}
|
|
// Eventually remove the number prefixes from intermediate directories
|
|
return parseNumberPrefixes
|
|
? (0, numberPrefix_1.stripPathNumberPrefixes)(sourceDirName, options.numberPrefixParser)
|
|
: sourceDirName;
|
|
}
|
|
const id = [computeDirNameIdPrefix(), baseID].filter(Boolean).join('/');
|
|
const docSlug = (0, slug_1.default)({
|
|
baseID,
|
|
source,
|
|
sourceDirName,
|
|
frontMatterSlug: frontMatter.slug,
|
|
stripDirNumberPrefixes: parseNumberPrefixes,
|
|
numberPrefixParser: options.numberPrefixParser,
|
|
});
|
|
// Note: the title is used by default for page title, sidebar label,
|
|
// pagination buttons... frontMatter.title should be used in priority over
|
|
// contentTitle (because it can contain markdown/JSX syntax)
|
|
const title = frontMatter.title ?? contentTitle ?? baseID;
|
|
const description = frontMatter.description ?? excerpt ?? '';
|
|
const permalink = (0, utils_1.normalizeUrl)([versionMetadata.path, docSlug]);
|
|
function getDocEditUrl() {
|
|
const relativeFilePath = path_1.default.relative(contentPath, filePath);
|
|
if (typeof options.editUrl === 'function') {
|
|
return options.editUrl({
|
|
version: versionMetadata.versionName,
|
|
versionDocsDirPath: (0, utils_1.posixPath)(path_1.default.relative(siteDir, versionMetadata.contentPath)),
|
|
docPath: (0, utils_1.posixPath)(relativeFilePath),
|
|
permalink,
|
|
locale: context.i18n.currentLocale,
|
|
});
|
|
}
|
|
else if (typeof options.editUrl === 'string') {
|
|
const isLocalized = contentPath === versionMetadata.contentPathLocalized;
|
|
const baseVersionEditUrl = isLocalized && options.editLocalizedFiles
|
|
? versionMetadata.editUrlLocalized
|
|
: versionMetadata.editUrl;
|
|
return (0, utils_1.getEditUrl)(relativeFilePath, baseVersionEditUrl);
|
|
}
|
|
return undefined;
|
|
}
|
|
const draft = (0, utils_1.isDraft)({ env, frontMatter });
|
|
const unlisted = (0, utils_1.isUnlisted)({ env, frontMatter });
|
|
const formatDate = (locale, date, calendar) => {
|
|
try {
|
|
return new Intl.DateTimeFormat(locale, {
|
|
day: 'numeric',
|
|
month: 'short',
|
|
year: 'numeric',
|
|
timeZone: 'UTC',
|
|
calendar,
|
|
}).format(date);
|
|
}
|
|
catch (err) {
|
|
logger_1.default.error `Can't format docs lastUpdatedAt date "${String(date)}"`;
|
|
throw err;
|
|
}
|
|
};
|
|
// Assign all of object properties during instantiation (if possible) for
|
|
// NodeJS optimization.
|
|
// Adding properties to object after instantiation will cause hidden
|
|
// class transitions.
|
|
return {
|
|
id,
|
|
title,
|
|
description,
|
|
source: (0, utils_1.aliasedSitePath)(filePath, siteDir),
|
|
sourceDirName,
|
|
slug: docSlug,
|
|
permalink,
|
|
draft,
|
|
unlisted,
|
|
editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
|
|
tags: (0, utils_1.normalizeFrontMatterTags)(versionMetadata.tagsPath, frontMatter.tags),
|
|
version: versionMetadata.versionName,
|
|
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
|
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
|
formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
|
|
? formatDate(i18n.currentLocale, new Date(lastUpdate.lastUpdatedAt * 1000), i18n.localeConfigs[i18n.currentLocale].calendar)
|
|
: undefined,
|
|
sidebarPosition,
|
|
frontMatter,
|
|
};
|
|
}
|
|
async function processDocMetadata(args) {
|
|
try {
|
|
return await doProcessDocMetadata(args);
|
|
}
|
|
catch (err) {
|
|
throw new Error(`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`, { cause: err });
|
|
}
|
|
}
|
|
exports.processDocMetadata = processDocMetadata;
|
|
function getUnlistedIds(docs) {
|
|
return new Set(docs.filter((doc) => doc.unlisted).map((doc) => doc.id));
|
|
}
|
|
function addDocNavigation({ docs, sidebarsUtils, }) {
|
|
const docsById = createDocsByIdIndex(docs);
|
|
const unlistedIds = getUnlistedIds(docs);
|
|
// Add sidebar/next/previous to the docs
|
|
function addNavData(doc) {
|
|
const navigation = sidebarsUtils.getDocNavigation({
|
|
docId: doc.id,
|
|
displayedSidebar: doc.frontMatter.displayed_sidebar,
|
|
unlistedIds,
|
|
});
|
|
const toNavigationLinkByDocId = (docId, type) => {
|
|
if (!docId) {
|
|
return undefined;
|
|
}
|
|
const navDoc = docsById[docId];
|
|
if (!navDoc) {
|
|
// This could only happen if user provided the ID through front matter
|
|
throw new Error(`Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`);
|
|
}
|
|
// Gracefully handle explicitly providing an unlisted doc ID in production
|
|
if (navDoc.unlisted) {
|
|
return undefined;
|
|
}
|
|
return (0, utils_2.toDocNavigationLink)(navDoc);
|
|
};
|
|
const previous = doc.frontMatter.pagination_prev !== undefined
|
|
? toNavigationLinkByDocId(doc.frontMatter.pagination_prev, 'prev')
|
|
: (0, utils_2.toNavigationLink)(navigation.previous, docsById);
|
|
const next = doc.frontMatter.pagination_next !== undefined
|
|
? toNavigationLinkByDocId(doc.frontMatter.pagination_next, 'next')
|
|
: (0, utils_2.toNavigationLink)(navigation.next, docsById);
|
|
return { ...doc, sidebar: navigation.sidebarName, previous, next };
|
|
}
|
|
const docsWithNavigation = docs.map(addNavData);
|
|
// Sort to ensure consistent output for tests
|
|
docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
|
|
return docsWithNavigation;
|
|
}
|
|
exports.addDocNavigation = addDocNavigation;
|
|
/**
|
|
* The "main doc" is the "version entry point"
|
|
* We browse this doc by clicking on a version:
|
|
* - the "home" doc (at '/docs/')
|
|
* - the first doc of the first sidebar
|
|
* - a random doc (if no docs are in any sidebar... edge case)
|
|
*/
|
|
function getMainDocId({ docs, sidebarsUtils, }) {
|
|
function getMainDoc() {
|
|
const versionHomeDoc = docs.find((doc) => doc.slug === '/');
|
|
const firstDocIdOfFirstSidebar = sidebarsUtils.getFirstDocIdOfFirstSidebar();
|
|
if (versionHomeDoc) {
|
|
return versionHomeDoc;
|
|
}
|
|
else if (firstDocIdOfFirstSidebar) {
|
|
return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar);
|
|
}
|
|
return docs[0];
|
|
}
|
|
return getMainDoc().id;
|
|
}
|
|
exports.getMainDocId = getMainDocId;
|
|
// By convention, Docusaurus considers some docs are "indexes":
|
|
// - index.md
|
|
// - readme.md
|
|
// - <folder>/<folder>.md
|
|
//
|
|
// This function is the default implementation of this convention
|
|
//
|
|
// Those index docs produce a different behavior
|
|
// - Slugs do not end with a weird "/index" suffix
|
|
// - Auto-generated sidebar categories link to them as intro
|
|
const isCategoryIndex = ({ fileName, directories, }) => {
|
|
const eligibleDocIndexNames = [
|
|
'index',
|
|
'readme',
|
|
directories[0]?.toLowerCase(),
|
|
];
|
|
return eligibleDocIndexNames.includes(fileName.toLowerCase());
|
|
};
|
|
exports.isCategoryIndex = isCategoryIndex;
|
|
/**
|
|
* `guides/sidebar/autogenerated.md` ->
|
|
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
*/
|
|
function toCategoryIndexMatcherParam({ source, sourceDirName, }) {
|
|
// source + sourceDirName are always posix-style
|
|
return {
|
|
fileName: path_1.default.posix.parse(source).name,
|
|
extension: path_1.default.posix.parse(source).ext,
|
|
directories: sourceDirName.split(path_1.default.posix.sep).reverse(),
|
|
};
|
|
}
|
|
exports.toCategoryIndexMatcherParam = toCategoryIndexMatcherParam;
|
|
// Docs are indexed by their id
|
|
function createDocsByIdIndex(docs) {
|
|
return lodash_1.default.keyBy(docs, (d) => d.id);
|
|
}
|
|
exports.createDocsByIdIndex = createDocsByIdIndex;
|