我开始使用标记来做笔记。
我用标记来查看我的笔记,它很漂亮。
但是随着我的笔记变长,我发现很难找到我想要的东西。
我知道markdown可以创建表,但它是否能够创建目录,跳转到部分,或定义页面部分markdown?
或者,是否有降价阅读器/编辑器可以做这些事情。搜索也是一个不错的功能。
简而言之,我想让它成为我很棒的笔记工具,功能就像写一本书一样。
我开始使用标记来做笔记。
我用标记来查看我的笔记,它很漂亮。
但是随着我的笔记变长,我发现很难找到我想要的东西。
我知道markdown可以创建表,但它是否能够创建目录,跳转到部分,或定义页面部分markdown?
或者,是否有降价阅读器/编辑器可以做这些事情。搜索也是一个不错的功能。
简而言之,我想让它成为我很棒的笔记工具,功能就像写一本书一样。
当前回答
基于albertodebortoli answer创建了附加检查和标点符号替换功能。
# @fn def generate_table_of_contents markdown # {{{
# @brief Generates table of contents for given markdown text
#
# @param [String] markdown Markdown string e.g. File.read('README.md')
#
# @return [String] Table of content in markdown format.
#
def generate_table_of_contents markdown
table_of_contents = ""
i_section = 0
# to track markdown code sections, because e.g. ruby comments also start with #
inside_code_section = false
markdown.each_line do |line|
inside_code_section = !inside_code_section if line.start_with?('```')
forbidden_words = ['Table of contents', 'define', 'pragma']
next if !line.start_with?('#') || inside_code_section || forbidden_words.any? { |w| line =~ /#{w}/ }
title = line.gsub("#", "").strip
href = title.gsub(/(^[!.?:\(\)]+|[!.?:\(\)]+$)/, '').gsub(/[!.,?:; \(\)-]+/, "-").downcase
bullet = line.count("#") > 1 ? " *" : "#{i_section += 1}."
table_of_contents << " " * (line.count("#") - 1) + "#{bullet} [#{title}](\##{href})\n"
end
table_of_contents
end
其他回答
如果IntelliJ用户do:,命令n或控件n提供创建或更新目录的选项。参考资料:阅读此处
有一个Ruby脚本叫做mdtoc。rb可以自动生成一个GFM Markdown目录,它与这里发布的其他一些脚本相似,但略有不同。
给定一个输入Markdown文件如下:
# Lorem Ipsum
Lorem ipsum dolor sit amet, mei alienum adipiscing te, has no possit delicata. Te nominavi suavitate sed, quis alia cum no, has an malis dictas explicari. At mel nonumes eloquentiam, eos ea dicat nullam. Sed eirmod gubergren scripserit ne, mei timeam nonumes te. Qui ut tale sonet consul, vix integre oportere an. Duis ullum at ius.
## Et cum
Et cum affert dolorem habemus. Sale malis at mel. Te pri copiosae hendrerit. Cu nec agam iracundia necessitatibus, tibique corpora adipisci qui cu. Et vix causae consetetur deterruisset, ius ea inermis quaerendum.
### His ut
His ut feugait consectetuer, id mollis nominati has, in usu insolens tractatos. Nemore viderer torquatos qui ei, corpora adipiscing ex nec. Debet vivendum ne nec, ipsum zril choro ex sed. Doming probatus euripidis vim cu, habeo apeirian et nec. Ludus pertinacia an pro, in accusam menandri reformidans nam, sed in tantas semper impedit.
### Doctus voluptua
Doctus voluptua his eu, cu ius mazim invidunt incorrupte. Ad maiorum sensibus mea. Eius posse sonet no vim, te paulo postulant salutatus ius, augue persequeris eum cu. Pro omnesque salutandi evertitur ea, an mea fugit gloriatur. Pro ne menandri intellegam, in vis clita recusabo sensibus. Usu atqui scaevola an.
## Id scripta
Id scripta alterum pri, nam audiam labitur reprehendunt at. No alia putent est. Eos diam bonorum oportere ad. Sit ad admodum constituto, vide democritum id eum. Ex singulis laboramus vis, ius no minim libris deleniti, euismod sadipscing vix id.
它生成了这个目录:
$ mdtoc.rb FILE.md
#### Table of contents
1. [Et cum](#et-cum)
* [His ut](#his-ut)
* [Doctus voluptua](#doctus-voluptua)
2. [Id scripta](#id-scripta)
请参阅我关于这个主题的博客文章。
基于albertodebortoli answer创建了附加检查和标点符号替换功能。
# @fn def generate_table_of_contents markdown # {{{
# @brief Generates table of contents for given markdown text
#
# @param [String] markdown Markdown string e.g. File.read('README.md')
#
# @return [String] Table of content in markdown format.
#
def generate_table_of_contents markdown
table_of_contents = ""
i_section = 0
# to track markdown code sections, because e.g. ruby comments also start with #
inside_code_section = false
markdown.each_line do |line|
inside_code_section = !inside_code_section if line.start_with?('```')
forbidden_words = ['Table of contents', 'define', 'pragma']
next if !line.start_with?('#') || inside_code_section || forbidden_words.any? { |w| line =~ /#{w}/ }
title = line.gsub("#", "").strip
href = title.gsub(/(^[!.?:\(\)]+|[!.?:\(\)]+$)/, '').gsub(/[!.,?:; \(\)-]+/, "-").downcase
bullet = line.count("#") > 1 ? " *" : "#{i_section += 1}."
table_of_contents << " " * (line.count("#") - 1) + "#{bullet} [#{title}](\##{href})\n"
end
table_of_contents
end
对于Visual Studio Code用户来说,今天(2020年)使用的最佳选择是Markdown All in One插件(扩展)。
要安装它,启动VS Code快速打开(Control/⌘+P),粘贴以下命令,并按enter。
ext install yzhang.markdown-all-in-one
要生成TOC,打开命令面板(Control/⌘+Shift+P),并选择select Markdown:创建内容表选项。
另一个选择是Markdown TOC插件。
要安装它,启动VS Code快速打开(Control/⌘+P),粘贴以下命令,并按enter。
ext install markdown-toc
要生成TOC,打开命令面板(Control/⌘+Shift+P),并选择Markdown TOC:插入/更新选项或使用Control/⌘+MT。
这是一个小的nodejs脚本,它生成目录,并考虑重复的标题:
const fs = require('fs')
const { mdToPdf } = require('md-to-pdf');
const stringtoreplace = '<toc/>'
const processTitleRepetitions = (contents, titleMap) => {
for (const content of contents) {
titleMap[content.link] = typeof titleMap[content.link] === 'undefined'
? 0
: titleMap[content.link] + 1
if (titleMap[content.link] > 0) {
content.link = `${content.link}-${titleMap[content.link]}`
}
}
}
const convertContentToPdf = async (targetFile) => {
const pdf = await mdToPdf({path: targetFile}).catch(console.error)
if(pdf) {
const pdfFile = `${targetFile.replace(/\.md/, '')}.pdf`
fs.writeFileSync(pdfFile, pdf.content)
return pdfFile
}
throw new Error("PDF generation failed.")
}
const generateTOC = (file, targetFile) => {
// Extract headers
const fileContent = fs.readFileSync(file, 'utf-8')
const titleLine = /((?<=^)#+)\s(.+)/
const contents = fileContent.split(/\r?\n/).
map(line => line.match(titleLine)).
filter(match => match).
filter(match => match[1].length > 1).
map(regExpMatchArray => {
return {
level: regExpMatchArray[1].length, text: regExpMatchArray[2],
link: '#' + regExpMatchArray[2].replace(/(\s+|[.,\/#!$%^&*;:{}=\-_`~()]+)/g, '-').toLowerCase(),
}
})
const titleMap = {}
processTitleRepetitions(contents, titleMap)
// Write content
let toctext = '## Table of Contents\n'
// Find the toplevel to adjust the level of the table of contents.
const topLevel = contents.reduce((maxLevel, content) => Math.min(content['level'], maxLevel), 1000)
levelCounter = {}
contents.forEach(item => {
let currentLevel = parseInt(item.level)
levelCounter[currentLevel] = levelCounter[currentLevel] ? levelCounter[currentLevel] + 1 : 1
Object.entries(levelCounter).forEach(e => {
if(currentLevel < parseInt(e[0])) {
levelCounter[e[0]] = 0
}
})
const level = Array(currentLevel - topLevel).fill('\t').join('')
const text = `${levelCounter[currentLevel]}. [${item['text']}](${item['link']}) \n`
toctext += level + text
})
const updatedContent = fileContent.toString().replace(stringtoreplace, toctext)
fs.writeFileSync(targetFile, updatedContent)
convertContentToPdf(targetFile).then((pdfFile) => {
console.info(`${pdfFile} has been generated.`)
})
}
const args = process.argv.slice(2)
if(args.length < 2) {
console.error("Please provide the name of the markdown file from which the headers should be extracted and the name of the file with the new table of contents")
console.info("Example: node MD_TOC.js <source_md> <target_md>")
process.exit(1)
}
const source_md = args[0]
const target_md = args[1]
generateTOC(source_md, target_md)
要使用它,您需要在markdown文件中注入<toc/>。
下面是你如何使用它:
generateTOC('../README.md', '../README_toc.md')
第一个参数是源markdown文件,第二个参数是带有markdown的文件。