diff --git a/docs/api-doc-markdown.md b/docs/api-doc-markdown.md
index a37e19d2d4..55ff232821 100644
--- a/docs/api-doc-markdown.md
+++ b/docs/api-doc-markdown.md
@@ -17,7 +17,7 @@ Documents use the following markdown header fields that are enclosed by a line `
For example:
-```markup
+```
---
id: doc1
title: My Document
@@ -29,7 +29,7 @@ Versioned documents have their ids altered to include the version number when th
For example:
-```markup
+```
---
id: version-1.0.0-doc1
title: My Document
@@ -52,7 +52,7 @@ Blog Posts use the following markdown header fields that are enclosed by a line
For example:
-```markup
+```
---
title: My First Blog Post
author: Frank Li
@@ -91,9 +91,10 @@ Example:
You can make an autogenerated list of links, which can be useful as a table of contents for API docs.
-In your markdown file, insert a line with the text <`AUTOGENERATED_TABLE_OF_CONTENTS>`. Write your documentation using `h3` headers for each function inside a code block. These will be found by Docusaurus and a list of links to these sections will inserted at the text <`AUTOGENERATED_TABLE_OF_CONTENTS>`.
+In your markdown file, insert a line with the text <`AUTOGENERATED_TABLE_OF_CONTENTS`>. Write your documentation using `h3` headers for each function inside a code block. These will be found by Docusaurus and a list of links to these sections will inserted at the text <`AUTOGENERATED_TABLE_OF_CONTENTS`>.
Example:
+
```markdown
### `docusaurus.function(a, b)`
@@ -111,4 +112,50 @@ will lead to a table of contents of the functions:
- `docusaurus.function(a, b)`
- `docdoc(file)`
```
+
and each function will link to their corresponding sections in the page.
+
+## Syntax Highlighting
+
+Syntax highlighting is enabled by default on fenced code blocks. The language should be detected automatically, but you can sometimes get better results by specifying the language. You can do so using an [info string](https://github.github.com/gfm/#example-111), following the three opening backticks. The following JavaScript example...
+
+ ```javascript
+ ReactDOM.render(
+
Hello, world! ,
+ document.getElementById('root')
+ );
+ ```
+
+...would be rendered with syntax highlighting like so:
+
+```javascript
+ReactDOM.render(
+ Hello, world! ,
+ document.getElementById('root')
+);
+```
+
+Highlighting is provided by [Highlight.js](https://highlightjs.org) using the theme specified in your `siteConfig.js` file as part of the `highlight` key:
+
+```
+highlight: {
+ theme: 'default'
+}
+```
+
+You can find the full list of supported themes in the Highlight.js [`styles`](https://github.com/isagalaev/highlight.js/tree/master/src/styles) directory.
+
+### Registering additional languages
+
+While Highlight.js provides support for [many popular languages out of the box](https://highlightjs.org/static/demo/), you may find the need to register additional language support. For these cases, we provide an escape valve by exposing the `hljs` constant as part of the `highlight` config key. This in turn allows you to call [`registerLanguage`](http://highlightjs.readthedocs.io/en/latest/api.html#registerlanguage-name-language):
+
+```
+highlight: {
+ theme: 'default',
+ hljs: function(hljs) {
+ hljs.registerLanguage('galacticbasic', function(hljs) {
+ // ...
+ });
+ }
+}
+```
diff --git a/docs/api-pages.md b/docs/api-pages.md
index 19678df974..9f9b26332d 100644
--- a/docs/api-pages.md
+++ b/docs/api-pages.md
@@ -127,7 +127,7 @@ Static assets should be placed into the `website/static` folder. They can be acc
## Styles
-You should configure your site's primary, secondary, and Prism colors using the `colors` field in `siteConfig` as specified [here](site-config.md). You can also configure other colors in the same way as described in the `siteConfig` doc.
+You should configure your site's primary, secondary, and code block colors using the `colors` field in `siteConfig` as specified [here](api-site-config.md). You can also configure other colors in the same way as described in the `siteConfig` doc.
You can provide your own custom styles by adding them anywhere in the `website/static` folder. Any `.css` files you provide in the `static` folder will get concatenated to the end of Docusaurus's provided styles, allowing you to add to or override Docusaurus default styles as you wish.
diff --git a/docs/api-site-config.md b/docs/api-site-config.md
index deac13c5d3..5641fb81d3 100644
--- a/docs/api-site-config.md
+++ b/docs/api-site-config.md
@@ -56,7 +56,6 @@ headerLinks: [
- `primaryColor` is the color used the header navigation bar and sidebars.
- `secondaryColor` is the color seen in the second row of the header navigation bar when the site window is narrow (including on mobile).
- - `prismColor` is the color used in the background of syntax highlighting for code in documentation. It is recommended to be the same color as `primaryColor` in `rgba` form with an alpha value of `0.03`. Other fields can be added
- Custom color configurations can also be added. For example, if user styles are added with colors specified as `$myColor`, then adding a `myColor` field to `colors` will allow you to easily configure this color.
`copyright` - The copyright string at footer of site and within feed
@@ -81,9 +80,18 @@ headerLinks: [
`gaTrackingId` - Google Analytics tracking ID to track page views.
-
`sourceCodeButton` - the type of button to use for pointing to your source code. If this field is non-null, the site will pull in the appropriate button code in the header, for you to be able to render as you see fit. Currently accepted values: `"github"`, `"none"`. Defaults to `"github"`.
+`highlight` - [Syntax highlighting](api-doc-markdown.md) options:
+
+ - `theme` is the name of the theme used by Highlight.js when highlighting code.
+ - `version` specifies a particular version of Highlight.js to be used.
+ - `hljs` provides an escape valve by passing an instance of Highlight.js to the function specified here, allowing additional languages to be registered for syntax highlighting.
+
+`markdownPlugins` - An array of plugins to be loaded by Remarkable, the markdown parser and renderer used by Docusaurus. The plugin will receive a reference to the Remarkable instance, allowing custom parsing and rendering rules to be defined.
+
+`scripts` - Array of JavaScript sources to load. The script tag will be inserted in the HTML head.
+
Users can also add their own custom fields if they wish to provide some data across different files.
## Example siteConfig.js with all fields
@@ -118,12 +126,8 @@ const siteConfig = {
favicon: "img/favicon.png",
colors: {
primaryColor: "#2E8555",
- secondaryColor: "#205C3B",
- prismColor:
- "rgba(46, 133, 85, 0.03)"
+ secondaryColor: "#205C3B"
},
-
-
editUrl: "https://github.com/deltice/test-site/edit/master/docs/",
users,
disableHeaderTitle: true,
@@ -138,9 +142,20 @@ const siteConfig = {
indexName: "github"
},
gaTrackingId: "U-A2352",
- sourceCodeButton: "github"
+ sourceCodeButton: "github",
+ highlight: {
+ theme: 'default'
+ },
+ markdownPlugins: [
+ function foo(md) {
+ md.renderer.rules.fence_custom.foo = function(tokens, idx, options, env, instance) {
+ return 'bar
';
+ }
+ }
+ ],
+ scripts: [ "https://docusaurus.io/slash.js" ]
+
};
module.exports = siteConfig;
-
```
diff --git a/examples/basics/siteConfig.js b/examples/basics/siteConfig.js
index 72cd71f2f8..b0111fda30 100644
--- a/examples/basics/siteConfig.js
+++ b/examples/basics/siteConfig.js
@@ -35,15 +35,17 @@ const siteConfig = {
/* colors for website */
colors: {
primaryColor: "#2E8555",
- secondaryColor: "#205C3B",
- prismColor:
- "rgba(46, 133, 85, 0.03)" /* primaryColor in rgba form, with 0.03 alpha */
+ secondaryColor: "#205C3B"
},
// This copyright info is used in /core/Footer.js and blog rss/atom feeds.
copyright:
"Copyright © " +
new Date().getFullYear() +
- " Your Name or Your Company Name"
+ " Your Name or Your Company Name",
+ highlight: {
+ // Highlight.js theme to use for syntax highlighting in code blocks
+ theme: "default"
+ }
};
module.exports = siteConfig;
diff --git a/lib/core/CompLibrary.js b/lib/core/CompLibrary.js
index 8d7fa9dcc9..d49152b01c 100644
--- a/lib/core/CompLibrary.js
+++ b/lib/core/CompLibrary.js
@@ -8,12 +8,10 @@
const Marked = require("./Marked.js");
const Container = require("./Container.js");
const GridBlock = require("./GridBlock.js");
-const Prism = require("./Prism.js");
// collection of other components to provide to users
module.exports = {
Marked: Marked,
Container: Container,
- GridBlock: GridBlock,
- Prism: Prism
+ GridBlock: GridBlock
};
diff --git a/lib/core/Head.js b/lib/core/Head.js
index 16251f3795..c912faacb0 100644
--- a/lib/core/Head.js
+++ b/lib/core/Head.js
@@ -10,15 +10,24 @@ const React = require("react");
// html head for each page
class Head extends React.Component {
render() {
- let links = this.props.config.headerLinks;
+ const links = this.props.config.headerLinks;
let hasBlog = false;
links.map(link => {
if (link.blog) hasBlog = true;
});
- let sourceCodeButton = this.props.config.sourceCodeButton;
- // defaults to github, but other values may be allowed in the future
- let includeGithubButton =
+ const sourceCodeButton = this.props.config.sourceCodeButton;
+ // defaults to GitHub, but other values may be allowed in the future
+ const includeGitHubButton =
sourceCodeButton === "github" || sourceCodeButton == null;
+
+ const highlightDefaultVersion = '9.12.0';
+ const highlightConfig = this.props.config.highlight
+ || { version: highlightDefaultVersion, theme: 'default' };
+ const highlightVersion = highlightConfig.version || highlightDefaultVersion;
+ const highlightTheme = highlightConfig.theme || 'default';
+
+ const hasCustomScripts = this.props.config.scripts;
+
return (
@@ -64,7 +73,7 @@ class Head extends React.Component {
href={this.props.config.url + "/blog/atom.xml"}
title={this.props.config.title + " Blog ATOM Feed"}
/>
- )}{" "}
+ )}
{hasBlog && (
)}
- {includeGithubButton && (
+ {includeGitHubButton && (
)}
-
-
+ {hasCustomScripts && this.props.config.scripts.map(function(source) {
+ return (
+
+ );
+ })}
);
}
diff --git a/lib/core/Marked.js b/lib/core/Marked.js
index e60247cdf5..2b7110d069 100644
--- a/lib/core/Marked.js
+++ b/lib/core/Marked.js
@@ -7,1117 +7,13 @@
/* Marked component is used to parse markdown to html */
-const React = require("react");
-import DOM from 'react-dom-factories';
-const Prism = require("./Prism");
-const Header = require("./Header");
-const WebPlayer = require('./WebPlayer');
-const SnackPlayer = require('./SnackPlayer');
-
-/**
- * Block-Level Grammar
- */
-
-const block = {
- newline: /^\n+/,
- code: /^( {4}[^\n]+\n*)+/,
- fences: noop,
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
- nptable: noop,
- lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
- blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
- def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
- table: noop,
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
- text: /^[^\n]+/
-};
-
-block.bullet = /(?:[*+-]|\d+\.)/;
-block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
-block.item = replace(block.item, "gm")(/bull/g, block.bullet)();
-
-block.list = replace(block.list)(/bull/g, block.bullet)(
- "hr",
- /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/
-)();
-
-block._tag =
- "(?!(?:" +
- "a|em|strong|small|s|cite|q|dfn|abbr|data|time|code" +
- "|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo" +
- "|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";
-
-block.html = replace(block.html)("comment", //)(
- "closed",
- /<(tag)[\s\S]+?<\/\1>/
-)("closing", /])*?>/)(/tag/g, block._tag)();
-
-block.paragraph = replace(block.paragraph)("hr", block.hr)(
- "heading",
- block.heading
-)("lheading", block.lheading)("blockquote", block.blockquote)(
- "tag",
- "<" + block._tag
-)("def", block.def)();
-
-/**
- * Normal Block Grammar
- */
-
-block.normal = merge({}, block);
-
-/**
- * GFM Block Grammar
- */
-
-block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
- paragraph: /^/
-});
-
-block.gfm.paragraph = replace(block.paragraph)(
- "(?!",
- "(?!" + block.gfm.fences.source.replace("\\1", "\\2") + "|"
-)();
-
-/**
- * GFM + Tables Block Grammar
- */
-
-block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
-});
-
-/**
- * Block Lexer
- */
-
-function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
-
- if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
-}
-
-/**
- * Expose Block Rules
- */
-
-Lexer.rules = block;
-
-/**
- * Static Lex Method
- */
-
-Lexer.lex = function(src, options) {
- const lexer = new Lexer(options);
- return lexer.lex(src);
-};
-
-/**
- * Preprocessing
- */
-
-Lexer.prototype.lex = function(src) {
- src = src
- .replace(/\r\n|\r/g, "\n")
- .replace(/\t/g, " ")
- .replace(/\u00a0/g, " ")
- .replace(/\u2424/g, "\n");
-
- return this.token(src, true);
-};
-
-/**
- * Lexing
- */
-
-Lexer.prototype.token = function(_src, top) {
- let src = _src.replace(/^ +$/gm, "");
- let next;
- let loose;
- let cap;
- let bull;
- let b;
- let item;
- let space;
- let i;
- let l;
-
- while (src) {
- // newline
- if ((cap = this.rules.newline.exec(src))) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: "space"
- });
- }
- }
-
- // code
- if ((cap = this.rules.code.exec(src))) {
- src = src.substring(cap[0].length);
- cap = cap[0].replace(/^ {4}/gm, "");
- this.tokens.push({
- type: "code",
- text: !this.options.pedantic ? cap.replace(/\n+$/, "") : cap
- });
- continue;
- }
-
- // fences (gfm)
- if ((cap = this.rules.fences.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "code",
- lang: cap[2],
- text: cap[3]
- });
- continue;
- }
-
- // heading
- if ((cap = this.rules.heading.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "heading",
- depth: cap[1].length,
- text: cap[2]
- });
- continue;
- }
-
- // table no leading pipe (gfm)
- if (top && (cap = this.rules.nptable.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: "table",
- header: cap[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
- cells: cap[3].replace(/\n$/, "").split("\n")
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = "right";
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = "center";
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = "left";
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i].split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // lheading
- if ((cap = this.rules.lheading.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "heading",
- depth: cap[2] === "=" ? 1 : 2,
- text: cap[1]
- });
- continue;
- }
-
- // hr
- if ((cap = this.rules.hr.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "hr"
- });
- continue;
- }
-
- // blockquote
- if ((cap = this.rules.blockquote.exec(src))) {
- src = src.substring(cap[0].length);
-
- this.tokens.push({
- type: "blockquote_start"
- });
-
- cap = cap[0].replace(/^ *> ?/gm, "");
-
- // Pass `top` to keep the current
- // "toplevel" state. This is exactly
- // how markdown.pl works.
- this.token(cap, top);
-
- this.tokens.push({
- type: "blockquote_end"
- });
-
- continue;
- }
-
- // list
- if ((cap = this.rules.list.exec(src))) {
- src = src.substring(cap[0].length);
- bull = cap[2];
-
- this.tokens.push({
- type: "list_start",
- ordered: bull.length > 1
- });
-
- // Get each top-level item.
- cap = cap[0].match(this.rules.item);
-
- next = false;
- l = cap.length;
- i = 0;
-
- for (; i < l; i++) {
- item = cap[i];
-
- // Remove the list item's bullet
- // so it is seen as the next token.
- space = item.length;
- item = item.replace(/^ *([*+-]|\d+\.) +/, "");
-
- // Outdent whatever the
- // list item contains. Hacky.
- if (~item.indexOf("\n ")) {
- // eslint-disable-line
- space -= item.length;
- item = !this.options.pedantic
- ? item.replace(new RegExp("^ {1," + space + "}", "gm"), "")
- : item.replace(/^ {1,4}/gm, "");
- }
-
- // Determine whether the next list item belongs here.
- // Backpedal if it does not belong in this list.
- if (this.options.smartLists && i !== l - 1) {
- b = block.bullet.exec(cap[i + 1])[0];
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
- src = cap.slice(i + 1).join("\n") + src;
- i = l - 1;
- }
- }
-
- // Determine whether item is loose or not.
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
- // for discount behavior.
- loose = next || /\n\n(?!\s*$)/.test(item);
- if (i !== l - 1) {
- next = item[item.length - 1] === "\n";
- if (!loose) {
- loose = next;
- }
- }
-
- this.tokens.push({
- type: loose ? "loose_item_start" : "list_item_start"
- });
-
- // Recurse.
- this.token(item, false);
-
- this.tokens.push({
- type: "list_item_end"
- });
- }
-
- this.tokens.push({
- type: "list_end"
- });
-
- continue;
- }
-
- // html
- if ((cap = this.rules.html.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: this.options.sanitize ? "paragraph" : "html",
- pre: cap[1] === "pre" || cap[1] === "script",
- text: cap[0]
- });
- continue;
- }
-
- // def
- if (top && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.links[cap[1].toLowerCase()] = {
- href: cap[2],
- title: cap[3]
- };
- continue;
- }
-
- // table (gfm)
- if (top && (cap = this.rules.table.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: "table",
- header: cap[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
- cells: cap[3].replace(/(?: *\| *)?\n$/, "").split("\n")
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = "right";
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = "center";
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = "left";
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i]
- .replace(/^ *\| *| *\| *$/g, "")
- .split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // top-level paragraph
- if (top && (cap = this.rules.paragraph.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "paragraph",
- text: cap[1][cap[1].length - 1] === "\n" ? cap[1].slice(0, -1) : cap[1]
- });
- continue;
- }
-
- // text
- if ((cap = this.rules.text.exec(src))) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "text",
- text: cap[0]
- });
- continue;
- }
-
- if (src) {
- throw new Error("Infinite loop on byte: " + src.charCodeAt(0));
- }
- }
-
- return this.tokens;
-};
-
-/**
- * Inline-Level Grammar
- */
-
-const inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
- url: noop,
- tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;
-
-inline.link = replace(inline.link)("inside", inline._inside)(
- "href",
- inline._href
-)();
-
-inline.reflink = replace(inline.reflink)("inside", inline._inside)();
-
-/**
- * Normal Inline Grammar
- */
-
-inline.normal = merge({}, inline);
-
-/**
- * Pedantic Inline Grammar
- */
-
-inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
-});
-
-/**
- * GFM Inline Grammar
- */
-
-inline.gfm = merge({}, inline.normal, {
- escape: replace(inline.escape)("])", "~|])")(),
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
- text: replace(inline.text)("]|", "~]|")("|", "|https?://|")()
-});
-
-/**
- * GFM + Line Breaks Inline Grammar
- */
-
-inline.breaks = merge({}, inline.gfm, {
- br: replace(inline.br)("{2,}", "*")(),
- text: replace(inline.gfm.text)("{2,}", "*")()
-});
-
-/**
- * Inline Lexer & Compiler
- */
-
-function InlineLexer(links, options) {
- this.options = options || marked.defaults;
- this.links = links;
- this.rules = inline.normal;
-
- if (!this.links) {
- throw new Error("Tokens array requires a `links` property.");
- }
-
- if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
- }
-}
-
-/**
- * Expose Inline Rules
- */
-
-InlineLexer.rules = inline;
-
-/**
- * Static Lexing/Compiling Method
- */
-
-InlineLexer.output = function(src, links, options) {
- const inline = new InlineLexer(links, options);
- return inline.output(src);
-};
-
-/**
- * Lexing/Compiling
- */
-
-InlineLexer.prototype.output = function(src) {
- const out = [];
- let link;
- let text;
- let href;
- let cap;
-
- while (src) {
- // escape
- if ((cap = this.rules.escape.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(cap[1]);
- continue;
- }
-
- // autolink
- if ((cap = this.rules.autolink.exec(src))) {
- src = src.substring(cap[0].length);
- if (cap[2] === "@") {
- text = cap[1][6] === ":" ? cap[1].substring(7) : cap[1];
- href = "mailto:" + text;
- } else {
- text = cap[1];
- href = text;
- }
- out.push(DOM.a({ href: this.sanitizeUrl(href) }, text));
- continue;
- }
-
- // url (gfm)
- if ((cap = this.rules.url.exec(src))) {
- src = src.substring(cap[0].length);
- text = cap[1];
- href = text;
- out.push(DOM.a({ href: this.sanitizeUrl(href) }, text));
- continue;
- }
-
- // tag
- if ((cap = this.rules.tag.exec(src))) {
- src = src.substring(cap[0].length);
- // TODO(alpert): Don't escape if sanitize is false
- out.push(cap[0]);
- continue;
- }
-
- // link
- if ((cap = this.rules.link.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(
- this.outputLink(cap, {
- href: cap[2],
- title: cap[3]
- })
- );
- continue;
- }
-
- // reflink, nolink
- if (
- (cap = this.rules.reflink.exec(src)) ||
- (cap = this.rules.nolink.exec(src))
- ) {
- src = src.substring(cap[0].length);
- link = (cap[2] || cap[1]).replace(/\s+/g, " ");
- link = this.links[link.toLowerCase()];
- if (!link || !link.href) {
- out.push.apply(out, this.output(cap[0][0]));
- src = cap[0].substring(1) + src;
- continue;
- }
- out.push(this.outputLink(cap, link));
- continue;
- }
-
- // strong
- if ((cap = this.rules.strong.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(DOM.strong(null, this.output(cap[2] || cap[1])));
- continue;
- }
-
- // em
- if ((cap = this.rules.em.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(DOM.em(null, this.output(cap[2] || cap[1])));
- continue;
- }
-
- // code
- if ((cap = this.rules.code.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(DOM.code(null, cap[2]));
- continue;
- }
-
- // br
- if ((cap = this.rules.br.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(DOM.br(null, null));
- continue;
- }
-
- // del (gfm)
- if ((cap = this.rules.del.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(DOM.del(null, this.output(cap[1])));
- continue;
- }
-
- // text
- if ((cap = this.rules.text.exec(src))) {
- src = src.substring(cap[0].length);
- out.push(this.smartypants(cap[0]));
- continue;
- }
-
- if (src) {
- throw new Error("Infinite loop on byte: " + src.charCodeAt(0));
- }
- }
-
- return out;
-};
-
-/**
- * Sanitize a URL for a link or image
- */
-
-InlineLexer.prototype.sanitizeUrl = function(url) {
- if (this.options.sanitize) {
- try {
- const prot = decodeURIComponent(url)
- .replace(/[^A-Za-z0-9:]/g, "")
- .toLowerCase();
- if (prot.indexOf("javascript:") === 0) {
- // eslint-disable-line
- return "#";
- }
- } catch (e) {
- return "#";
- }
- }
- return url;
-};
-
-/**
- * Compile Link
- */
-
-InlineLexer.prototype.outputLink = function(cap, link) {
- if (cap[0][0] !== "!") {
- const shouldOpenInNewWindow =
- link.href.charAt(0) !== "/" && link.href.charAt(0) !== "#";
-
- return DOM.a(
- {
- href: this.sanitizeUrl(link.href),
- title: link.title,
- target: shouldOpenInNewWindow ? "_blank" : ""
- },
- this.output(cap[1])
- );
- } else {
- return DOM.img(
- {
- src: this.sanitizeUrl(link.href),
- alt: cap[1],
- title: link.title
- },
- null
- );
- }
-};
-
-/**
- * Smartypants Transformations
- */
-
-InlineLexer.prototype.smartypants = function(text) {
- if (!this.options.smartypants) {
- return text;
- }
- return text
- .replace(/--/g, "\u2014")
- .replace(/'([^']*)'/g, "\u2018$1\u2019")
- .replace(/"([^"]*)"/g, "\u201C$1\u201D")
- .replace(/\.{3}/g, "\u2026");
-};
-
-/**
- * Parsing & Compiling
- */
-
-function Parser(options) {
- this.tokens = [];
- this.token = null;
- this.options = options || marked.defaults;
-}
-
-/**
- * Static Parse Method
- */
-
-Parser.parse = function(src, options) {
- const parser = new Parser(options);
- return parser.parse(src);
-};
-
-/**
- * Parse Loop
- */
-
-Parser.prototype.parse = function(src) {
- this.inline = new InlineLexer(src.links, this.options);
- this.tokens = src.reverse();
-
- const out = [];
- while (this.next()) {
- out.push(this.tok());
- }
-
- return out;
-};
-
-/**
- * Next Token
- */
-
-Parser.prototype.next = function() {
- return (this.token = this.tokens.pop());
-};
-
-/**
- * Preview Next Token
- */
-
-Parser.prototype.peek = function() {
- return this.tokens[this.tokens.length - 1] || 0;
-};
-
-/**
- * Parse Text Tokens
- */
-
-Parser.prototype.parseText = function() {
- let body = this.token.text;
-
- while (this.peek().type === "text") {
- body += "\n" + this.next().text;
- }
-
- return this.inline.output(body);
-};
-
-/**
- * Parse Current Token
- */
-
-Parser.prototype.tok = function() {
- // eslint-disable-line
- switch (this.token.type) {
- case "space": {
- return [];
- }
- case "hr": {
- return DOM.hr(null, null);
- }
- case "heading": {
- return (
-
- {this.inline.output(this.token.text)}
-
- );
- }
- case 'code': {
- const lang = this.token.lang, text = this.token.text;
-
- if (
- lang && lang.indexOf('ReactNativeWebPlayer') === 0
- ) {
- return (
-
- {text}
-
- );
- }
-
- if (lang && lang.indexOf('SnackPlayer') === 0) {
- return (
-
- {text}
-
- );
- }
-
- if (lang) {
- return {text} ;
- }
-
- return {text} ;
- }
- case "table": {
- const table = [];
- const body = [];
- let row = [];
- let heading;
- let i;
- let cells;
- let j;
-
- // header
- for (i = 0; i < this.token.header.length; i++) {
- heading = this.inline.output(this.token.header[i]);
- row.push(
- DOM.th(
- this.token.align[i]
- ? { style: { textAlign: this.token.align[i] } }
- : null,
- heading
- )
- );
- }
- table.push(DOM.thead(null, DOM.tr(null, row)));
-
- // body
- for (i = 0; i < this.token.cells.length; i++) {
- row = [];
- cells = this.token.cells[i];
- for (j = 0; j < cells.length; j++) {
- row.push(
- DOM.td(
- this.token.align[j]
- ? { style: { textAlign: this.token.align[j] } }
- : null,
- this.inline.output(cells[j])
- )
- );
- }
- body.push(DOM.tr(null, row));
- }
- table.push(DOM.thead(null, body));
-
- return DOM.table(null, table);
- }
- case "blockquote_start": {
- const body = [];
-
- while (this.next().type !== "blockquote_end") {
- body.push(this.tok());
- }
-
- return DOM.blockquote(null, body);
- }
- case "list_start": {
- const type = this.token.ordered ? "ol" : "ul";
- const body = [];
-
- while (this.next().type !== "list_end") {
- body.push(this.tok());
- }
-
- return DOM[type](null, body);
- }
- case "list_item_start": {
- const body = [];
-
- while (this.next().type !== "list_item_end") {
- body.push(this.token.type === "text" ? this.parseText() : this.tok());
- }
-
- return DOM.li(null, body);
- }
- case "loose_item_start": {
- const body = [];
-
- while (this.next().type !== "list_item_end") {
- body.push(this.tok());
- }
-
- return DOM.li(null, body);
- }
- case "html": {
- return DOM.div({
- dangerouslySetInnerHTML: {
- __html: this.token.text
- }
- });
- }
- case "paragraph": {
- return this.options.paragraphFn
- ? this.options.paragraphFn.call(
- null,
- this.inline.output(this.token.text)
- )
- : DOM.p(null, this.inline.output(this.token.text));
- }
- case "text": {
- return this.options.paragraphFn
- ? this.options.paragraphFn.call(null, this.parseText())
- : DOM.p(null, this.parseText());
- }
- }
-};
-
-/**
- * Helpers
- */
-
-function replace(regex, opt) {
- regex = regex.source;
- opt = opt || "";
- return function self(name, val) {
- if (!name) {
- return new RegExp(regex, opt);
- }
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, "$1");
- regex = regex.replace(name, val);
- return self;
- };
-}
-
-function noop() {}
-noop.exec = noop;
-
-function merge(obj) {
- let i = 1;
- let target;
- let key;
-
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
-
- return obj;
-}
-
-/**
- * Marked
- */
-
-function marked(src, opt, callback) {
- if (callback || typeof opt === "function") {
- if (!callback) {
- callback = opt;
- opt = null;
- }
-
- if (opt) {
- opt = merge({}, marked.defaults, opt);
- }
-
- const highlight = opt.highlight;
- let tokens;
- let pending;
- let i = 0;
-
- try {
- tokens = Lexer.lex(src, opt);
- } catch (e) {
- return callback(e);
- }
-
- pending = tokens.length;
-
- const done = function(hi) {
- let out, err;
-
- if (hi !== true) {
- delete opt.highlight;
- }
-
- try {
- out = Parser.parse(tokens, opt);
- } catch (e) {
- err = e;
- }
-
- opt.highlight = highlight;
-
- return err ? callback(err) : callback(null, out);
- };
-
- if (!highlight || highlight.length < 3) {
- return done(true);
- }
-
- if (!pending) {
- return done();
- }
-
- for (; i < tokens.length; i++) {
- (function(token) {
- if (token.type !== "code") {
- return --pending || done();
- }
- return highlight(token.text, token.lang, (err, code) => {
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- return undefined;
- });
- })(tokens[i]);
- }
-
- return undefined;
- }
- try {
- if (opt) {
- opt = merge({}, marked.defaults, opt);
- }
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += "\nPlease report this to https://github.com/chjj/marked.";
- if ((opt || marked.defaults).silent) {
- return [
- DOM.p(null, "An error occurred:"),
- DOM.pre(null, e.message)
- ];
- }
- throw e;
- }
-}
-
-/**
- * Options
- */
-
-marked.options = marked.setOptions = function(opt) {
- merge(marked.defaults, opt);
- return marked;
-};
-
-marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: "lang-",
- smartypants: false,
- paragraphFn: null
-};
-
-/**
- * Expose
- */
-
-marked.Parser = Parser;
-marked.parser = Parser.parse;
-
-marked.Lexer = Lexer;
-marked.lexer = Lexer.lex;
-
-marked.InlineLexer = InlineLexer;
-marked.inlineLexer = InlineLexer.output;
-
-marked.parse = marked;
+const React = require('react');
+const Remarkable = require('./Remarkable');
class Marked extends React.Component {
render() {
return (
-
- {marked(this.props.children, this.props)}
-
+
);
}
}
diff --git a/lib/core/Prism.js b/lib/core/Prism.js
deleted file mode 100644
index be438dde4e..0000000000
--- a/lib/core/Prism.js
+++ /dev/null
@@ -1,1161 +0,0 @@
-/**
- * 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.
- */
-
-/* Prism is used by Marked to do code syntas highlighting */
-
-const React = require("react");
-
-/**
- * Prism: Lightweight, robust, elegant syntax highlighting
- * MIT license https://www.opensource.org/licenses/mit-license.php/
- * @author Lea Verou https://lea.verou.me
- */
-
-// Private helper vars
-const lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
-
-const Prism = {
- util: {
- encode(tokens) {
- if (tokens instanceof Token) {
- return new Token(
- tokens.type,
- Prism.util.encode(tokens.content),
- tokens.alias
- );
- } else if (Prism.util.type(tokens) === "Array") {
- return tokens.map(Prism.util.encode);
- } else {
- return tokens
- .replace(/&/g, "&")
- .replace(/ {
- return Prism.util.clone(v);
- })
- );
- }
-
- return o;
- }
- },
-
- languages: {
- extend(id, redef) {
- const lang = Prism.util.clone(Prism.languages[id]);
-
- for (const key in redef) {
- lang[key] = redef[key];
- }
-
- return lang;
- },
-
- /**
- * Insert a token before another token in a language literal
- * As this needs to recreate the object (we cannot actually insert before keys in object literals),
- * we cannot just provide an object, we need an object and a key.
- * @param inside The key (or language id) of the parent
- * @param before The key to insert before. If not provided, the function appends instead.
- * @param insert Object with the key/value pairs to insert
- * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
- */
- insertBefore(inside, before, insert, root) {
- root = root || Prism.languages;
- const grammar = root[inside];
-
- if (arguments.length == 2) {
- insert = arguments[1];
-
- for (var newToken in insert) {
- if (insert.hasOwnProperty(newToken)) {
- grammar[newToken] = insert[newToken];
- }
- }
-
- return grammar;
- }
-
- const ret = {};
-
- for (const token in grammar) {
- if (grammar.hasOwnProperty(token)) {
- if (token == before) {
- for (var newToken in insert) {
- if (insert.hasOwnProperty(newToken)) {
- ret[newToken] = insert[newToken];
- }
- }
- }
-
- ret[token] = grammar[token];
- }
- }
-
- // Update references in other language definitions
- Prism.languages.DFS(Prism.languages, function(key, value) {
- if (value === root[inside] && key != inside) {
- this[key] = ret;
- }
- });
-
- return (root[inside] = ret);
- },
-
- // Traverse a language definition with Depth First Search
- DFS(o, callback, type) {
- for (const i in o) {
- if (o.hasOwnProperty(i)) {
- callback.call(o, i, o[i], type || i);
-
- if (Prism.util.type(o[i]) === "Object") {
- Prism.languages.DFS(o[i], callback);
- } else if (Prism.util.type(o[i]) === "Array") {
- Prism.languages.DFS(o[i], callback, i);
- }
- }
- }
- }
- },
-
- highlightAll(async, callback) {
- const elements = document.querySelectorAll(
- 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
- );
-
- for (let i = 0, element; (element = elements[i++]); ) {
- Prism.highlightElement(element, async === true, callback);
- }
- },
-
- highlightElement(element, async, callback) {
- // Find language
- let language,
- grammar,
- parent = element;
-
- while (parent && !lang.test(parent.className)) {
- parent = parent.parentNode;
- }
-
- if (parent) {
- language = (parent.className.match(lang) || [, ""])[1];
- grammar = Prism.languages[language];
- }
-
- // Set language on the element, if not present
- element.className =
- element.className.replace(lang, "").replace(/\s+/g, " ") +
- " language-" +
- language;
-
- // Set language on the parent, for styling
- parent = element.parentNode;
-
- if (/pre/i.test(parent.nodeName)) {
- parent.className =
- parent.className.replace(lang, "").replace(/\s+/g, " ") +
- " language-" +
- language;
- }
-
- if (!grammar) {
- return;
- }
-
- let code = element.textContent;
-
- if (!code) {
- return;
- }
-
- code = code.replace(/^(?:\r?\n|\r)/, "");
-
- const env = {
- element,
- language,
- grammar,
- code
- };
-
- Prism.hooks.run("before-highlight", env);
-
- if (async && Prismself.Worker) {
- const worker = new Worker(Prism.filename);
-
- worker.onmessage = function(evt) {
- env.highlightedCode = Token.stringify(JSON.parse(evt.data), language);
-
- Prism.hooks.run("before-insert", env);
-
- env.element.innerHTML = env.highlightedCode;
-
- callback && callback.call(env.element);
- Prism.hooks.run("after-highlight", env);
- };
-
- worker.postMessage(
- JSON.stringify({
- language: env.language,
- code: env.code
- })
- );
- } else {
- env.highlightedCode = Prism.highlight(
- env.code,
- env.grammar,
- env.language
- );
-
- Prism.hooks.run("before-insert", env);
-
- env.element.innerHTML = env.highlightedCode;
-
- callback && callback.call(element);
-
- Prism.hooks.run("after-highlight", env);
- }
- },
-
- highlight(text, grammar, language) {
- const tokens = Prism.tokenize(text, grammar);
- return Token.stringify(Prism.util.encode(tokens), language);
- },
-
- tokenize(text, grammar, language) {
- const Token = Prism.Token;
-
- const strarr = [text];
-
- if (grammar && grammar.rest) {
- const rest = grammar.rest;
- for (var token in rest) {
- grammar[token] = rest[token];
- }
-
- delete grammar.rest;
- }
-
- tokenloop: for (var token in grammar) {
- if (!grammar.hasOwnProperty(token) || !grammar[token]) {
- continue;
- }
-
- let patterns = grammar[token];
- patterns = Prism.util.type(patterns) === "Array" ? patterns : [patterns];
-
- for (let j = 0; j < patterns.length; ++j) {
- let pattern = patterns[j],
- inside = pattern.inside,
- lookbehind = !!pattern.lookbehind,
- lookbehindLength = 0,
- alias = pattern.alias;
-
- pattern = pattern.pattern || pattern;
-
- for (let i = 0; i < strarr.length; i++) {
- // Don't cache length as it changes during the loop
-
- const str = strarr[i];
-
- if (strarr.length > text.length) {
- // Something went terribly wrong, ABORT, ABORT!
- break tokenloop;
- }
-
- if (str instanceof Token) {
- continue;
- }
-
- pattern.lastIndex = 0;
-
- var match = pattern.exec(str);
-
- if (match) {
- if (lookbehind) {
- lookbehindLength = match[1].length;
- }
-
- var from = match.index - 1 + lookbehindLength,
- match = match[0].slice(lookbehindLength),
- len = match.length,
- to = from + len,
- before = str.slice(0, from + 1),
- after = str.slice(to + 1);
-
- const args = [i, 1];
-
- if (before) {
- args.push(before);
- }
-
- const wrapped = new Token(
- token,
- inside ? Prism.tokenize(match, inside) : match,
- alias
- );
-
- args.push(wrapped);
-
- if (after) {
- args.push(after);
- }
-
- Array.prototype.splice.apply(strarr, args);
- }
- }
- }
- }
-
- return strarr;
- },
-
- hooks: {
- all: {},
-
- add(name, callback) {
- const hooks = Prism.hooks.all;
-
- hooks[name] = hooks[name] || [];
-
- hooks[name].push(callback);
- },
-
- run(name, env) {
- const callbacks = Prism.hooks.all[name];
-
- if (!callbacks || !callbacks.length) {
- return;
- }
-
- for (let i = 0, callback; (callback = callbacks[i++]); ) {
- callback(env);
- }
- }
- }
-};
-
-const Token = (Prism.Token = function(type, content, alias) {
- this.type = type;
- this.content = content;
- this.alias = alias;
-});
-
-Token.reactify = function(o, language, parent, key) {
- if (typeof o == "string") {
- return o;
- }
-
- if (Prism.util.type(o) === "Array") {
- return o.map((element, i) => {
- return Token.reactify(element, language, o, i);
- });
- }
-
- const env = {
- type: o.type,
- content: Token.reactify(o.content, language, parent),
- tag: "span",
- classes: ["token", o.type],
- attributes: { key },
- language,
- parent
- };
-
- if (env.type == "comment") {
- env.attributes.spellCheck = true;
- }
-
- if (o.alias) {
- const aliases = Prism.util.type(o.alias) === "Array" ? o.alias : [o.alias];
- Array.prototype.push.apply(env.classes, aliases);
- }
-
- Prism.hooks.run("wrap", env);
-
- env.attributes.className = env.classes.join(" ");
-
- return React.DOM[env.tag](env.attributes, env.content);
-};
-
-(Prism.languages.markup = {
- comment: //,
- prolog: /<\?[\s\S]+?\?>/,
- doctype: //i,
- cdata: //i,
- tag: {
- pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,
- inside: {
- tag: {
- pattern: /^<\/?[^\s>\/]+/i,
- inside: { punctuation: /^<\/?/, namespace: /^[^\s>\/:]+:/ }
- },
- "attr-value": {
- pattern: /=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i,
- inside: { punctuation: /[=>"']/ }
- },
- punctuation: /\/?>/,
- "attr-name": {
- pattern: /[^\s>\/]+/,
- inside: { namespace: /^[^\s>\/:]+:/ }
- }
- }
- },
- entity: /?[\da-z]{1,8};/i
-}), (Prism.languages.markup.tag.inside["attr-value"].inside.entity =
- Prism.languages.markup.entity), Prism.hooks.add("wrap", function(a) {
- "entity" === a.type && (a.attributes.title = a.content.replace(/&/, "&"));
-}), (Prism.languages.xml = Prism.languages.markup), (Prism.languages.html =
- Prism.languages.markup), (Prism.languages.mathml =
- Prism.languages.markup), (Prism.languages.svg = Prism.languages.markup);
-(Prism.languages.css = {
- comment: /\/\*[\s\S]*?\*\//,
- atrule: { pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, inside: { rule: /@[\w-]+/ } },
- url: /url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
- selector: /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
- string: {
- pattern: /("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
- greedy: !0
- },
- property: /(\b|\B)[\w-]+(?=\s*:)/i,
- important: /\B!important\b/i,
- function: /[-a-z0-9]+(?=\()/i,
- punctuation: /[(){};:]/
-}), (Prism.languages.css.atrule.inside.rest = Prism.util.clone(
- Prism.languages.css
-)), Prism.languages.markup &&
- (
- Prism.languages.insertBefore("markup", "tag", {
- style: {
- pattern: /(