{ "info": { "author": "Philip Hodder", "author_email": "philip.hodder@encodis.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Topic :: Text Processing :: Markup", "Topic :: Utilities" ], "description": "# Introduction\n\nFor a while I've been running the excellent [DokuWiki](https://www.dokuwiki.org) on my Mac using OS X's bundled Apache server. The problem is that every time Apple update the OS they futz with the Apache config, so I have to work out how to get it going again. Then I have to update `DokuWiki` itself, as I don't do that nearly as often as I should. Etc, etc.\n\nHowever, it struck me that I don't really need a wiki as such---all I really need for my purposes are inter-page links (within pages in the same folder, usually) and the ability to tag pages and then get lists of pages that match a given set of tags. (This is basically DokuWiki's double bracket syntax for links to another page -- `[[A Page Title]] ` -- and its [tag](https://www.dokuwiki.org/plugin:tag) plugin.) I don't actually need the \"wiki\" bit, as I can easily edit the files locally and compile/deploy as needed. I've also got used to using Markdown rather than DokuWiki's markup (although there is a Markdown plugin for that but it's not Pandoc Markdown, which I prefer... and so on and so on).\n\nSo this project hosts a Python script (`mokuwiki.py`) that takes a source folder of Markdown documents and processes them according to a number of directives, putting the results in a target folder. The files in this target folder can then processed by a Markdown engine (such as [Pandoc](https://pandoc.org)) as usual. For my 'wikis' I usually use the 'single file' mode and Pandoc's standalone option on each file to produce the individual HTML pages (so in that respect it's a bit like part of a static site generator), but you can also run MokuWiki on a single file to take advantage of useful directives like file includes or comments.\n\n> NOTE: Originally I referred to this project as \"fake wiki\" which led to \"mock wiki\", and in a fit of alliterative humour I changed the project to \"mokuwiki\" in homage to *DokuWiki*. This should not be construed as \"mocking\" *DokuWiki*---far from it! *DokuWiki* is a great piece of software---if you need a proper wiki use that, don't use this!\n\n# How it works\n\nMokuWiki makes two key assumptions about the files that it processes:\n\n1. YAML metadata elements in each source file control how it is processed. Most importantly this includes the name of the resulting file in the target folder (the 'title' element, see below). \n2. Directives are processed once to yield Markdown files that will then bprocessed by some other application (the assumption is Pandoc, or something that understands Pandoc flavoured Markdown as that is what MokuWiki emits).\n\n## Metadata\n\nAll YAML metadata elements are passed through to the output files in the target folder unchanged. However, the presence of the following metadata will have the indicated result:\n\n* *title*: The page's title is used to link to it using a 'page link' directive in another page (see below). It is also used to create the file name for that page in the target folder (see [Filename conversion] below). Titles must be unique within the source folder. \n\n* *alias*: Aliases are also used to link to a page as an alternative to using a page's title. This can be useful if the actual title that is to be displayed (the \"formal\" title, if you will) is long but has a common shorter form. Aliases must be unique and not the same as any title.\n\n* *tags*: A YAML sequence of strings that represent what the page is about, e.g. '[vehicle, equipment]'\n\nFor example, if this is the contents of `file1.md`:\n\n```\n---\ntitle: Page One\nalias: 1st Page\nauthor: Phil\ntags: [abc]\n...\n\nA link to [[Page Two]]\n\n```\n\nand this is `file2.md`\n\n```\n---\ntitle: Page Two\nauthor: Phil\ntags: [abc]\n...\n\nA link to [[Page One]]\n\nA link to [[1st Page]]\n\n```\n\nthen MokuWiki will create two files in the target folder. Based on their titles these will be `page_one.md` and `page_two.md` in the target folder. The page link directives (the double square brackets) will become, in `page_two.md` for example:\n\n```\n---\ntitle: Page Two\nauthor: Phil\ntags: [abc]\n...\n\nA link to [Page One](page_one.html)\n\nA link to [1st Page](page_one.html)\n\n```\n\n> NOTE: The YAML metadata block must start with three dashes and end with three periods. \n\n## Directives\n\nThe following directives are supported within a page. These generally take the form of double characters (often brackets) that should be unrecognised by a Markdown processor. \n\n### Page links\n\nAs described above links between pages are specified using double square brackets, so `[[Page One]]` is converted to a standard Markdown link to the HTML version of the page with that title: `[Page One](page_one.html)`. If a page has an alias then that can be used instead of the title, although the link name is still based on the title: `[[1st Page]]` becomes `[1st Page](page_one.html)`. \n\nYou can also define a \"display\" name using the syntax `[[Display Name|Page One]]`. This will become `[Display Name](page_one.html)` in the target file. Note that unlike the similar DokuWiki syntax you cannot specify an actual filename here: that is always determined by the 'title' metadata. \n\nNote that MokuWiki assumes that the eventual output will be HTML, so all of the links end in \".html\".\n\nIf a page does not have a 'title' field in the metadata block (or no metadata block at all) then processing of that file is skipped. The 'title' also cannot contain parentheses or brackets (basically just alpha-numeric characters and some punctuation)---see the section on [Filename Conversion] below.\n\nPage link directives that link to a non-existent page are transformed into bracketed spans with the 'broken' class. That is, `[[No Such Page]]` will be converted to `[No Such Page]{.broken}`. Use the `--broken` command line option to change the class name used for broken links. Use the `--report` command line option to list all broken links (i.e. missing pages) on standard out once processing is complete.\n\n#### Namespaces \n\nPage names can contain references to namespaces, again based on the MoukWiki model, e.g. `[[ns1:Page One]]`. Namespaces are assumed to refer to folders and so cannot contain spaces. How these are incorporated into the resulting link depends on whether the `--fullns` command line option is set:\n\n1. When not set (the default) it assumes that the source folder is the main folder, with a single level of child folders, e.g. \"source/ns1\", \"source/n2\" and so on. A page link with a namespace reference in a page in the folder \"source/ns1\" is assumed to point to a page in a sibling folder. Therefore a page link directive like `[[ns2:Page Two]]` in a document in \"source/ns1\" will convert to `[Page Two](../ns2/page_two.html)`.\n\n2. When `--fullns` is set it will treat a namespace as a full path of folders. The author is then responsible for specifying the correct relative path, e.g. `[[..:..:ns2:ns3:Some Page]]` will become `[Some Page](../../ns2/n3/some_page.html)`.\n\n> NOTE: MokuWiki does **not** recursively process folders and keep track of namespaces. This functionality merely makes it easier to create links between pages in different folders. Note also that this functionality may change in future versions...\n\n### Tag links\n\nTags that have been can be referenced in a page using the following syntax: `{{tag1}}`. This will produce a list of page links that have the \"tag1\" tag. So, for example, a source fragment:\n\n```\nPages containing tag 'abc':\n\n{{abc}}\n```\n\nmight produce:\n\n```\nPages containing tags 'abc':\n\n[Page One](page_one.html)\n\n[Page Two](page_two.html)\n```\n\nTag names cannot contain brackets or punctuation. When being defined in the YAML block tag names can contain spaces, e.g. `tags: [Wordy Tag, Other Tag]`. However, when referencing tags with spaces you must use an underscore instead of a space, e.g. `{{Wordy_Tag +other_tag}}`. Tag names are case-insensitive.\n\nTags can be combined using various operators:\n\n1. `{{tag1 tag2}}` includes pages with 'tag1' *or* 'tag2'\n2. `{{tag1 +tag2}}` includes pages with 'tag1' *and* 'tag2'\n3. `{{tag1 -tag2}}` includes pages with 'tag1' that do *not* have 'tag2'\n4. `{{*}}` includes *all* pages in the wiki that have any tag. Note that pages do not have to have a `tags` fields.\n5. `{{#}}` represents the number of pages that have any tag\n6. `{{#tag1}}` represents the number of pages that have the tag 'tag1'\n7. `{{@}}` will return a list of all tags defined in the source folder as a series of bracketed spans with the class name 'tag'. This can be used to style tag lists. The class name can be changed using the `--tag` command line option.\n\n### Include directives\n\nInclude one file in another using the following markup: `<>`. Any YAML data blocks will be removed from the included file before inclusion. This pattern actually supports globbing, so you can do `<>` and so on. The path is assumed to be relative to the directory that the module was invoked from.\n\nBlank lines will be inserted between the contents of each file, and separators can be inserted between each one by using the syntax `<>`. (The default is no separator, but \"* * *\" is a useful one as it becomes a horizontal rule when processed by `pandoc`. )\n\nA prefix can also be inserted in front of each *line* of the included files by specifying it as a third 'argument'. For example, `< >>` will insert `> ` in front of each line, including the content of the file as a block quote. To do so without a separator between files just leave that argument empty: `< >>`.\n\n### Image links\n\nThe image link directive provides an easier way to link to images: the syntax `!!A Nice Image!!` will be converted to `![A Nice Image](images/a_nice_image.jpg)`. Some points to note include:\n\n1. The name of the link ('A Nice Image' in the example) is also the name of the image's caption.\n2. The default assumes that all images are in an `images` folder which is a child of the folder the referencing file is in. The folder name can be changed with the `--media` command line option. \n3. The default file format assumed is JPEG, therefore the extension is '.jpg'. This can be changed using the following syntax: `!!Another Picture|png!!`.\n4. MoukWiki will not check for the existence of the 'image' folder or move any images into the target folder.\n\n### Exec directives\n\nThe 'exec' directive allows the output of a command can be inserted into the document using the following syntax: `%% ls -l test/*.dat %%`. The command must be in the user's PATH and any file specifications that the directive is to glob must be the last element of the command line (as shown here). Multiple, semi-colon separated commands are supported.\n\n1. This directive uses the [subprocess.run()](https://docs.python.org/3/library/subprocess.html#subprocess.run) function. Therefore [standard security considerations](https://docs.python.org/3.6/library/subprocess.html#security-considerations) should be borne in mind when using this feature.\n2. This feature has not been checked on Windows machines, but should work if executed in the appropriate shell (e.g. Git Bash).\n3. The output of the command should be text suitable for a Markdown file.\n\n### Comment directives\n\nSingle line comments can be included in a source file: any characters on the line that occur after a double slash (`//`) will be removed. There are no block comments. \n\n## Other features\n\n### Single file mode\n\nSingle file mode can be enabled with the `--single` option. Only a single input file is expected and the output file given on the command line is used 'as-is' for the output (i.e. is assumed to be the intended output file name). This is not very useful for page links and tags but can be very handy for using the 'include' and 'exec' directives in the specified input file. The [search index] option is disabled in single file mode.\n\n### Search index\n\nThe optional command line option `--index` will cause MokuWiki to output a JSON file (called '_index.json') which contains an inverted index of terms contained in each page against page titles and file names. This can be used to create a simplistic search function in the \"wiki\". This is in JSON format:\n\n```\n{\n \"page\": [\n [\"page_one\", \"Page One\"],\n [\"page_two\", \"Page Two\"]\n ],\n \"abc\": [\n [\"page_one\", \"Page One\"],\n [\"page_two\", \"Page Two\"]\n ],\n \"one\": [\n [\"page_one\", \"Page One\"]\n ],\n \"two\": [\n [\"page_two\", \"Page Two\"]\n ]\n}\n```\n\nTo include this directly in an HTML page using a `