1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00

Merge pull request #2710 from daiyam/fix-toc

fix toc
This commit is contained in:
Junyoung Choi
2018-12-24 16:41:41 +09:00
committed by GitHub
3 changed files with 49 additions and 48 deletions

View File

@@ -2,51 +2,27 @@
* @fileoverview Markdown table of contents generator * @fileoverview Markdown table of contents generator
*/ */
import { EOL } from 'os'
import toc from 'markdown-toc' import toc from 'markdown-toc'
import diacritics from 'diacritics-map'
import stripColor from 'strip-color'
import mdlink from 'markdown-link' import mdlink from 'markdown-link'
import slugify from './slugify'
const EOL = require('os').EOL const hasProp = Object.prototype.hasOwnProperty
/** /**
* @caseSensitiveSlugify Custom slugify function * From @enyaxu/markdown-it-anchor
* 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
*/ */
function caseSensitiveSlugify (str) { function uniqueSlug (slug, slugs, opts) {
function replaceDiacritics (str) { let uniq = slug
return str.replace(/[À-ž]/g, function (ch) { let i = opts.uniqueSlugStartIndex
return diacritics[ch] || ch while (hasProp.call(slugs, uniq)) uniq = `${slug}-${i++}`
}) slugs[uniq] = true
return uniq
} }
function getTitle (str) { function linkify (token) {
if (/^\[[^\]]+\]\(/.test(str)) { token.content = mdlink(token.content, '#' + token.slug)
var m = /^\[([^\]]+)\]/.exec(str) return token
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
} }
const TOC_MARKER_START = '<!-- toc -->' const TOC_MARKER_START = '<!-- toc -->'
@@ -91,8 +67,23 @@ export function generateInEditor (editor) {
* @returns generatedTOC String containing generated TOC * @returns generatedTOC String containing generated TOC
*/ */
export function generate (markdownText) { export function generate (markdownText) {
const generatedToc = toc(markdownText, {slugify: caseSensitiveSlugify, linkify: linkify}) const slugs = {}
return TOC_MARKER_START + EOL + EOL + generatedToc.content + EOL + EOL + TOC_MARKER_END const opts = {
uniqueSlugStartIndex: 1
}
const result = toc(markdownText, {
slugify: title => {
return uniqueSlug(slugify(title), slugs, opts)
},
linkify: false
})
const md = toc.bullets(result.json.map(linkify), {
highest: result.highest
})
return TOC_MARKER_START + EOL + EOL + md + EOL + EOL + TOC_MARKER_END
} }
function wrapTocWithEol (toc, editor) { function wrapTocWithEol (toc, editor) {

View File

@@ -7,7 +7,6 @@ import _ from 'lodash'
import ConfigManager from 'browser/main/lib/ConfigManager' import ConfigManager from 'browser/main/lib/ConfigManager'
import katex from 'katex' import katex from 'katex'
import { lastFindInArray } from './utils' import { lastFindInArray } from './utils'
import anchor from '@enyaxu/markdown-it-anchor'
function createGutter (str, firstLineNumber) { function createGutter (str, firstLineNumber) {
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 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-imsize'))
this.md.use(require('markdown-it-footnote')) this.md.use(require('markdown-it-footnote'))
this.md.use(require('markdown-it-multimd-table')) this.md.use(require('markdown-it-multimd-table'))
this.md.use(anchor, { this.md.use(require('@enyaxu/markdown-it-anchor'), {
slugify: (title) => { slugify: require('./slugify')
var slug = encodeURI(title.trim()
.replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '')
.replace(/\s+/g, '-'))
.replace(/\-+$/, '')
return slug
}
}) })
this.md.use(require('markdown-it-kbd')) this.md.use(require('markdown-it-kbd'))
this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']}) this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})

17
browser/lib/slugify.js Normal file
View File

@@ -0,0 +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) {
let slug = title.trim()
slug = replaceDiacritics(slug)
slug = slug.replace(/[^\w\s-]/g, '').replace(/\s+/g, '-')
return encodeURI(slug).replace(/\-+$/, '')
}