转换标记文档的文件夹,用标记链接和列表替换页间链接和标记标记

mokuwiki的Python项目详细描述


简介

一段时间以来,我一直在我的Mac电脑上使用OS X捆绑的Apache服务器运行优秀的Dokuwiki。问题是,每次苹果用apache配置更新操作系统时,他们都会使用futz,所以我必须想办法让它重新运行。然后我必须更新dokuwiki本身,因为我没有像应该的那样经常更新。等等,等等。

然而,让我吃惊的是,我并不真的需要这样的wiki——我真正需要的只是页面间的链接(通常在同一个文件夹中的页面内),以及标记页面,然后获取与给定标记集匹配的页面列表的能力。(这基本上是dokuwiki的双括号语法,用于链接到另一个页面--[[a page title]]--以及它的标记插件。)我实际上不需要"wiki"位,因为我可以轻松地在本地编辑文件并编译/部署为需要。我也已经习惯了使用markdown而不是dokuwiki的标记(虽然有一个markdown插件,但它不是pandoc markdown,我更喜欢这个……等等)。

因此,这个项目托管了一个python脚本(mokuwiki.py),它接受一个标记文档的源文件夹,并根据许多指令对其进行处理,将结果放在一个目标文件夹中。然后,目标文件夹中的文件可以像往常一样由降价引擎(例如pandoc)处理。对于我的"wiki",我通常在每个文件上使用"单个文件"模式和pandoc的独立选项来生成单独的html页面(因此在这方面,它有点像静态站点生成器的一部分),但是也可以在单个文件上运行mokuwiki来利用诸如file这样的有用指令包括或评论。

< Buff行情>

注:最初我把这个项目称为"假维基",这导致了"假维基",在一段头韵式的幽默中,我把这个项目改为"mokuwiki",以表示对dokuwiki的敬意。这不应该被理解为"嘲笑"dokuwiki---远远不是!dokuwiki是一个很棒的软件——如果你需要一个合适的wiki使用它,不要使用它!

工作原理

mokuwiki对它处理的文件做了两个关键假设:

  1. 每个源文件中的yaml元数据元素控制如何处理它。最重要的是,这包括目标文件夹中结果文件的名称("title"元素,见下文)。
  2. 指令被处理一次以产生降价文件,然后由其他应用程序处理(假设是pandoc,或者理解pandoc风格的降价,因为这是mokuwiki发出的)。

元数据

所有yaml元数据元素都将以不变的方式传递到目标文件夹中的输出文件。但是,如果存在以下元数据,则会得到指定的结果:

  • title:页面标题用于在另一个页面中使用"页面链接"指令链接到该页面(请参见下文)。它还用于在目标文件夹中创建该页的文件名(请参见下面的[文件名转换])。标题在源文件夹中必须是唯一的。

  • 别名:别名还用于链接到页面,作为使用页面标题的替代方法。如果要显示的实际标题("正式"标题,如果您愿意的话)很长,但有一个通用的较短格式,那么这一点非常有用。别名必须是唯一的,不能与任何标题相同。

  • 标记:表示页面内容的字符串的yaml序列,例如,"[车辆,设备]"

例如,如果这是file1.md的内容

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

这里是file2.md

---
title: Page Two
author: Phil
tags: [abc]
...

A link to [[Page One]]

A link to [[1st Page]]

然后mokuwiki将在目标文件夹中创建两个文件。根据标题,这些将是page_one.md第二页。md在目标文件夹中。页面链接指令(双方括号)将变为,inpage\u two.md例如:

---
title: Page Two
author: Phil
tags: [abc]
...

A link to [Page One](page_one.html)

A link to [1st Page](page_one.html)

< Buff行情>

注意:yaml元数据块必须以三个破折号开头,以三个句点结尾。

指令

页面中支持以下指令。这些字符通常采用双字符(通常是括号)的形式,降价处理器应该无法识别这些字符。

页面链接

