Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix toc #2710

Merged
merged 4 commits into from
Dec 24, 2018
Merged

fix toc #2710

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 30 additions & 39 deletions browser/lib/markdown-toc-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,27 @@
* @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

/**
* @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 uniqueSlug (slug, slugs, opts) {
let uniq = slug
let i = opts.uniqueSlugStartIndex
while (hasProp.call(slugs, uniq)) uniq = `${slug}-${i++}`
slugs[uniq] = true
return uniq
}

function linkify (tok, text, slug, opts) {
var uniqeID = opts.num === 0 ? '' : '-' + opts.num
tok.content = mdlink(text, '#' + slug + uniqeID)
return tok
function linkify (token) {
token.content = mdlink(token.content, '#' + token.slug)
return token
}

const TOC_MARKER_START = '<!-- toc -->'
Expand Down Expand Up @@ -91,8 +67,23 @@ 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 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) {
Expand Down
11 changes: 2 additions & 9 deletions browser/lib/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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']})
Expand Down
17 changes: 17 additions & 0 deletions browser/lib/slugify.js
Original file line number Diff line number Diff line change
@@ -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(/\-+$/, '')
}