diff --git a/examples/docSidebar.js b/examples/sidebar.json similarity index 69% rename from examples/docSidebar.js rename to examples/sidebar.json index 9c96494a00..7a1d054018 100644 --- a/examples/docSidebar.js +++ b/examples/sidebar.json @@ -1,10 +1,10 @@ -module.exports = { - docs: { - Docusaurus: ["doc1"], +{ + "docs": { + "Docusaurus": ["doc1"], "First Category": ["doc2"], "Second Category": ["doc3"] }, "docs-other": { "First Category": ["doc4", "doc5"] } -}; +} diff --git a/lib/gen-doc-sidebar.js b/lib/gen-doc-sidebar.js deleted file mode 100644 index 0490322c5c..0000000000 --- a/lib/gen-doc-sidebar.js +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env node - -/* script to generate docSidebar.js file for users who are using - doc front mattters with category, layout, previous, and next fields */ -const glob = require("glob"); -const fs = require("fs"); -const path = require("path"); -const prettier = require("prettier"); - -function splitHeader(content) { - const lines = content.split("\n"); - let i = 1; - for (; i < lines.length - 1; ++i) { - if (lines[i] === "---") { - break; - } - } - return { - header: lines.slice(1, i + 1).join("\n"), - content: lines.slice(i + 1).join("\n") - }; -} - -// Extract markdown metadata header -function extractMetadata(content) { - const metadata = {}; - const both = splitHeader(content); - const lines = both.header.split("\n"); - for (let i = 0; i < lines.length - 1; ++i) { - const keyvalue = lines[i].split(":"); - const key = keyvalue[0].trim(); - let value = keyvalue.slice(1).join(":").trim(); - // Handle the case where you have "Community #10" - try { - value = JSON.parse(value); - } catch (e) {} - metadata[key] = value; - } - return { metadata, rawContent: both.content }; -} - -const docs = {}; -const sidebar = {}; - -const files = glob.sync(process.cwd() + "/../docs/**"); -files.forEach(file => { - const extension = path.extname(file); - if (extension === ".md" || extension === ".markdown") { - const metadata = extractMetadata(fs.readFileSync(file, "utf8")).metadata; - if (!metadata.id) { - return; - } - const data = {}; - data["category"] = metadata.category; - data["sidebar"] = metadata.layout; - if (metadata.next) { - data["next"] = metadata.next; - } - if (metadata.previous) { - data["previous"] = metadata.previous; - } - docs[metadata.id] = data; - } -}); - -Object.keys(docs).forEach(id => { - if (!docs[id].previous) { - sidebar[docs[id].sidebar] = {}; - sidebar[docs[id].sidebar][docs[id].category] = []; - sidebar[docs[id].sidebar][docs[id].category].push(id); - } -}); - -Object.keys(sidebar).forEach(sb => { - const categories = sidebar[sb]; - Object.keys(categories).forEach(category => { - const docIds = categories[category]; - next = docIds[0]; - while (next) { - id = next; - next = docs[id].next; - if (!next) { - return; - } - if (docs[next].category === category) { - docIds.push(next); - } else { - categories[docs[next].category] = []; - categories[docs[next].category].push(next); - } - } - }); -}); - -const str = prettier.format("module.exports = " + JSON.stringify(sidebar)); -fs.writeFileSync(process.cwd() + "/docSidebar.js", str, "utf8"); diff --git a/lib/publish-gh-pages.js b/lib/publish-gh-pages.js index 87c66d34b3..bd4604350c 100644 --- a/lib/publish-gh-pages.js +++ b/lib/publish-gh-pages.js @@ -33,8 +33,7 @@ if (shell.exec("docusaurus-build").code) { shell.exit(1); } -shell.cd(__dirname); -shell.cd(".."); +shell.cd(process.cwd()); shell.cd("build"); if ( diff --git a/lib/server/generate.js b/lib/server/generate.js index 6d78c0b0d3..aa8cd01b12 100644 --- a/lib/server/generate.js +++ b/lib/server/generate.js @@ -70,7 +70,7 @@ function execute() { console.log("generate.js triggered..."); - const regexSubFolder = /docs\/(.*)\/.*/; + const regexSubFolder = /translated_docs\/(.*)\/.*/; const enabledLanguages = []; languages.filter(lang => lang.enabled).map(lang => { @@ -82,27 +82,21 @@ function execute() { let mdToHtml = {}; for (let i = 0; i < Metadata.length; i++) { const metadata = Metadata[i]; - mdToHtml["/docs/" + metadata.language + "/" + metadata.source] = - "/" + siteConfig.projectName + "/" + metadata.permalink; + if (metadata.language !== "en") { + continue; + } + mdToHtml[metadata.source] = siteConfig.baseUrl + metadata.permalink; } const DocsLayout = require("../core/DocsLayout.js"); - fs.removeSync(__dirname + "/../../build"); + fs.removeSync(CWD + "/build"); - // create html files for all docs + // create html files for all English docs let files = glob.sync(CWD + "/../docs/**"); files.forEach(file => { // console.log(file); let language = "en"; - const match = regexSubFolder.exec(file); - if (match) { - language = match[1]; - } - - if (enabledLanguages.indexOf(language) === -1) { - return; - } const extension = path.extname(file); @@ -120,6 +114,61 @@ function execute() { rawContent = insertTableOfContents(rawContent); } + /* replace any links to markdown files to their website html links */ + Object.keys(mdToHtml).forEach(function(key, index) { + rawContent = rawContent.replace( + new RegExp(key, "g"), + mdToHtml[key].replace("/en/", "/" + language + "/") + ); + }); + + const docComp = ( + + {rawContent} + + ); + const str = renderToStaticMarkup(docComp); + + let targetFile = + CWD + "/build/" + siteConfig.projectName + "/" + metadata.permalink; + // console.log(targetFile); + writeFileAndCreateFolder(targetFile, str); + } + }); + + // create html files for all non-English docs + if (languages.length > 1) { + files = glob.sync(CWD + "/translated_docs/**"); + files.forEach(file => { + let language = "en"; + + const match = regexSubFolder.exec(file); + if (match) { + language = match[1]; + } + + if (enabledLanguages.indexOf(language) === -1) { + return; + } + + const extension = path.extname(file); + if (extension !== ".md" && extension !== ".markdown") { + return; + } + + const result = readMetadata.processMetadata(file); + if (!result) { + return; + } + + const metadata = result.metadata; + let rawContent = result.rawContent; + + /* generate table of contents if appropriate */ + if (rawContent && rawContent.indexOf(TABLE_OF_CONTENTS_TOKEN) != -1) { + rawContent = insertTableOfContents(rawContent); + } + /* replace any links to markdown files to their website html links */ Object.keys(mdToHtml).forEach(function(key, index) { rawContent = rawContent.replace(new RegExp(key, "g"), mdToHtml[key]); @@ -131,18 +180,20 @@ function execute() { ); const str = renderToStaticMarkup(docComp); - let targetFile = - __dirname + - "/../../build" + - "/" + - siteConfig.projectName + - "/" + - metadata.permalink; + CWD + "/build/" + siteConfig.projectName + "/" + metadata.permalink; // console.log(targetFile); writeFileAndCreateFolder(targetFile, str); - } - }); + }); + } + + /* copy docs assets if they exist */ + if (fs.existsSync(CWD + "/../docs/assets")) { + fs.copySync( + CWD + "/../docs/assets", + CWD + "/build/" + siteConfig.projectName + "/docs/assets" + ); + } // create html files for all blog posts if (fs.existsSync(__dirname + "../core/MetadataBlog.js")) { @@ -152,8 +203,13 @@ function execute() { const MetadataBlog = require("../core/MetadataBlog.js"); const BlogPostLayout = require("../core/BlogPostLayout.js"); - files = glob.sync(CWD + "/../blog/**/*.*"); + files = glob.sync(CWD + "/blog/**/*.*"); files.sort().reverse().forEach(file => { + const extension = path.extname(file); + if (extension !== ".md" && extension !== ".markdown") { + return; + } + /* convert filename ot use slashes */ const filePath = path .basename(file) @@ -185,13 +241,7 @@ function execute() { const str = renderToStaticMarkup(blogPostComp); let targetFile = - __dirname + - "/../../build" + - "/" + - siteConfig.projectName + - "/" + - "blog/" + - filePath; + CWD + "/build/" + siteConfig.projectName + "/blog/" + filePath; writeFileAndCreateFolder(targetFile, str); }); // create html files for all blog pages @@ -210,25 +260,32 @@ function execute() { const str = renderToStaticMarkup(blogPageComp); let targetFile = - __dirname + - "/../../build" + - "/" + + CWD + + "/build/" + siteConfig.projectName + - "/" + - "blog" + + "/blog" + (page > 0 ? "/page" + (page + 1) : "") + "/index.html"; writeFileAndCreateFolder(targetFile, str); } + /* copy blog assets if they exist */ + if (fs.existsSync(CWD + "/blog/assets")) { + fs.copySync( + CWD + "/blog/assets", + CWD + "/build/" + siteConfig.projectName + "/blog/assets" + ); + } + /* copy all static files from docusaurus */ files = glob.sync(__dirname + "/../static/**"); files.forEach(file => { - let targetFile = file.replace( - "/lib/static/", - "/build" + "/" + siteConfig.projectName + "/" - ); - + let targetFile = + CWD + + "/build/" + + siteConfig.projectName + + "/" + + file.split("/static/")[1]; if (file.match(/\.css$/)) { let cssContent = fs.readFileSync(file); cssContent = cssContent @@ -259,12 +316,7 @@ function execute() { files.forEach(file => { if (file.match(/\.css$/) && !isSeparateCss(file)) { const mainCss = - __dirname + - "/../../build" + - "/" + - siteConfig.projectName + - "/" + - "css/main.css"; + CWD + "/build/" + siteConfig.projectName + "/css/main.css"; let cssContent = fs.readFileSync(file); cssContent = fs.readFileSync(mainCss) + "\n" + cssContent; @@ -287,12 +339,7 @@ function execute() { } else if (!fs.lstatSync(file).isDirectory()) { let parts = file.split("static"); let targetFile = - __dirname + - "/../../build" + - "/" + - siteConfig.projectName + - "/" + - parts[1]; + CWD + "/build/" + siteConfig.projectName + "/" + parts[1]; mkdirp.sync(targetFile.replace(new RegExp("/[^/]*$"), "")); fs.copySync(file, targetFile); } @@ -315,7 +362,7 @@ function execute() { const ReactComp = require(tempFile); let targetFile = - __dirname + "/../../build/" + siteConfig.projectName + "/" + parts[1]; + CWD + "/build/" + siteConfig.projectName + "/" + parts[1]; targetFile = targetFile.replace(/\.js$/, ".html"); const regexLang = /\/pages\/(.*)\//; @@ -364,21 +411,14 @@ function execute() { } else if (!fs.lstatSync(file).isDirectory()) { let parts = file.split("pages"); let targetFile = - __dirname + - "/../../build" + - "/" + - siteConfig.projectName + - "/" + - parts[1]; + CWD + "/build/" + siteConfig.projectName + "/" + parts[1]; mkdirp.sync(targetFile.replace(new RegExp("/[^/]*$"), "")); fs.copySync(file, targetFile); } }); /* copy html files in 'en' to base level as well */ - files = glob.sync( - __dirname + "/../../build" + "/" + siteConfig.projectName + "/" + "en/**" - ); + files = glob.sync(CWD + "/build/" + siteConfig.projectName + "/en/**"); files.forEach(file => { let targetFile = file.replace("en/", ""); if (file.match(/\.html$/)) { diff --git a/lib/server/readMetadata.js b/lib/server/readMetadata.js index 9398f40609..dc8584428e 100644 --- a/lib/server/readMetadata.js +++ b/lib/server/readMetadata.js @@ -12,8 +12,9 @@ const CWD = process.cwd(); const path = require("path"); const fs = require("fs"); const os = require("os"); -const sidebar = require(CWD + "/docSidebar.js"); +const sidebar = require(CWD + "/sidebar.json"); const glob = require("glob"); +const siteConfig = require(CWD + "/siteConfig.js"); let languages; if (fs.existsSync(CWD + "/languages.js")) { languages = require(CWD + "/languages.js"); @@ -108,11 +109,12 @@ function processMetadata(file) { const rawContent = result.rawContent; metadata.source = path.basename(file); - // in permalink replace /en/ language with localized folder - metadata.permalink = metadata.permalink.replace( - /\/en\//g, - "/" + language + "/" - ); + if (languages.length === 1 && !siteConfig.useEnglishUrl) { + metadata.permalink = "docs/" + metadata.id + ".html"; + } else { + metadata.permalink = "docs/" + language + "/" + metadata.id + ".html"; + } + // change ids previous, next metadata.localized_id = metadata.id; metadata.id = language + "-" + metadata.id; @@ -139,7 +141,7 @@ function processMetadata(file) { function generateDocsMetadata() { const order = readSidebar(sidebar); - const regexSubFolder = /docs\/(.*)\/.*/; + const regexSubFolder = /translated_docs\/(.*)\/.*/; const enabledLanguages = []; languages.filter(lang => lang.enabled).map(lang => { @@ -148,7 +150,25 @@ function generateDocsMetadata() { const metadatas = []; - const files = glob.sync(CWD + "/../docs/**"); + /* metadata for english files */ + let files = glob.sync(CWD + "/../docs/**"); + files.forEach(file => { + let language = "en"; + + const extension = path.extname(file); + + if (extension === ".md" || extension === ".markdown") { + const res = processMetadata(file); + if (!res) { + return; + } + let metadata = res.metadata; + metadatas.push(metadata); + } + }); + + /* metadata for non-english docs */ + files = glob.sync(CWD + "/translated_docs/**"); files.forEach(file => { let language = "en"; const match = regexSubFolder.exec(file); @@ -186,8 +206,12 @@ function generateDocsMetadata() { function generateBlogMetadata() { const metadatas = []; - let files = glob.sync(CWD + "/../blog/**/*.*"); + let files = glob.sync(CWD + "/blog/**/*.*"); files.sort().reverse().forEach(file => { + const extension = path.extname(file); + if (extension !== ".md" && extension !== ".markdown") { + return; + } // Transform // 2015-08-13-blog-post-name-0.5.md // into @@ -197,8 +221,6 @@ function generateBlogMetadata() { .replace("-", "/") .replace("-", "/") .replace("-", "/") - // react-middleware is broken with files that contains multiple . - // like react-0.14.js .replace(/\./g, "-") .replace(/\-md$/, ".html"); const result = extractMetadata(fs.readFileSync(file, { encoding: "utf8" })); diff --git a/lib/server/server.js b/lib/server/server.js index f5297fbbb9..3f857ac18c 100644 --- a/lib/server/server.js +++ b/lib/server/server.js @@ -22,6 +22,7 @@ function execute(port) { const glob = require("glob"); const translate = require("./translate.js"); let siteConfig = require(CWD + "/siteConfig.js"); + const ENABLE_TRANSLATION = fs.existsSync(CWD + "/languages.js"); /** * Removes a module from the cache @@ -78,7 +79,6 @@ function execute(port) { readMetadata.generateDocsMetadata(); purgeCache("../core/metadata.js"); Metadata = require("../core/metadata.js"); - } /****************************************************************************/ @@ -121,7 +121,7 @@ function execute(port) { reloadMetadata(); /* handle all requests for document pages */ - const app = express().get(/docs\/[\s\S]*html$/, (req, res, next) => { + const app = express().get(/docs\/.*html$/, (req, res, next) => { purgeCache(CWD + "/siteConfig.js"); siteConfig = require(CWD + "/siteConfig.js"); @@ -131,23 +131,29 @@ function execute(port) { let links = {}; for (let i = 0; i < Metadata.length; i++) { const metadata = Metadata[i]; - links[metadata.permalink] = - "docs/" + metadata.language + "/" + metadata.source; + if (metadata.language === "en") { + links[metadata.permalink] = CWD + "/../docs/" + metadata.source; + } else { + links[metadata.permalink] = + CWD + "/translated_docs/" + metadata.language + "/" + metadata.source; + } } let mdToHtml = {}; for (let i = 0; i < Metadata.length; i++) { const metadata = Metadata[i]; - mdToHtml["/docs/" + metadata.language + "/" + metadata.source] = - siteConfig.baseUrl + metadata.permalink; + if (metadata.language !== "en") { + continue; + } + mdToHtml[metadata.source] = siteConfig.baseUrl + metadata.permalink; } + console.log(mdToHtml); let file = links[req.path.toString().replace(siteConfig.baseUrl, "")]; - file = CWD + "/../" + file; + console.log(file); if (!fs.existsSync(file)) { next(); return; } - console.log(file); const result = readMetadata.processMetadata(file); const metadata = result.metadata; @@ -161,9 +167,17 @@ function execute(port) { /* replace any links to markdown files to their website html links */ Object.keys(mdToHtml).forEach(function(key, index) { - rawContent = rawContent.replace(new RegExp(key, "g"), mdToHtml[key]); + rawContent = rawContent.replace( + new RegExp(key, "g"), + mdToHtml[key].replace("/en/", "/" + language + "/") + ); }); + rawContent = rawContent.replace( + /\]\(assets\//g, + "](" + siteConfig.baseUrl + "docs/assets/" + ); + purgeCache("../core/DocsLayout.js"); const DocsLayout = require("../core/DocsLayout.js"); const docComp = ( @@ -175,7 +189,9 @@ function execute(port) { res.send(renderToStaticMarkup(docComp)); }); /* handle all requests for blog pages and posts */ - app.get(/blog\/[\s\S]*html$/, (req, res) => { + app.get(/blog\/.*html$/, (req, res) => { + console.log(req.path); + purgeCache(CWD + "/siteConfig.js"); siteConfig = require(CWD + "/siteConfig.js"); @@ -229,12 +245,16 @@ function execute(port) { let file = parts[1]; file = file.replace(/\.html$/, ".md"); file = file.replace(new RegExp("/", "g"), "-"); - file = CWD + "/../blog/" + file; + file = CWD + "/blog/" + file; const result = readMetadata.extractMetadata( fs.readFileSync(file, { encoding: "utf8" }) ); - const rawContent = result.rawContent; + let rawContent = result.rawContent; + rawContent = rawContent.replace( + /\]\(assets\//g, + "](" + siteConfig.baseUrl + "blog/assets/" + ); const metadata = Object.assign( { path: req.path.toString().split("blog/")[1], content: rawContent }, result.metadata @@ -385,6 +405,14 @@ function execute(port) { }); /* serve static content first from user folder then from docusaurus */ + app.use( + siteConfig.baseUrl + "docs/assets/", + express.static(CWD + "/../docs/assets") + ); + app.use( + siteConfig.baseUrl + "blog/assets/", + express.static(CWD + "/blog/assets") + ); app.use(siteConfig.baseUrl, express.static(CWD + "/static")); app.use(siteConfig.baseUrl, express.static(__dirname + "/../static")); diff --git a/lib/write-translations.js b/lib/write-translations.js index 610850e557..24c46f1514 100644 --- a/lib/write-translations.js +++ b/lib/write-translations.js @@ -20,6 +20,7 @@ const path = require("path"); const siteConfig = require(CWD + "/siteConfig.js"); const babylon = require("babylon"); const traverse = require("babel-traverse").default; +const sidebar = require(CWD + "/sidebar.json"); function writeFileAndCreateFolder(file, content) { mkdirp.sync(file.replace(new RegExp("/[^/]*$"), "")); @@ -37,18 +38,17 @@ function execute() { }; /* look through front matter of docs for titles and categories to translate */ - let files = glob.sync(CWD + "/../docs/en/**"); + let files = glob.sync(CWD + "/../docs/**"); files.forEach(file => { const extension = path.extname(file); if (extension === ".md" || extension === ".markdown") { const res = readMetadata.processMetadata(file); if (!res) { - return + return; } const metadata = res.metadata; translations["localized-strings"][metadata.localized_id] = metadata.title; - translations["localized-strings"][metadata.category] = metadata.category; if (metadata.sidebar_title) { translations["localized-strings"][metadata.sidebar_title] = @@ -66,6 +66,14 @@ function execute() { siteConfig.headerLinksExternal[i].text; } + /* find sidebar category titles to translate */ + Object.keys(sidebar).forEach(sb => { + const categories = sidebar[sb]; + Object.keys(categories).forEach(category => { + translations["localized-strings"][category] = category; + }); + }); + /* go through pages to look for text inside translate tags */ files = glob.sync(CWD + "/pages/en/**"); files.forEach(file => { @@ -96,7 +104,10 @@ function execute() { }); } }); - writeFileAndCreateFolder(CWD + "/i18n/en.json", JSON.stringify(translations)); + writeFileAndCreateFolder( + CWD + "/i18n/en.json", + JSON.stringify(translations, null, 2) + ); } execute(); diff --git a/package.json b/package.json index ae771ccdfc..8db15774f5 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "docusaurus-build": "./lib/build-files.js", "docusaurus-publish": "./lib/publish-gh-pages.js", "docusaurus-examples": "./lib/copy-examples.js", - "docusaurus-write-translations": "./lib/write-translations.js", - "docusaurus-gen-doc-sidebar": "./lib/gen-doc-sidebar.js" + "docusaurus-write-translations": "./lib/write-translations.js" } }