如上所述,页面之间的链接使用双方括号指定,因此[[page one]]将转换为指向该标题为[page one](page_one.html)的页面的HTML版本的标准标记链接。如果页面有别名,则可以使用别名代替标题,尽管链接名称仍基于标题:[[1st page]]变为[1st page](page_one.html)

您还可以使用语法[[display name page one]]定义"display"名称。这将成为目标文件中的[显示名称](page_one.html)。注意,与类似的dokuwiki语法不同,您不能在这里指定实际的文件名:它总是由"title"元数据决定。

请注意,mokuwiki假定最终输出为html,因此所有链接都以".html"结尾。

如果页面的元数据块中没有"title"字段(或根本没有元数据块),则跳过对该文件的处理。"title"也不能包含圆括号或方括号(基本上只有字母数字字符和一些标点符号)--请参阅下面关于[文件名转换]的部分。

链接到不存在的页的页链接指令将转换为带"breaked"类的括号跨距。也就是说,[[没有这样的页面]]将转换为[没有这样的页面]{.broken}。使用--broken命令行选项更改用于断开链接的类名。处理完成后,使用--report命令行选项列出标准输出上所有断开的链接(即丢失的页面)。

命名空间

页面名称可以包含对名称空间的引用,同样基于moukwiki模型,例如[[ns1:page on e]]。假定命名空间引用文件夹,因此不能包含空格。如何将它们合并到结果链接中取决于是否设置了--fullns命令行选项:

  1. 如果未设置(默认设置),则假定源文件夹是主文件夹,具有单个级别的子文件夹,例如"source/ns1"、"source/n2"等。假定文件夹"source/ns1"中页面中具有命名空间引用的页面链接指向同级文件夹中的页面。因此,像"source/ns1"中文档中的[[ns2:page two]]这样的页面链接指令将转换为[page two](../ns2/page\u two.html)

  2. 当设置了--fullns时,它将把命名空间视为文件夹的完整路径。然后,作者负责指定正确的相对路径,例如[[…:..:ns2:ns3:some page]将变为[some page](../../ns2/n3/some廑page.html)

< Buff行情>

注意:mokuwiki不会递归地处理文件夹并跟踪名称空间。此功能只会使在不同文件夹中的页面之间创建链接变得更容易。还请注意,此功能可能会在以后的版本中更改…

标记链接

可以使用以下语法在页中引用的标记:{{tag1}}。这将生成包含"tag1"标记的页面链接列表。例如,一个源片段:

Pages containing tag 'abc':

{{abc}}

可能产生:

Pages containing tags 'abc':

[Page One](page_one.html)

[Page Two](page_two.html)

标记名不能包含方括号或标点符号。在yaml块中定义时,标记名可以包含空格,例如标记:[wordy tag,other tag]。然而,W引用带有空格的标记时,必须使用下划线而不是空格,例如{{{wordy_tag+other_tag}。标记名不区分大小写。

可以使用各种运算符组合标记:

  1. {{tag1 tag2}包括带有"tag1"或"tag2"的页
  2. {{tag1+tag2}包括带有"tag1"和"tag2"的页
  3. {{tag1-tag2}包括带有"tag1"但不具有"tag2"的页
  4. {{*}包含wiki中所有具有任何标记的页面。请注意,页面不必有标记字段。
  5. {{{}}表示具有任何标记的页数
  6. {{tag1}表示具有标记"tag1"的页数
  7. {{@}将返回源文件夹中定义的所有标记的列表,这些标记是一系列以类名称"tag"括起来的跨距。这可用于设置标记列表的样式。可以使用--tag命令行选项更改类名。

包含指令

使用以下标记将一个文件包含在另一个文件中:<;<;include\me.md>;。任何yaml数据块都将在包含之前从包含的文件中删除。此模式实际上支持全局搜索,因此您可以执行<;<;include_x*y.dat>;等操作。假定路径是相对于调用模块的目录的。

将在每个文件的内容之间插入空行,并且可以使用语法<;<;include_x*y.dat**>;在每个文件之间插入分隔符。(默认值为无分隔符,但"***"是一个有用的分隔符,因为当由pandoc处理时,它变成了一个水平规则)

通过将前缀指定为第三个"参数",还可以在包含的文件的每个行的前面插入前缀。例如,<;<;include_x*y.dat**>;>;将在每行前面插入>;,包括文件内容作为块引号。若要在文件之间不使用分隔符,请将该参数保留为空:<;<;include_x*y.dat_124;gt;>;

图像链接

image link指令提供了一种更容易链接到图像的方法:语法!!好形象!!将转换为![漂亮的图像](images/a_nice_image.jpg)。注意事项包括:

  1. 链接的名称(示例中的"漂亮图像")也是图像标题的名称。
  2. 默认情况下,所有图像都位于images文件夹中,该文件夹是引用文件所在文件夹的子文件夹。可以使用--media命令行选项更改文件夹名。
  3. 假定默认文件格式为JPEG,因此扩展名为".jpg"。这可以使用以下语法进行更改:!!另一张图片png!!
  4. Moukwiki不会检查"图像"文件夹是否存在,也不会将任何图像移动到目标文件夹。

执行指令

"exec"指令允许使用以下语法将命令的输出插入到文档中:%%ls-l test/*.dat%。命令必须在用户的路径中,并且该指令要glob的任何文件规范都必须是命令行的最后一个元素(如下所示)。支持多个分号分隔的命令。

  1. 此指令使用子流程函数。因此,在使用此功能时,应牢记标准的安全注意事项。
  2. 此功能尚未在Windows计算机上检查,但如果在适当的shell(例如git bash)中执行,则应该可以工作。
  3. 的输出该命令应为适合标记文件的文本。

注释指令

源文件中可以包含单行注释:行中双斜杠(//)之后出现的任何字符都将被删除。没有块注释。

其他功能

单文件模式

使用--single选项可以启用单文件模式。只需要一个输入文件,命令行中给出的输出文件将按原样用于输出(即假定为预期的输出文件名)。这对于页面链接和标记不是很有用,但是对于在指定的输入文件中使用"include"和"exec"指令非常方便。在单文件模式下,[搜索索引]选项被禁用。

搜索索引

可选的命令行选项--index将导致mokuwiki输出一个json文件(称为''u index.json'),该文件包含每个页面中包含的术语相对于页面标题和文件名的反向索引。这可以用来在"wiki"中创建一个简单的搜索功能。这是json格式:

{
    "page": [
        ["page_one", "Page One"],
        ["page_two", "Page Two"]
    ],
    "abc": [
        ["page_one", "Page One"],
        ["page_two", "Page Two"]
    ],
    "one": [
        ["page_one", "Page One"]
    ],
    "two": [
        ["page_two", "Page Two"]
    ]
}

要使用<;script>;语句将其直接包含在html页面中,通常可以方便地将其声明为变量。使用--prefix选项在json前面加一个字符串。例如,作者在其中一个项目上使用了--prefix='var mw=mw{};mw.searchindex='

搜索索引字段

默认情况下,将分析以下yaml元数据字段以创建搜索索引:"title"、"alias"、"summary"、"tags"和"keywords"。将元数据字段"noindex"设置为"true"的源文件将被索引。使用--fields选项指定不同的列表,例如--fields='title,author'

文件的内容(即正文文本,元数据之后)可以通过使用名为\u body/code>的"伪字段"进行索引。所有标点符号等都从索引项中删除。

噪音词

默认情况下,mokuwiki中包含一小部分"噪音词"。如果它们出现在任何选定的元数据字段中,则不会编制索引。可以使用--noise选项更改列表,以提供一个包含单词的纯文本文件,每行一个单词。例如,--noise=bad_words.txt

文件名转换

从"title"字段创建目标文件名,如下所示:去掉前导和后面的空格,用下划线替换剩余的空格,并使整个字符串小写。Unicode字符也会被删除。

安装

由于mokuwiki可以在pypi上找到,所以安装应该简单到:

$ pip install mokuwiki

mokuwiki依赖于pyyaml。有些单元测试依赖于deepdiff

用法

安装后mokuwiki应作为命令行脚本提供:

$ mokuwiki source-dir target-dir

或者它可以作为标准的python模块运行:

$ python -m mokuwiki source-dir target-dir

使用"mokuwiki()"函数在python解释器中运行:

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

0

对所有选项运行mokuwiki--help

注意事项

  1. 不能有两个标题/别名相同的页面(对于Wiki来说,这实际上是有意义的)。
  2. mokuwiki仅将指令标记转换为等效的标记——将任何其他功能添加到生成的html中必须通过一个pandoc模板或类似的机制来完成。应保留常规标记语法。
  3. 这是作为我的第一个python项目之一开始的,所以大部分都是从堆栈溢出答案中拼凑出来的。它也主要是为我的特殊需要而设计的,尽管我试着尽可能地概括它。似乎可以正常工作,但如果没有仔细考虑,我不会在生产中使用它…

待办事项

  1. 更好的错误处理。
  2. 更有效的文件I/O。当前每个文件都被读取一次以创建索引,然后它们都被再次读取,以便可以解析标记链接。也许有一种更有效的方法可以使用数据库或其他一些新的工具来实现这一点,但是在测试中,与"转换为HTML"步骤相比,脚本运行所需的时间可以忽略不计。
  3. 用基于dokuwiki的模型替换当前的名称空间机制。
  4. 将处理特殊标记字符(例如"{{@}")的复杂逻辑替换为更优雅的逻辑。

开发说明

单元测试

许多单元测试包含在tests文件夹中,可以使用pytest应用程序运行。

包装配送

当准备发布时,使用bumpversion应用程序更新版本号,例如

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

1

这将更新源文件和安装配置。然后构建分发版:

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

2

测试安装

使用Docker可以完成正确安装分发的测试。使用以下命令(如有必要,将下载"python"docker映像,因此第一次运行时可能需要几分钟):

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

3

这将启动"python"docker映像并执行命令提示符。从这里安装本地"dist"文件夹中的"mokuwiki"发行版(安装在"/mnt"下的docker映像中)。请注意,必须首先安装依赖项(pyyaml),因为指定了"-no index"。

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

4

上传到testpypi

将发行版上载到testpypi站点:

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

5

然后运行"python"docker映像并尝试从那里安装:

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

6

上传到pypi

按如下方式上载到实际包索引(或指定最新分发版):

---
title: Page One
alias: 1st Page
author: Phil
tags: [abc]
...

A link to [[Page Two]]

7

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何拆分字符串(基于各种分隔符),但不保留空格?   解析。Json格式的txt文件和knime中的java   java Spring rest api为什么在rest api调用的响应中更改了数据类型   升华文本3抛出java。lang.ClassNotFoundException,而记事本++不存在   java Android指纹扫描仪在尝试5次后停止工作?   java Android如何设置精确的重复报警?   java如何使用HTTPGET connect为access API输入用户名和密码   java当测试报告显示没有测试失败时,Gradle为什么说“有失败的测试”?   用Gson实现java获取响应   MapReduce程序中函数错误的java不可映射参数   java spring安全性不符合自动代理的条件   java GWT使用异步回调进行同步/阻塞调用   java奇怪的类数组问题无法在jsp中显示   如何在java中使用PrinterJob使用epl打印条形码   java如何在JTable中居中单元格   将Java Mockito测试转换为Kotlin   html Java正则表达式模式匹配到多个相同标记   testCompile中缺少java Gradle(Android)多项目依赖项   在输入提示后输入字符串时发生java FileNotFoundException