From f88bbc6d72d88905d2eff8e186a947688a103e74 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 8 Oct 2018 10:36:09 -0400 Subject: [PATCH] convert markdown logic to re-usable component --- app/components/ecosystem/module-lbrycrd.js | 20 +--- app/components/markdown.js | 82 +++++++++++++++++ app/sass/init/_markdown.scss | 2 +- app/views/redirect.js | 101 +++------------------ documents/partials/lbrycrd.md | 16 ++++ 5 files changed, 114 insertions(+), 107 deletions(-) create mode 100644 app/components/markdown.js create mode 100644 documents/partials/lbrycrd.md diff --git a/app/components/ecosystem/module-lbrycrd.js b/app/components/ecosystem/module-lbrycrd.js index 331cf19..744620a 100644 --- a/app/components/ecosystem/module-lbrycrd.js +++ b/app/components/ecosystem/module-lbrycrd.js @@ -1,6 +1,6 @@ "use strict"; - +import markdown from "../markdown"; // E X P O R T @@ -20,23 +20,7 @@ module.exports = exports = () => `
-

This section assumes "blockchain" already means something to you. If you're totally new, the key problem solved by blockhain is the ability for distributed, disparate entities to all agree on a rivalrous state of affairs. For a more comprehensive introduction to blockchain, try starting [here]

- -

LBRY uses a public, proof-of-work blockchain that is very similar to Bitcoin. The blockchain is the foundation of the protocol stack.

- -

The most salient feature of the LBRY blockchain is the association of a string of characters (a "name") with a structured set of metadata. This name can be accessed as a LBRY URL, e.g. lbry://hellolbry

- -

The LBRY blockchain stores names and metadata in a Merkle tree. This allows LBRY URLs to be trustfully resolved even without a full copy of the blockchain.

- -

The metadata contains information about the content, such as the title, creator, price (if any), and a unique signature allowing the actual content to be fetched from the data network, the next level in the LBRY stack.

- -

Additional Resources

