From 4f9b37433c3f381a718cab268a52f1f606a15b03 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 15 Dec 2018 10:11:04 +0100 Subject: [PATCH 1/4] fix toc by sharing `slugify()` --- browser/lib/markdown-toc-generator.js | 63 +++++++++++---------------- browser/lib/markdown.js | 11 +---- browser/lib/slugify.js | 6 +++ 3 files changed, 33 insertions(+), 47 deletions(-) create mode 100644 browser/lib/slugify.js diff --git a/browser/lib/markdown-toc-generator.js b/browser/lib/markdown-toc-generator.js index eae448ec9..a7bc79f37 100644 --- a/browser/lib/markdown-toc-generator.js +++ b/browser/lib/markdown-toc-generator.js @@ -6,47 +6,21 @@ import toc from 'markdown-toc' import diacritics from 'diacritics-map' import stripColor from 'strip-color' import mdlink from 'markdown-link' +import slugify from './slugify' const EOL = require('os').EOL +const hasProp = Object.prototype.hasOwnProperty + /** - * @caseSensitiveSlugify Custom slugify function - * Same implementation that the original used by markdown-toc (node_modules/markdown-toc/lib/utils.js), - * but keeps original case to properly handle https://github.com/BoostIO/Boostnote/issues/2067 + * From @enyaxu/markdown-it-anchor */ -function caseSensitiveSlugify (str) { - function replaceDiacritics (str) { - return str.replace(/[À-ž]/g, function (ch) { - return diacritics[ch] || ch - }) - } - - function getTitle (str) { - if (/^\[[^\]]+\]\(/.test(str)) { - var m = /^\[([^\]]+)\]/.exec(str) - if (m) return m[1] - } - return str - } - - str = getTitle(str) - str = stripColor(str) - // str = str.toLowerCase() //let's be case sensitive - - // `.split()` is often (but not always) faster than `.replace()` - str = str.split(' ').join('-') - str = str.split(/\t/).join('--') - str = str.split(/<\/?[^>]+>/).join('') - str = str.split(/[|$&`~=\\\/@+*!?({[\]})<>=.,;:'"^]/).join('') - str = str.split(/[。?!,、;:“”【】()〔〕[]﹃﹄“ ”‘’﹁﹂—…-~《》〈〉「」]/).join('') - str = replaceDiacritics(str) - return str -} - -function linkify (tok, text, slug, opts) { - var uniqeID = opts.num === 0 ? '' : '-' + opts.num - tok.content = mdlink(text, '#' + slug + uniqeID) - return tok +function uniqueSlug (slug, slugs, opts) { + let uniq = slug + let i = opts.uniqueSlugStartIndex + while (hasProp.call(slugs, uniq)) uniq = `${slug}-${i++}` + slugs[uniq] = true + return uniq } const TOC_MARKER_START = '' @@ -91,8 +65,21 @@ export function generateInEditor (editor) { * @returns generatedTOC String containing generated TOC */ export function generate (markdownText) { - const generatedToc = toc(markdownText, {slugify: caseSensitiveSlugify, linkify: linkify}) - return TOC_MARKER_START + EOL + EOL + generatedToc.content + EOL + EOL + TOC_MARKER_END + const slugs = {} + const opts = { + uniqueSlugStartIndex: 1 + } + + const tokens = toc(markdownText, { + slugify: title => { + return uniqueSlug(slugify(title), slugs, opts) + }, + linkify: false + }) + + const md = tokens.json.map(token => mdlink(token.content, '#' + token.slug)).join(EOL) + + return TOC_MARKER_START + EOL + EOL + md + EOL + EOL + TOC_MARKER_END } function wrapTocWithEol (toc, editor) { diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 2a7b66b01..0f7d58b58 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -7,7 +7,6 @@ import _ from 'lodash' import ConfigManager from 'browser/main/lib/ConfigManager' import katex from 'katex' import { lastFindInArray } from './utils' -import anchor from '@enyaxu/markdown-it-anchor' function createGutter (str, firstLineNumber) { if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 @@ -118,14 +117,8 @@ class Markdown { this.md.use(require('markdown-it-imsize')) this.md.use(require('markdown-it-footnote')) this.md.use(require('markdown-it-multimd-table')) - this.md.use(anchor, { - slugify: (title) => { - var slug = encodeURI(title.trim() - .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '') - .replace(/\s+/g, '-')) - .replace(/\-+$/, '') - return slug - } + this.md.use(require('@enyaxu/markdown-it-anchor'), { + slugify: require('./slugify') }) this.md.use(require('markdown-it-kbd')) this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']}) diff --git a/browser/lib/slugify.js b/browser/lib/slugify.js new file mode 100644 index 000000000..0ff21245f --- /dev/null +++ b/browser/lib/slugify.js @@ -0,0 +1,6 @@ +module.exports = function slugify (title) { + return encodeURI(title.trim() + .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '') + .replace(/\s+/g, '-')) + .replace(/\-+$/, '') +} From d5a2aa6d6d8ab0434cd29da4a4b294e4c1839ae2 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sat, 15 Dec 2018 10:41:47 +0100 Subject: [PATCH 2/4] fix missing bullets --- browser/lib/markdown-toc-generator.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/browser/lib/markdown-toc-generator.js b/browser/lib/markdown-toc-generator.js index a7bc79f37..7a97f8009 100644 --- a/browser/lib/markdown-toc-generator.js +++ b/browser/lib/markdown-toc-generator.js @@ -2,14 +2,13 @@ * @fileoverview Markdown table of contents generator */ +import { EOL } from 'os' import toc from 'markdown-toc' import diacritics from 'diacritics-map' import stripColor from 'strip-color' import mdlink from 'markdown-link' import slugify from './slugify' -const EOL = require('os').EOL - const hasProp = Object.prototype.hasOwnProperty /** @@ -23,6 +22,11 @@ function uniqueSlug (slug, slugs, opts) { return uniq } +function linkify (token) { + token.content = mdlink(token.content, '#' + token.slug) + return token +} + const TOC_MARKER_START = '' const TOC_MARKER_END = '' @@ -70,14 +74,16 @@ export function generate (markdownText) { uniqueSlugStartIndex: 1 } - const tokens = toc(markdownText, { + const result = toc(markdownText, { slugify: title => { return uniqueSlug(slugify(title), slugs, opts) }, linkify: false }) - const md = tokens.json.map(token => mdlink(token.content, '#' + token.slug)).join(EOL) + const md = toc.bullets(result.json.map(linkify), { + highest: result.highest + }) return TOC_MARKER_START + EOL + EOL + md + EOL + EOL + TOC_MARKER_END } From b99980fda1afcb12df5316337fb0b869a65b550e Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sun, 16 Dec 2018 19:38:04 +0100 Subject: [PATCH 3/4] improve slug by replacing diacritics and removing unwanted characters --- browser/lib/slugify.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/browser/lib/slugify.js b/browser/lib/slugify.js index 0ff21245f..3b6386de3 100644 --- a/browser/lib/slugify.js +++ b/browser/lib/slugify.js @@ -1,6 +1,17 @@ +import diacritics from 'diacritics-map' + +function replaceDiacritics(str) { + return str.replace(/[À-ž]/g, function(ch) { + return diacritics[ch] || ch; + }); +} + module.exports = function slugify (title) { - return encodeURI(title.trim() - .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '') - .replace(/\s+/g, '-')) - .replace(/\-+$/, '') + let slug = title.trim() + + slug = replaceDiacritics(slug) + + slug = slug.replace(/[^\w\s-]/g, '').replace(/\s+/g, '-') + + return encodeURI(slug).replace(/\-+$/, '') } From 256653677e31302212aee0d252cdd34f16ad64e2 Mon Sep 17 00:00:00 2001 From: Baptiste Augrain Date: Sun, 16 Dec 2018 19:45:18 +0100 Subject: [PATCH 4/4] fix lint errors and remove unused dependencies --- browser/lib/markdown-toc-generator.js | 2 -- browser/lib/slugify.js | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/browser/lib/markdown-toc-generator.js b/browser/lib/markdown-toc-generator.js index 7a97f8009..af1c833f4 100644 --- a/browser/lib/markdown-toc-generator.js +++ b/browser/lib/markdown-toc-generator.js @@ -4,8 +4,6 @@ import { EOL } from 'os' import toc from 'markdown-toc' -import diacritics from 'diacritics-map' -import stripColor from 'strip-color' import mdlink from 'markdown-link' import slugify from './slugify' diff --git a/browser/lib/slugify.js b/browser/lib/slugify.js index 3b6386de3..a3447a901 100644 --- a/browser/lib/slugify.js +++ b/browser/lib/slugify.js @@ -1,9 +1,9 @@ import diacritics from 'diacritics-map' -function replaceDiacritics(str) { - return str.replace(/[À-ž]/g, function(ch) { - return diacritics[ch] || ch; - }); +function replaceDiacritics (str) { + return str.replace(/[À-ž]/g, function (ch) { + return diacritics[ch] || ch + }) } module.exports = function slugify (title) {