Browse Source

Extraction tool

Benoît Hubert 6 years ago
parent
commit
0a9e424b4b

+ 1 - 1
.gitignore

@@ -1,2 +1,2 @@
-react-tuto/node_modules
+node_modules
 js/dist
 js/dist

+ 37 - 0
react-tuto/test/extract.test.js

@@ -0,0 +1,37 @@
+const assert = require('assert');
+const extract = require('../tools/extract');
+
+const md = `# The Title
+
+## Subsection 1 - Ain't it cool
+
+Content for subsection 1 with \`markdown\` stuff.
+
+Another paragraph.
+
+## Subsection 2 - Wow it works!
+
+Content for subsection 2.`
+
+describe('extract', () => {
+  it('build the correct structure', () => {
+    const actual = extract(md);
+    const expected = {
+      title: 'The Title',
+      path: '/the-title',
+      items: [
+        {
+          title: 'Subsection 1 - Ain\'t it cool',
+          path: '/subsection-1-aint-it-cool',
+          content: 'Content for subsection 1 with `markdown` stuff.\n\nAnother paragraph.'
+        },
+        {
+          title: 'Subsection 2 - Wow it works!',
+          path: '/subsection-2-wow-it-works',
+          content: 'Content for subsection 2.'
+        }
+      ]
+    };
+    assert.deepStrictEqual(actual, expected);
+  });
+});

+ 67 - 0
react-tuto/tools/extract.js

@@ -0,0 +1,67 @@
+const slug = require('slug');
+
+function makeSlug(title) {
+  return slug(title, {lower: true});
+}
+
+function extractTitleAndPath(markdown) {
+  const titleRegex = /^#\s(.*)/mi;
+  let title;
+  try {
+    [, title] = markdown.match(titleRegex);
+  } catch(e) {
+    throw new Error('Could not find h1 title');
+  }
+  const path = `/${makeSlug(title)}`;
+  return { title, path };
+}
+
+function findNextSubtitleIndex(lines) {
+  const subtitleRegex = /^##\s(.*)/i;
+  for (let i = 0; i < lines.length; i++) {
+    const line = lines[i];
+    const matches = line.match(subtitleRegex);
+    if (matches) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+function getSection(lines, start, end) {
+  return lines.slice(start, end).join('\n');
+}
+
+function extractSections(markdown) {
+  let lines = markdown.split('\n');
+  const subtitleRegex = /^##\s.*/gm;
+  const contents = markdown.split(/^##\s.*/gm)
+    .map(c => {
+      let start = 0;
+      while(c[start] === '\n') {
+        start++;
+      }
+      let end = c.length - 1;
+      while(c[end] === '\n') {
+        end--;
+      }
+      return c.substring(start, end + 1);
+    });
+  contents.shift();
+  const titles = lines.filter(l => /^##\s.*/.test(l))
+    .map(l => l.substr(3));
+
+  return titles.map((title, i) => ({
+    title,
+    path: `/${makeSlug(title)}`,
+    content: contents[i]
+  }));
+}
+
+function extract(markdown) {
+  const { title, path } = extractTitleAndPath(markdown);
+  const items = extractSections(markdown);
+  return { title, path, items };
+}
+
+module.exports = extract;

+ 21 - 0
react-tuto/tools/package-lock.json

@@ -0,0 +1,21 @@
+{
+  "name": "tools",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "slug": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/slug/-/slug-1.1.0.tgz",
+      "integrity": "sha512-NuIOjDQeTMPm+/AUIHJ5636mF3jOsYLFnoEErl9Tdpt4kpt4fOrAJxscH9mUgX1LtPaEqgPCawBg7A4yhoSWRg==",
+      "requires": {
+        "unicode": ">= 0.3.1"
+      }
+    },
+    "unicode": {
+      "version": "11.0.1",
+      "resolved": "https://registry.npmjs.org/unicode/-/unicode-11.0.1.tgz",
+      "integrity": "sha512-+cHtykLb+eF1yrSLWTwcYBrqJkTfX7Quoyg7Juhe6uylF43ZbMdxMuSHNYlnyLT8T7POAvavgBthzUF9AIaQvQ=="
+    }
+  }
+}

+ 15 - 0
react-tuto/tools/package.json

@@ -0,0 +1,15 @@
+{
+  "name": "tools",
+  "version": "1.0.0",
+  "description": "",
+  "main": "extract.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "slug": "^1.1.0"
+  }
+}