- + ${markdown("./documents/partials/lbrycrd.md")}
`; diff --git a/app/components/markdown.js b/app/components/markdown.js new file mode 100644 index 0000000..9004433 --- /dev/null +++ b/app/components/markdown.js @@ -0,0 +1,82 @@ +"use strict"; + +import decamelize from "decamelize"; +import exists from "fs-exists-sync"; +import fs from "graceful-fs"; +import fm from "front-matter"; +import html from "choo/html"; +import path from "path"; +import raw from "choo/html/raw"; +import { require as local } from "app-root-path"; + +const numberRegex = /^[0-9]/g; +const md = require("markdown-it")({ + html: true, + typographer: true +}).use(local("app/modules/markdown-it-sup")) + .use(require("markdown-it-anchor"), { + slugify: stringToSlugify => { + let finalString = stringToSlugify + .toLowerCase() + .replace(/\s\/\s/g, "-") + .replace(/\s/g, "-") + .replace(/%/g, "") + .replace(/\(/g, "") + .replace(/\)/g, "") + .replace(/,/g, ""); + + if (finalString.match(numberRegex)) finalString = `_${finalString}`; + return finalString; + } + }); + + + +export default path => { + + const markdownFile = fs.readFileSync(path, "utf-8"); + const markdownFileDetails = fm(markdownFile); + const renderedMarkdown = md.render(markdownFileDetails.body); + const updatedMarkdown = wikiFinder(partialFinder(renderedMarkdown)); + + return html` +
${raw(updatedMarkdown)}
+ `; +}; + +function partialFinder(markdownBody) { + const regexToFindPartials = /<\w+ ?\/>/g; + const partials = markdownBody.match(regexToFindPartials); + + if (!partials) return markdownBody; + + for (const partial of partials) { + const filename = decamelize(partial, "-").replace("<", "") + .replace("/>", "") + .trim(); + const fileExistsTest = exists(`./app/components/${filename}.js`); // `local` results in error if used here and file !exist + + if (!fileExistsTest) + markdownBody = markdownBody.replace(partial, ""); + + else { + const partialFunction = require(path.join(__dirname, "..", `./components/${filename}.js`)); + + if (filename === "glossary-toc") markdownBody = markdownBody.replace(partial, partialFunction); + else markdownBody = markdownBody.replace(partial, `${partialFunction.default()}
`); + } + } + + return markdownBody; +} + +function wikiFinder(markdownBody) { + return markdownBody.replace(/\[\[([\w\s/-]+)\]\]/g, (match, p1) => { + const label = p1.trim(); + const url = encodeURI("/glossary#" + label.replace(/\s+/g, "-")); + + return label ? + `${label}` : + match.input; + }); +} diff --git a/app/sass/init/_markdown.scss b/app/sass/init/_markdown.scss index 5e86f52..33a6664 100644 --- a/app/sass/init/_markdown.scss +++ b/app/sass/init/_markdown.scss @@ -184,7 +184,7 @@ } } - a:not(.__button-black):not(.button):not(.header-anchor):not(.newsletter-standalone__submit):not(.__plain) { + a:not(.__button-black):not(.button) { @include underline($teal, $white); color: $teal; diff --git a/app/views/redirect.js b/app/views/redirect.js index 149fd4a..a35efd4 100644 --- a/app/views/redirect.js +++ b/app/views/redirect.js @@ -1,60 +1,24 @@ "use strict"; - - -// P A C K A G E S - -import decamelize from "decamelize"; -import exists from "fs-exists-sync"; -import fm from "front-matter"; import fs from "graceful-fs"; import html from "choo/html"; -import path from "path"; +import fm from "front-matter"; import { require as local } from "app-root-path"; +import markdown from "../components/markdown"; import raw from "choo/html/raw"; -// V A R I A B L E S - -const numberRegex = /^[0-9]/g; const redirect404 = local("app/modules/redirect-404"); -const md = require("markdown-it")({ - html: true, - typographer: true -}).use(local("app/modules/markdown-it-sup")) - .use(require("markdown-it-anchor"), { - slugify: stringToSlugify => { - let finalString = stringToSlugify - .toLowerCase() - .replace(/\s\/\s/g, "-") - .replace(/\s/g, "-") - .replace(/%/g, "") - .replace(/\(/g, "") - .replace(/\)/g, "") - .replace(/,/g, ""); - - if (finalString.match(numberRegex)) finalString = `_${finalString}`; - return finalString; - } - }); - - - -// E X P O R T - module.exports = exports = (state, emit) => { // eslint-disable-line - let path; + const partialPath = state.route === "resources/*" ? `resources/${state.params.wildcard}` : state.params.wildcard; + const path = `./documents/${partialPath}.md`; - if (state.route === "resources/*") path = `resources/${state.params.wildcard}`; - else path = state.params.wildcard; - - if (!fs.existsSync(`./documents/${path}.md`)) + if (!fs.existsSync(path)) { return redirect404(state); + } - const markdownFile = fs.readFileSync(`./documents/${path}.md`, "utf-8"); + const markdownFile = fs.readFileSync(path, "utf-8"); const markdownFileDetails = fm(markdownFile); - const renderedMarkdown = md.render(markdownFileDetails.body); - const updatedMarkdown = wikiFinder(partialFinder(renderedMarkdown)); if (markdownFileDetails.attributes.meta) { const customMetadata = {}; @@ -66,14 +30,16 @@ module.exports = exports = (state, emit) => { // eslint-disable-line } } + // below seems evil state.lbry = customMetadata; } + // below should be refactored into components let pageScript = ""; - if (path === "glossary") pageScript = ""; - if (path === "overview") pageScript = ""; - if (path === "playground") pageScript = ""; + if (partialPath === "glossary") pageScript = ""; + if (partialPath === "overview") pageScript = ""; + if (partialPath === "playground") pageScript = ""; return html`
@@ -87,51 +53,10 @@ module.exports = exports = (state, emit) => { // eslint-disable-line
-
${raw(updatedMarkdown)}
+ ${markdown(path)} ${raw(pageScript)}
`; }; - - - -// H E L P E R S - -function partialFinder(markdownBody) { - const regexToFindPartials = /<\w+ ?\/>/g; - const partials = markdownBody.match(regexToFindPartials); - - if (!partials) return markdownBody; - - for (const partial of partials) { - const filename = decamelize(partial, "-").replace("<", "") - .replace("/>", "") - .trim(); - const fileExistsTest = exists(`./app/components/${filename}.js`); // `local` results in error if used here and file !exist - - if (!fileExistsTest) - markdownBody = markdownBody.replace(partial, ""); - - else { - const partialFunction = require(path.join(__dirname, "..", `./components/${filename}.js`)); - - if (filename === "glossary-toc") markdownBody = markdownBody.replace(partial, partialFunction); - else markdownBody = markdownBody.replace(partial, `
${partialFunction.default()}
`); - } - } - - return markdownBody; -} - -function wikiFinder(markdownBody) { - return markdownBody.replace(/\[\[([\w\s/-]+)\]\]/g, (match, p1) => { - const label = p1.trim(); - const url = encodeURI("/glossary#" + label.replace(/\s+/g, "-")); - - return label ? - `${label}` : - match.input; - }); -} diff --git a/documents/partials/lbrycrd.md b/documents/partials/lbrycrd.md new file mode 100644 index 0000000..683ffa1 --- /dev/null +++ b/documents/partials/lbrycrd.md @@ -0,0 +1,16 @@ +_This section assumes "blockchain" already means something to you. If you're totally new, the key problem solved by blockhain is the ability for distributed, disparate entities to all agree on a rivalrous state of affairs. For a more comprehensive introduction to blockchain, try starting [here](https://lopp.net/bitcoin.html)_ + +LBRY uses a public, proof-of-work blockchain that is very similar to Bitcoin. The blockchain is the foundation of the protocol stack. + +The most salient feature of the LBRY blockchain is the association of a normalized string of characters (a "name") with a structured set of metadata. This coupling is called a [[claim]]. The content referenced by a claim can be accessed as a LBRY URL, e.g. [lbry://hellolbry](/playground?url=hellolbry). + +The LBRY blockchain stores names and metadata in a parallel [[Merkle tree]], separate from the tree used to store transaction data. This allows LBRY URLs to be trustfully resolved even without a full copy of the blockchain. + +The metadata contains information about the content, such as the title, creator, price (if any), and a unique signature allowing the actual content to be fetched from the data network, the next level in the LBRY stack. + +### Additional Resources + +* See the [Whitepaper](/whitepaper "Whitepaper") for a more comprehensive introduction to the LBRY blockchain. +* See the [Resources](/resources) for documentation about the LBRY blockchain, including its API. +* See [[Naming]] for learning more about LBRY URLs and how they work. +* See [[Identities]] for learning how the LBRY blockchain handles publisher identities.