我开始使用标记来做笔记。

我用标记来查看我的笔记,它很漂亮。

但是随着我的笔记变长,我发现很难找到我想要的东西。

我知道markdown可以创建表,但它是否能够创建目录,跳转到部分,或定义页面部分markdown?

或者,是否有降价阅读器/编辑器可以做这些事情。搜索也是一个不错的功能。

简而言之,我想让它成为我很棒的笔记工具,功能就像写一本书一样。


当前回答

只需使用带有插件的文本编辑器。

你的编辑器很可能有一个包/插件来为你处理这个问题。例如,在Emacs中,可以安装markdown-toc TOC生成器。然后在编辑时,只需反复调用M-x markdown-toc-generate-or-refresh-toc。如果你想经常这样做,那就值得一个键绑定。它擅长生成一个简单的TOC,而不会用HTML锚污染您的文档。

其他编辑器也有类似的插件,所以流行的列表是这样的:

器name: markdown-toc Vim: markdown-toc Atom: markdown-toc VSCode: markdown-toc

其他回答

MultiMarkdown Composer似乎生成了一个目录来辅助编辑。

也可能存在这样或那样的库,它们可以生成TOC:参见Python Markdown TOC扩展。

这是一个小的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的文件。

你可以使用DocToc从命令行生成目录:

doctoc /path/to/file

要使链接与Bitbucket生成的锚点兼容,请使用——Bitbucket参数运行它。

您可以尝试使用这个ruby脚本从标记文件生成TOC。

 #!/usr/bin/env ruby

require 'uri'

fileName = ARGV[0]
fileName = "README.md" if !fileName

File.open(fileName, 'r') do |f|
  inside_code_snippet = false
  f.each_line do |line|
    forbidden_words = ['Table of contents', 'define', 'pragma']
    inside_code_snippet = !inside_code_snippet if line.start_with?('```')
    next if !line.start_with?("#") || forbidden_words.any? { |w| line =~ /#{w}/ } || inside_code_snippet

    title = line.gsub("#", "").strip
    href = URI::encode title.gsub(" ", "-").downcase
    puts "  " * (line.count("#")-1) + "* [#{title}](\##{href})"
  end
end

对我来说,@Tum提出的解决方案对于2个层次的目录来说非常有效。然而,对于第3个关卡,这种方法却不起作用。它没有像前两层那样显示链接,而是显示纯文本3.5.1。[bla blabla](#blablabla) <br>代替。

我的解决方案是@Tum解决方案(非常简单)的补充,适用于需要3级或以上目录的人。

在第二层,一个简单的制表符将为您正确地完成缩进。但它不支持2个标签。相反,你必须使用一个标签,并添加尽可能多的&nbsp;根据你自己的需要来正确对齐第三层。

下面是一个使用4个关卡的例子(关卡越高,它就变得越糟糕):

# Table of Contents
1. [Title](#title) <br>
    1.1. [sub-title](#sub_title) <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.1.1. [sub-sub-title](#sub_sub_title)
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.1.1.1. [sub-sub-sub-title](#sub_sub_sub_title)

# Title <a name="title"></a>
Heading 1

## Sub-Title <a name="sub_title"></a>
Heading 2

### Sub-Sub-Title <a name="sub_sub_title"></a>
Heading 3

#### Sub-Sub-Sub-Title <a name="sub_sub_sub_title"></a>
Heading 4

这将给出以下结果,其中目录表的每个元素都是到其相应部分的链接。还要注意<br>,以便添加新行,而不是在同一行上。

目录

标题 1.1. 字幕 1.1.1。Sub-Sub-Title                   1.1.1.1。Sub-Sub-Sub-Title

标题

标题1

字幕

标题2

Sub-Sub-Title

标题3

Sub-Sub-Sub-Title

标题4