Skip to content

Commit

Permalink
refactor: refactor code tab split (#1369)
Browse files Browse the repository at this point in the history
* refactor: refactor code tab split

* Add split tab unit test

* Fix code tab list bug
  • Loading branch information
zachbadgett authored and yangshun committed May 2, 2019
1 parent 5030952 commit 0813920
Show file tree
Hide file tree
Showing 9 changed files with 671 additions and 43 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ website/
scripts
packages/docusaurus-1.x/lib/core/metadata.js
packages/docusaurus-1.x/lib/core/MetadataBlog.js
packages/docusaurus-1.x/lib/core/__tests__/split-tab.test.js
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"devDependencies": {
"babel-core": "^7.0.0-0",
"babel-eslint": "8",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"eslint": "4.x",
"eslint-config-airbnb": "17.1.0",
"eslint-config-prettier": "^2.9.0",
Expand Down
179 changes: 145 additions & 34 deletions packages/docusaurus-1.x/lib/core/Doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,120 @@ const translateThisDoc = translate(
'Translate this Doc|recruitment message asking to translate the docs',
);

const splitTabsToTitleAndContent = content => {
const titles = content.match(/<!--(.*?)-->/gms);
const tabs = content.split(/<!--.*?-->/gms);
if (!titles || !tabs || !titles.length || !tabs.length) {
return [];
const splitTabsToTitleAndContent = (lines, indents) => {
let first = false;
let inBlock = false;
let whitespace = false;
const tc = [];
let current = {
content: [],
};
lines.forEach(line => {
if (indents) {
line = line.replace(new RegExp(`^((\\t|\\s{4}){${indents}})`, 'g'), '');
}
let pos = 0;
const end = line.length;
const isToken = (cline, cpos, ...chars) => {
for (let i = 0; i < chars.length; i++) {
if (cline.charCodeAt(cpos) !== chars[i]) {
return false;
}
cpos++;
}
return true;
};
while (pos + 1 < end) {
// Skip all the whitespace when we first start the scan.
for (let max = end; pos < max; pos++) {
if (line.charCodeAt(pos) !== 0x20 && line.charCodeAt(pos) !== 0x0a) {
break;
}
whitespace = true;
}
// Check for the start of a comment: <!--
// If we're in a code block we skip it.
if (
isToken(
line,
pos,
0x3c /* < */,
0x21 /* ! */,
0x2d /* - */,
0x2d /* - */,
) &&
!inBlock
) {
if (current !== null && current.title !== undefined) {
tc.push({
title: current.title,
content: current.content.join('\n'),
});
current = {
content: [],
};
}
first = true;
pos += 4;
let b0;
let b1;
const buf = [];
// Add all characters to the title buffer until
// we reach the end marker: -->
for (let max = end; pos < max; pos++) {
const b = line.charCodeAt(pos);
if (b0 === 0x2d /* - */ && b1 === 0x2d /* - */) {
if (b !== 0x3e /* > */) {
throw new Error(`Invalid comment sequence "--"`);
}
break;
}
buf.push(b);
b0 = b1;
b1 = b;
}
// Clear the line out before we add it to content.
// This also means tabs can only be defined on a line by itself.
line = '\n';
// Trim the last 2 characters: --
current.title = String.fromCharCode(...buf)
.substring(0, buf.length - 2)
.trim();
}
// If the first thing in a code tab is not a title it's invalid.
if (!first) {
throw new Error(`Invalid code tab markdown`);
}
// Check for code block: ```
// If the line begins with whitespace we don't consider it a code block.
if (
isToken(line, pos, 0x60 /* ` */, 0x60 /* ` */, 0x60 /* ` */) &&
!whitespace
) {
pos += 3;
inBlock = !inBlock;
}
pos++;
whitespace = false;
}
current.content.push(line);
});
if (current !== null && current.title !== undefined) {
tc.push({
title: current.title,
content: current.content.join('\n'),
});
}
tabs.shift();
return titles.map((title, idx) => ({
title: title.substring(4, title.length - 3).trim(),
content: tabs[idx],
}));
return tc;
};

const cleanTheCodeTag = content => {
const cleanTheCodeTag = (content, indents) => {
const prepend = (line, indent) => {
if (indent) {
return ' '.repeat(indent) + line;
}
return line;
};
const contents = content.split(/(<pre>)(.*?)(<\/pre>)/gms);
let inCodeBlock = false;
const cleanContents = contents.map(c => {
Expand All @@ -47,7 +147,7 @@ const cleanTheCodeTag = content => {
if (inCodeBlock) {
return c.replace(/\n/g, '<br />');
}
return c;
return prepend(c, indents);
});
return cleanContents.join('');
};
Expand All @@ -56,32 +156,43 @@ const cleanTheCodeTag = content => {
class Doc extends React.Component {
renderContent() {
const {content} = this.props;
let inCodeTabs = false;
const contents = content.split(
/(<!--DOCUSAURUS_CODE_TABS-->\n)(.*?)(\n<!--END_DOCUSAURUS_CODE_TABS-->)/gms,
);

const renderResult = contents.map(c => {
if (c === '<!--DOCUSAURUS_CODE_TABS-->\n') {
inCodeTabs = true;
return '';
}
if (c === '\n<!--END_DOCUSAURUS_CODE_TABS-->') {
inCodeTabs = false;
return '';
}
if (inCodeTabs) {
let indents = 0;
return content.replace(
/(\t|\s{4})*?(<!--DOCUSAURUS_CODE_TABS-->\n)(.*?)((\n|\t|\s{4})<!--END_DOCUSAURUS_CODE_TABS-->)/gms,
m => {
const contents = m.split('\n').filter(c => {
if (!indents) {
indents = (
c.match(/((\t|\s{4})+)<!--DOCUSAURUS_CODE_TABS-->/) || []
).length;
}
if (c.match(/(\t|\s{4})+<!--DOCUSAURUS_CODE_TABS-->/)) {
return false;
}
if (
c.match(
/<!--END_DOCUSAURUS_CODE_TABS-->|<!--DOCUSAURUS_CODE_TABS-->/,
) ||
(indents > 0 &&
c.match(
/(\t|\s{4})+(<!--END_DOCUSAURUS_CODE_TABS-->|<!--DOCUSAURUS_CODE_TABS-->)/,
))
) {
return false;
}
return true;
});
if (indents) {
indents -= 1;
}
const codeTabsMarkdownBlock = renderToStaticMarkup(
<CodeTabsMarkdownBlock>
{splitTabsToTitleAndContent(c)}
{splitTabsToTitleAndContent(contents, indents)}
</CodeTabsMarkdownBlock>,
);
return cleanTheCodeTag(codeTabsMarkdownBlock);
}
return c;
});

return renderResult.join('');
return cleanTheCodeTag(codeTabsMarkdownBlock, indents);
},
);
}

render() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!--DOCUSAURUS_CODE_TABS-->
<!--JavaScript-->
```js
console.log('Hello, world!');
```
<!--Python-->
```py
print('Hello, world!')
```

<!--C-->
```C
#include <stdio.h>

int main() {
printf("Hello World!");
return 0;
}
```

<!--Pascal-->
```Pascal
program HelloWorld;
begin
WriteLn('Hello, world!');
end.
```

<!--END_DOCUSAURUS_CODE_TABS-->
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
1. Doc
* Hello
<!--DOCUSAURUS_CODE_TABS-->
<!--JavaScript-->
```js
console.log('Hello, world!');
```
<!--Python-->
```py
print('Hello, world!')
```

<!--C-->
```C
#include <stdio.h>
int main() {
printf("Hello World!");
return 0;
}
```

<!--Pascal-->
```Pascal
program HelloWorld;
begin
WriteLn('Hello, world!');
end.
```

<!--END_DOCUSAURUS_CODE_TABS-->
1. Do that
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"_comment": "This file is auto-generated by write-translations.js",
"localized-strings": {
},
"pages-strings": {
"Help Translate|recruit community translators for your project": "Help Us Translate",
"Edit this Doc|recruitment message asking to edit the doc source": "Edit",
"Translate this Doc|recruitment message asking to translate the docs": "Translate"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/* List of projects/orgs using your project for the users page */

const siteConfig = {
title: 'Docusaurus',
tagline: 'Easy to Maintain Open Source Documentation Websites',
url: 'https://docusaurus.io',
baseUrl: '/',
organizationName: 'facebook',
projectName: 'Docusaurus',
cname: 'docusaurus.io',
noIndex: false,
editUrl: 'https://github.com/facebook/docusaurus/edit/master/docs/',
headerLinks: [],
headerIcon: 'img/docusaurus.svg',
footerIcon: 'img/docusaurus_monochrome.svg',
favicon: 'img/docusaurus.ico',
algolia: {
apiKey: '3eb9507824b8be89e7a199ecaa1a9d2c',
indexName: 'docusaurus',
algoliaOptions: {
facetFilters: ['language:LANGUAGE', 'version:VERSION'],
},
},
colors: {
primaryColor: '#2E8555',
secondaryColor: '#205C3B',
},
translationRecruitingLink: 'https://crowdin.com/project/docusaurus',
copyright: `Copyright © ${new Date().getFullYear()} Facebook Inc.`,
usePrism: ['jsx'],
highlight: {
theme: 'atom-one-dark',
},
scripts: [
'https://buttons.github.io/buttons.js',
'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js',
'/js/code-blocks-buttons.js',
],
gaTrackingId: 'UA-44373548-31',
facebookAppId: '199138890728411',
facebookComments: true,
twitter: 'true',
twitterUsername: 'docusaurus',
ogImage: 'img/docusaurus.png',
twitterImage: 'img/docusaurus.png',
onPageNav: 'separate',
cleanUrl: true,
scrollToTop: true,
scrollToTopOptions: {
zIndex: 100,
},
enableUpdateTime: true,
enableUpdateBy: true,
docsSideNavCollapsible: true,
};

module.exports = siteConfig;
Loading

0 comments on commit 0813920

Please sign in to comment.