mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-09 23:27:28 +02:00
ESLintify Part 1 (#837)
* ESLint-ify * Allow empty try/catch * Escape regexp
This commit is contained in:
parent
128dbfca0a
commit
e8e3f42685
44 changed files with 466 additions and 555 deletions
|
@ -13,9 +13,9 @@ const siteConfig = require(CWD + '/siteConfig.js');
|
|||
|
||||
const join = path.join;
|
||||
|
||||
const languages_js = join(CWD, 'languages.js');
|
||||
const versions_json = join(CWD, 'versions.json');
|
||||
const versions_js = join(CWD, 'pages/en/versions.js');
|
||||
const languagesFile = join(CWD, 'languages.js');
|
||||
const versionsJSONFile = join(CWD, 'versions.json');
|
||||
const versionsFile = join(CWD, 'pages/en/versions.js');
|
||||
|
||||
class Translation {
|
||||
constructor() {
|
||||
|
@ -28,17 +28,15 @@ class Translation {
|
|||
},
|
||||
];
|
||||
|
||||
this._load();
|
||||
this.load();
|
||||
}
|
||||
|
||||
enabledLanguages() {
|
||||
return this.languages.filter(lang => lang.enabled);
|
||||
}
|
||||
enabledLanguages = () => this.languages.filter(lang => lang.enabled);
|
||||
|
||||
_load() {
|
||||
if (fs.existsSync(languages_js)) {
|
||||
load() {
|
||||
if (fs.existsSync(languagesFile)) {
|
||||
this.enabled = true;
|
||||
this.languages = require(languages_js);
|
||||
this.languages = require(languagesFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +48,7 @@ class Versioning {
|
|||
this.versions = [];
|
||||
this.missingVersionsPage = false;
|
||||
|
||||
this._load();
|
||||
this.load();
|
||||
}
|
||||
|
||||
printMissingVersionsPageError() {
|
||||
|
@ -61,16 +59,16 @@ class Versioning {
|
|||
);
|
||||
}
|
||||
|
||||
_load() {
|
||||
if (fs.existsSync(versions_json)) {
|
||||
load() {
|
||||
if (fs.existsSync(versionsJSONFile)) {
|
||||
this.enabled = true;
|
||||
this.versions = JSON.parse(fs.readFileSync(versions_json, 'utf8'));
|
||||
this.versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8'));
|
||||
this.defaultVersion = siteConfig.defaultVersionShown
|
||||
? siteConfig.defaultVersionShown
|
||||
: this.versions[0]; // otherwise show the latest version (other than next/master)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(versions_js)) {
|
||||
if (!fs.existsSync(versionsFile)) {
|
||||
this.missingVersionsPage = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,12 +137,10 @@ async function execute() {
|
|||
} else {
|
||||
file = join(CWD, 'versioned_docs', metadata.source);
|
||||
}
|
||||
} else if (metadata.language === 'en') {
|
||||
file = join(CWD, '..', readMetadata.getDocsPath(), metadata.source);
|
||||
} else {
|
||||
if (metadata.language === 'en') {
|
||||
file = join(CWD, '..', readMetadata.getDocsPath(), metadata.source);
|
||||
} else {
|
||||
file = join(CWD, 'translated_docs', metadata.language, metadata.source);
|
||||
}
|
||||
file = join(CWD, 'translated_docs', metadata.language, metadata.source);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(file)) {
|
||||
|
@ -156,14 +154,14 @@ async function execute() {
|
|||
const language = metadata.language;
|
||||
|
||||
// generate table of contents if appropriate
|
||||
if (rawContent && rawContent.indexOf(TABLE_OF_CONTENTS_TOKEN) != -1) {
|
||||
if (rawContent && rawContent.indexOf(TABLE_OF_CONTENTS_TOKEN) !== -1) {
|
||||
rawContent = insertTableOfContents(rawContent);
|
||||
}
|
||||
|
||||
let defaultVersion = env.versioning.defaultVersion;
|
||||
|
||||
// replace any links to markdown files to their website html links
|
||||
Object.keys(mdToHtml).forEach(function(key, index) {
|
||||
Object.keys(mdToHtml).forEach(key => {
|
||||
let link = mdToHtml[key];
|
||||
link = utils.getPath(link, siteConfig.cleanUrl);
|
||||
link = link.replace('/en/', '/' + language + '/');
|
||||
|
@ -489,34 +487,33 @@ async function execute() {
|
|||
const match = regexLang.exec(normalizedFile);
|
||||
const langParts = match[1].split(sep);
|
||||
if (langParts.indexOf('en') !== -1) {
|
||||
// copy and compile a page for each enabled language from the English file
|
||||
// Copy and compile a page for each enabled language from the English file.
|
||||
for (let i = 0; i < enabledLanguages.length; i++) {
|
||||
let language = enabledLanguages[i];
|
||||
// skip conversion from english file if a file exists for this language
|
||||
const language = enabledLanguages[i];
|
||||
// Skip conversion from English file if a file exists for this language.
|
||||
if (
|
||||
language !== 'en' &&
|
||||
fs.existsSync(
|
||||
language === 'en' ||
|
||||
!fs.existsSync(
|
||||
normalizedFile.replace(sep + 'en' + sep, sep + language + sep)
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
translate.setLanguage(language);
|
||||
const str = renderToStaticMarkupWithDoctype(
|
||||
<Site
|
||||
language={language}
|
||||
config={siteConfig}
|
||||
title={ReactComp.title}
|
||||
description={ReactComp.description}
|
||||
metadata={{id: pageID}}>
|
||||
<ReactComp language={language} />
|
||||
</Site>
|
||||
);
|
||||
writeFileAndCreateFolder(
|
||||
// TODO: use path functions
|
||||
targetFile.replace(sep + 'en' + sep, sep + language + sep),
|
||||
str
|
||||
);
|
||||
}
|
||||
translate.setLanguage(language);
|
||||
const str = renderToStaticMarkupWithDoctype(
|
||||
<Site
|
||||
language={language}
|
||||
config={siteConfig}
|
||||
title={ReactComp.title}
|
||||
description={ReactComp.description}
|
||||
metadata={{id: pageID}}>
|
||||
<ReactComp language={language} />
|
||||
</Site>
|
||||
);
|
||||
writeFileAndCreateFolder(
|
||||
// TODO: use path functions
|
||||
targetFile.replace(sep + 'en' + sep, sep + language + sep),
|
||||
str
|
||||
);
|
||||
}
|
||||
|
||||
// write to base level
|
||||
|
|
|
@ -55,7 +55,9 @@ function extractMetadata(content) {
|
|||
.trim();
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch (e) {}
|
||||
} catch (err) {
|
||||
// Ignore the error as it means it's not a JSON value.
|
||||
}
|
||||
metadata[key] = value;
|
||||
}
|
||||
return {metadata, rawContent: both.content};
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const CWD = process.cwd();
|
||||
const fs = require('fs');
|
||||
|
||||
const Metadata = require('../core/metadata.js');
|
||||
const fs = require('fs');
|
||||
|
||||
const CWD = process.cwd();
|
||||
let languages;
|
||||
if (fs.existsSync(CWD + '/languages.js')) {
|
||||
languages = require(CWD + '/languages.js');
|
||||
|
@ -24,10 +25,9 @@ if (fs.existsSync(CWD + '/languages.js')) {
|
|||
|
||||
// returns data broken up into categories for a sidebar
|
||||
function readCategories(sidebar) {
|
||||
const enabledLanguages = [];
|
||||
languages.filter(lang => lang.enabled).map(lang => {
|
||||
enabledLanguages.push(lang.tag);
|
||||
});
|
||||
const enabledLanguages = languages
|
||||
.filter(lang => lang.enabled)
|
||||
.map(lang => lang.tag);
|
||||
|
||||
const allCategories = {};
|
||||
|
||||
|
@ -88,7 +88,9 @@ function readCategories(sidebar) {
|
|||
let i = 0;
|
||||
while (metadata && i++ < 1000) {
|
||||
if (!currentCategory || metadata.category !== currentCategory.name) {
|
||||
currentCategory && categories.push(currentCategory);
|
||||
if (currentCategory) {
|
||||
categories.push(currentCategory);
|
||||
}
|
||||
currentCategory = {
|
||||
name: metadata.category,
|
||||
links: [],
|
||||
|
|
|
@ -66,7 +66,8 @@ function readSidebar() {
|
|||
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = ids[i];
|
||||
let previous, next;
|
||||
let previous;
|
||||
let next;
|
||||
if (i > 0) previous = ids[i - 1];
|
||||
if (i < ids.length - 1) next = ids[i + 1];
|
||||
order[id] = {
|
||||
|
@ -86,13 +87,13 @@ function processMetadata(file, refDir) {
|
|||
const language = utils.getLanguage(file, refDir) || 'en';
|
||||
|
||||
const metadata = {};
|
||||
for (const fieldName of Object.keys(result.metadata)) {
|
||||
Object.keys(result.metadata).forEach(fieldName => {
|
||||
if (SupportedHeaderFields.has(fieldName)) {
|
||||
metadata[fieldName] = result.metadata[fieldName];
|
||||
} else {
|
||||
console.warn(`Header field "${fieldName}" in ${file} is not supported.`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const rawContent = result.rawContent;
|
||||
|
||||
|
@ -193,10 +194,8 @@ function generateMetadataDocs() {
|
|||
// create a default list of documents for each enabled language based on docs in English
|
||||
// these will get replaced if/when the localized file is downloaded from crowdin
|
||||
enabledLanguages
|
||||
.filter(currentLanguage => {
|
||||
return currentLanguage != 'en';
|
||||
})
|
||||
.map(currentLanguage => {
|
||||
.filter(currentLanguage => currentLanguage !== 'en')
|
||||
.forEach(currentLanguage => {
|
||||
let baseMetadata = Object.assign({}, metadata);
|
||||
baseMetadata['id'] = baseMetadata['id']
|
||||
.toString()
|
||||
|
@ -291,7 +290,7 @@ function generateMetadataDocs() {
|
|||
});
|
||||
|
||||
fs.writeFileSync(
|
||||
__dirname + '/../core/metadata.js',
|
||||
path.join(__dirname, '/../core/metadata.js'),
|
||||
'/**\n' +
|
||||
' * @' +
|
||||
'generated\n' + // separate this out for Nuclide treating @generated as readonly
|
||||
|
@ -360,7 +359,7 @@ function generateMetadataBlog() {
|
|||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
__dirname + '/../core/MetadataBlog.js',
|
||||
path.join(__dirname, '/../core/MetadataBlog.js'),
|
||||
'/**\n' +
|
||||
' * @' +
|
||||
'generated\n' + // separate this out for Nuclide treating @generated as readonly
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-cond-assign */
|
||||
|
||||
function execute(port, options) {
|
||||
const extractTranslations = require('../write-translations');
|
||||
|
||||
|
@ -45,8 +47,18 @@ function execute(port, options) {
|
|||
const join = path.join;
|
||||
const sep = path.sep;
|
||||
|
||||
// remove a module and child modules from require cache, so server does not have
|
||||
// to be restarted
|
||||
function removeModulePathFromCache(moduleName) {
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
|
||||
if (cacheKey.indexOf(moduleName) > 0) {
|
||||
delete module.constructor._pathCache[cacheKey];
|
||||
}
|
||||
});
|
||||
/* eslint-enable no-underscore-dangle */
|
||||
}
|
||||
|
||||
// Remove a module and child modules from require cache, so server
|
||||
// does not have to be restarted.
|
||||
function removeModuleAndChildrenFromCache(moduleName) {
|
||||
let mod = require.resolve(moduleName);
|
||||
if (mod && (mod = require.cache[mod])) {
|
||||
|
@ -59,14 +71,6 @@ function execute(port, options) {
|
|||
}
|
||||
}
|
||||
|
||||
function removeModulePathFromCache(moduleName) {
|
||||
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
|
||||
if (cacheKey.indexOf(moduleName) > 0) {
|
||||
delete module.constructor._pathCache[cacheKey];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
let readMetadata = require('./readMetadata.js');
|
||||
|
@ -147,6 +151,36 @@ function execute(port, options) {
|
|||
});
|
||||
}
|
||||
|
||||
function startLiveReload() {
|
||||
// Start LiveReload server.
|
||||
process.env.NODE_ENV = 'development';
|
||||
const server = tinylr();
|
||||
server.listen(constants.LIVE_RELOAD_PORT, function() {
|
||||
console.log(
|
||||
'LiveReload server started on port %d',
|
||||
constants.LIVE_RELOAD_PORT
|
||||
);
|
||||
});
|
||||
|
||||
// gaze watches some specified dirs and triggers a callback when they change.
|
||||
gaze(
|
||||
[
|
||||
'../' + readMetadata.getDocsPath() + '/**/*', // docs
|
||||
'**/*', // website
|
||||
'!node_modules/**/*', // node_modules
|
||||
],
|
||||
function() {
|
||||
// Listen for all kinds of file changes - modified/added/deleted.
|
||||
this.on('all', function() {
|
||||
// Notify LiveReload clients that there's a change.
|
||||
// Typically, LiveReload will only refresh the changed paths,
|
||||
// so we use / here to force a full-page reload.
|
||||
server.notifyClients(['/']);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
reloadMetadata();
|
||||
|
@ -200,12 +234,10 @@ function execute(port, options) {
|
|||
} else {
|
||||
file = join(CWD, 'versioned_docs', metadata.source);
|
||||
}
|
||||
} else if (!env.translation.enabled || metadata.language === 'en') {
|
||||
file = join(CWD, '..', readMetadata.getDocsPath(), metadata.source);
|
||||
} else {
|
||||
if (!env.translation.enabled || metadata.language === 'en') {
|
||||
file = join(CWD, '..', readMetadata.getDocsPath(), metadata.source);
|
||||
} else {
|
||||
file = join(CWD, 'translated_docs', metadata.language, metadata.source);
|
||||
}
|
||||
file = join(CWD, 'translated_docs', metadata.language, metadata.source);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(file)) {
|
||||
|
@ -225,7 +257,7 @@ function execute(port, options) {
|
|||
let defaultVersion = env.versioning.defaultVersion;
|
||||
|
||||
// replace any links to markdown files to their website html links
|
||||
Object.keys(mdToHtml).forEach(function(key, index) {
|
||||
Object.keys(mdToHtml).forEach(key => {
|
||||
let link = mdToHtml[key];
|
||||
link = utils.getPath(link, siteConfig.cleanUrl);
|
||||
link = link.replace('/en/', '/' + language + '/');
|
||||
|
@ -333,8 +365,8 @@ function execute(port, options) {
|
|||
);
|
||||
const str = renderToStaticMarkupWithDoctype(blogPageComp);
|
||||
|
||||
let path = (page > 0 ? 'page' + (page + 1) : '') + '/index.html';
|
||||
blogPages[path] = str;
|
||||
const pagePath = (page > 0 ? 'page' + (page + 1) : '') + '/index.html';
|
||||
blogPages[pagePath] = str;
|
||||
}
|
||||
|
||||
let parts = req.path.toString().split('blog/');
|
||||
|
@ -398,7 +430,7 @@ function execute(port, options) {
|
|||
|
||||
// handle all other main pages
|
||||
app.get(pageRouting(siteConfig.baseUrl), (req, res, next) => {
|
||||
// look for user provided html file first
|
||||
// Look for user-provided HTML file first.
|
||||
let htmlFile = req.path.toString().replace(siteConfig.baseUrl, '');
|
||||
htmlFile = join(CWD, 'pages', htmlFile);
|
||||
if (
|
||||
|
@ -470,8 +502,8 @@ function execute(port, options) {
|
|||
fs.existsSync((userFile = englishFile))
|
||||
) {
|
||||
// copy into docusaurus so require paths work
|
||||
let parts = userFile.split('pages' + sep);
|
||||
let tempFile = join(__dirname, '..', 'pages', parts[1]);
|
||||
let userFileParts = userFile.split('pages' + sep);
|
||||
let tempFile = join(__dirname, '..', 'pages', userFileParts[1]);
|
||||
tempFile = tempFile.replace(
|
||||
path.basename(file),
|
||||
'temp' + path.basename(file)
|
||||
|
@ -501,7 +533,6 @@ function execute(port, options) {
|
|||
res.send(str);
|
||||
} else {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -598,36 +629,6 @@ function execute(port, options) {
|
|||
|
||||
if (options.watch) startLiveReload();
|
||||
app.listen(port);
|
||||
|
||||
function startLiveReload() {
|
||||
// Start LiveReload server.
|
||||
process.env.NODE_ENV = 'development';
|
||||
const server = tinylr();
|
||||
server.listen(constants.LIVE_RELOAD_PORT, function() {
|
||||
console.log(
|
||||
'LiveReload server started on port %d',
|
||||
constants.LIVE_RELOAD_PORT
|
||||
);
|
||||
});
|
||||
|
||||
// gaze watches some specified dirs and triggers a callback when they change.
|
||||
gaze(
|
||||
[
|
||||
'../' + readMetadata.getDocsPath() + '/**/*', // docs
|
||||
'**/*', // website
|
||||
'!node_modules/**/*', // node_modules
|
||||
],
|
||||
function() {
|
||||
// Listen for all kinds of file changes - modified/added/deleted.
|
||||
this.on('all', function() {
|
||||
// Notify LiveReload clients that there's a change.
|
||||
// Typically, LiveReload will only refresh the changed paths,
|
||||
// so we use / here to force a full-page reload.
|
||||
server.notifyClients(['/']);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = execute;
|
||||
|
|
|
@ -32,8 +32,6 @@ MetadataBlog = require('../core/MetadataBlog.js');
|
|||
module.exports = function(callback) {
|
||||
console.log('sitemap.js triggered...');
|
||||
|
||||
let urls = [];
|
||||
|
||||
let files = glob.sync(CWD + '/pages/en/**/*.js');
|
||||
|
||||
// English-only is the default.
|
||||
|
@ -48,25 +46,23 @@ module.exports = function(callback) {
|
|||
// If we have a languages.js file, get all the enabled languages in there
|
||||
if (fs.existsSync(CWD + '/languages.js')) {
|
||||
let languages = require(CWD + '/languages.js');
|
||||
enabledLanguages = languages.filter(lang => {
|
||||
return lang.enabled == true;
|
||||
});
|
||||
enabledLanguages = languages.filter(lang => lang.enabled);
|
||||
}
|
||||
|
||||
// create a url mapping to all the enabled languages files
|
||||
files.map(file => {
|
||||
// Create a url mapping to all the enabled languages files
|
||||
const urls = files.map(file => {
|
||||
let url = file.split('/pages/en')[1];
|
||||
url = siteConfig.cleanUrl
|
||||
? url.replace(/\.js$/, '')
|
||||
: url.replace(/\.js$/, '.html');
|
||||
let links = enabledLanguages.map(lang => {
|
||||
const links = enabledLanguages.map(lang => {
|
||||
let langUrl = lang.tag + url;
|
||||
return {lang: lang.tag, url: langUrl};
|
||||
});
|
||||
urls.push({url, changefreq: 'weekly', priority: 0.5, links});
|
||||
return {url, changefreq: 'weekly', priority: 0.5, links};
|
||||
});
|
||||
|
||||
MetadataBlog.map(blog => {
|
||||
MetadataBlog.forEach(blog => {
|
||||
urls.push({
|
||||
url: '/blog/' + utils.getPath(blog.path, siteConfig.cleanUrl),
|
||||
changefreq: 'weekly',
|
||||
|
@ -76,7 +72,7 @@ module.exports = function(callback) {
|
|||
|
||||
Object.keys(Metadata)
|
||||
.filter(key => Metadata[key].language === 'en')
|
||||
.map(key => {
|
||||
.forEach(key => {
|
||||
let doc = Metadata[key];
|
||||
let docUrl = utils.getPath(doc.permalink, siteConfig.cleanUrl);
|
||||
let links = enabledLanguages.map(lang => {
|
||||
|
@ -94,7 +90,7 @@ module.exports = function(callback) {
|
|||
const sm = sitemap.createSitemap({
|
||||
hostname: siteConfig.url,
|
||||
cacheTime: 600 * 1000, // 600 sec - cache purge period
|
||||
urls: urls,
|
||||
urls,
|
||||
});
|
||||
|
||||
sm.toXML((err, xml) => {
|
||||
|
|
|
@ -25,8 +25,8 @@ module.exports = function translatePlugin(babel) {
|
|||
description = attributes[i].value.value;
|
||||
}
|
||||
}
|
||||
/* use an expression container if inside a jsxelement */
|
||||
if (path.findParent(path => true).node.type === 'JSXElement') {
|
||||
/* use an expression container if inside a JSXElement */
|
||||
if (path.findParent(() => true).node.type === 'JSXElement') {
|
||||
path.replaceWith(
|
||||
t.jSXExpressionContainer(
|
||||
t.callExpression(t.identifier('translate'), [
|
||||
|
|
|
@ -96,7 +96,7 @@ files.forEach(file => {
|
|||
|
||||
// returns the version to use for a document based on its id and
|
||||
// what the requested version is
|
||||
function docVersion(id, req_version) {
|
||||
function docVersion(id, reqVersion) {
|
||||
if (!available[id]) {
|
||||
return null;
|
||||
}
|
||||
|
@ -104,13 +104,10 @@ function docVersion(id, req_version) {
|
|||
// is found, then check if that version has an available file to use
|
||||
let requestedFound = false;
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
if (versions[i] === req_version) {
|
||||
if (versions[i] === reqVersion) {
|
||||
requestedFound = true;
|
||||
}
|
||||
if (!requestedFound) {
|
||||
continue;
|
||||
}
|
||||
if (available[id].has(versions[i])) {
|
||||
if (requestedFound && available[id].has(versions[i])) {
|
||||
return versions[i];
|
||||
}
|
||||
}
|
||||
|
@ -243,18 +240,16 @@ function docData() {
|
|||
}
|
||||
|
||||
// return the version of the sidebar to use given a requested version
|
||||
function sidebarVersion(req_version) {
|
||||
function sidebarVersion(reqVersion) {
|
||||
// iterate through versions until a version less than or equal to the requested
|
||||
// is found, then check if that version has an available file to use
|
||||
let requestedFound = false;
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
if (versions[i] === req_version) {
|
||||
if (versions[i] === reqVersion) {
|
||||
requestedFound = true;
|
||||
}
|
||||
if (!requestedFound) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
requestedFound &&
|
||||
fs.existsSync(
|
||||
CWD + '/versioned_sidebars/version-' + versions[i] + '-sidebars.json'
|
||||
)
|
||||
|
@ -263,7 +258,7 @@ function sidebarVersion(req_version) {
|
|||
}
|
||||
}
|
||||
throw new Error(
|
||||
`No sidebar file available to use for version ${req_version}. Verify that 'version-${req_version}-sidebars.json' exists.`
|
||||
`No sidebar file available to use for version ${reqVersion}. Verify that 'version-${reqVersion}-sidebars.json' exists.`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue