diff --git a/docs/api-commands.md b/docs/api-commands.md index 3a43fb60ca4fc..304e9de8762c0 100644 --- a/docs/api-commands.md +++ b/docs/api-commands.md @@ -59,6 +59,7 @@ Alias: `build`. | Options | Default | Description | | -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------- | | `--skip-image-compression` | `false` | Skip compression of image assets. You usually won't want to skip this unless your images have already been optimized. | +| `--skip-next-release` | `false` | Skip the next release documents when versioning is enabled. This will not build HTML files for documents in `/docs` directory.| Generates the static website, applying translations if necessary. Useful for building the website prior to deployment. diff --git a/v1/lib/__tests__/build-files.test.js b/v1/lib/__tests__/build-files.test.js index 2c1203179f8a1..5c0d34cb4efc2 100644 --- a/v1/lib/__tests__/build-files.test.js +++ b/v1/lib/__tests__/build-files.test.js @@ -31,6 +31,11 @@ function generateSite() { shell.exec('yarn build', {silent: true}); } +function generateSiteSkipNextRelease() { + shell.cd('website'); + shell.exec('yarn build --skip-next-release', {silent: true}); +} + function clearBuildFolder() { return rimraf(buildDir); } @@ -94,3 +99,41 @@ describe('Build files', () => { }); }); }); + +describe('Build files but skip next release', () => { + beforeEach(() => { + shell.cd(CWD); + }); + + beforeAll(() => { + generateSiteSkipNextRelease(); + return Promise.all([ + glob(`${docsDir}/**/*.md`), + glob(`${buildDir}/${siteConfig.projectName}/docs/**/*.html`), + glob(`${docsDir}/assets/*`), + glob(`${buildDir}/${siteConfig.projectName}/img/*`), + ]).then(results => { + [ + inputMarkdownFiles, + outputHTMLFiles, + inputAssetsFiles, + outputAssetsFiles, + ] = results; + }); + }); + + afterAll(() => { + clearBuildFolder(); + }); + + test('Did not generate HTML files from markdown files for next release', () => { + const metadata = outputHTMLFiles.map(file => + filepath.create(file).basename(), + ); + inputMarkdownFiles.forEach(file => { + const data = fs.readFileSync(file, 'utf8'); + const frontmatter = fm(data); + expect(metadata).not.toContain(`${frontmatter.attributes.id}.html`); + }); + }); +}); diff --git a/v1/lib/server/__tests__/start.test.js b/v1/lib/server/__tests__/start.test.js index c394a5081c6fd..5453207d92d6f 100644 --- a/v1/lib/server/__tests__/start.test.js +++ b/v1/lib/server/__tests__/start.test.js @@ -18,7 +18,7 @@ const siteConfig = require(`${process.cwd()}/siteConfig.js`); // siteConfig virtually. jest.mock(`${process.cwd()}/siteConfig.js`, () => jest.fn(), {virtual: true}); -jest.mock('commander'); +jest.genMockFromModule('commander'); jest.mock('react-dev-utils/openBrowser'); jest.mock('portfinder'); jest.mock('../liveReloadServer.js'); diff --git a/v1/lib/server/readMetadata.js b/v1/lib/server/readMetadata.js index 7c2048dd44af4..6878583d5ae86 100644 --- a/v1/lib/server/readMetadata.js +++ b/v1/lib/server/readMetadata.js @@ -10,6 +10,7 @@ const CWD = process.cwd(); const path = require('path'); const fs = require('fs'); const glob = require('glob'); +const program = require('commander'); const metadataUtils = require('./metadataUtils'); @@ -37,6 +38,8 @@ const SupportedHeaderFields = new Set([ 'custom_edit_url', ]); +program.option('--skip-next-release').parse(process.argv); + let allSidebars; if (fs.existsSync(`${CWD}/sidebars.json`)) { allSidebars = require(`${CWD}/sidebars.json`); @@ -54,6 +57,14 @@ function getDocsPath() { return siteConfig.customDocsPath ? siteConfig.customDocsPath : 'docs'; } +function shouldGenerateNextReleaseDocs() { + return !( + env.versioning.enabled && + program.name() === 'docusaurus-build' && + program.skipNextRelease + ); +} + // returns map from id to object containing sidebar ordering info function readSidebar(sidebars = {}) { Object.assign(sidebars, versionFallback.sidebarData()); @@ -220,74 +231,76 @@ function generateMetadataDocs() { const metadatas = {}; const defaultMetadatas = {}; - // metadata for english files - const docsDir = path.join(CWD, '../', getDocsPath()); - let files = glob.sync(`${docsDir}/**`); - files.forEach(file => { - const extension = path.extname(file); + if (shouldGenerateNextReleaseDocs()) { + // metadata for english files + const docsDir = path.join(CWD, '../', getDocsPath()); + let files = glob.sync(`${docsDir}/**`); + files.forEach(file => { + const extension = path.extname(file); - if (extension === '.md' || extension === '.markdown') { - const res = processMetadata(file, docsDir); + if (extension === '.md' || extension === '.markdown') { + const res = processMetadata(file, docsDir); - if (!res) { - return; - } - const metadata = res.metadata; - metadatas[metadata.id] = metadata; - - // 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 => currentLanguage !== 'en') - .forEach(currentLanguage => { - const baseMetadata = Object.assign({}, metadata); - baseMetadata.id = baseMetadata.id - .toString() - .replace(/^en-/, `${currentLanguage}-`); - if (baseMetadata.permalink) { - baseMetadata.permalink = baseMetadata.permalink - .toString() - .replace( - new RegExp(`^${docsPart}en/`), - `${docsPart}${currentLanguage}/`, - ); - } - if (baseMetadata.next) { - baseMetadata.next = baseMetadata.next - .toString() - .replace(/^en-/, `${currentLanguage}-`); - } - if (baseMetadata.previous) { - baseMetadata.previous = baseMetadata.previous + if (!res) { + return; + } + const metadata = res.metadata; + metadatas[metadata.id] = metadata; + + // 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 => currentLanguage !== 'en') + .forEach(currentLanguage => { + const baseMetadata = Object.assign({}, metadata); + baseMetadata.id = baseMetadata.id .toString() .replace(/^en-/, `${currentLanguage}-`); - } - baseMetadata.language = currentLanguage; - defaultMetadatas[baseMetadata.id] = baseMetadata; - }); - Object.assign(metadatas, defaultMetadatas); - } - }); + if (baseMetadata.permalink) { + baseMetadata.permalink = baseMetadata.permalink + .toString() + .replace( + new RegExp(`^${docsPart}en/`), + `${docsPart}${currentLanguage}/`, + ); + } + if (baseMetadata.next) { + baseMetadata.next = baseMetadata.next + .toString() + .replace(/^en-/, `${currentLanguage}-`); + } + if (baseMetadata.previous) { + baseMetadata.previous = baseMetadata.previous + .toString() + .replace(/^en-/, `${currentLanguage}-`); + } + baseMetadata.language = currentLanguage; + defaultMetadatas[baseMetadata.id] = baseMetadata; + }); + Object.assign(metadatas, defaultMetadatas); + } + }); - // metadata for non-english docs - const translatedDir = path.join(CWD, 'translated_docs'); - files = glob.sync(`${CWD}/translated_docs/**`); - files.forEach(file => { - if (!utils.getLanguage(file, translatedDir)) { - return; - } + // metadata for non-english docs + const translatedDir = path.join(CWD, 'translated_docs'); + files = glob.sync(`${CWD}/translated_docs/**`); + files.forEach(file => { + if (!utils.getLanguage(file, translatedDir)) { + return; + } - const extension = path.extname(file); + const extension = path.extname(file); - if (extension === '.md' || extension === '.markdown') { - const res = processMetadata(file, translatedDir); - if (!res) { - return; + if (extension === '.md' || extension === '.markdown') { + const res = processMetadata(file, translatedDir); + if (!res) { + return; + } + const metadata = res.metadata; + metadatas[metadata.id] = metadata; } - const metadata = res.metadata; - metadatas[metadata.id] = metadata; - } - }); + }); + } // metadata for versioned docs const versionData = versionFallback.docData();