Last active
May 19, 2024 23:33
-
-
Save johnd0e/7d00f4d8899ec9920b2b84ceed4a6e02 to your computer and use it in GitHub Desktop.
Makefile for documents converting using pandoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HelpDown Makefile scripts | |
------------------------- | |
Предлагается [система сборки документации][HelpDown Makefile scripts] | |
в различных форматах (__.hlf__, __.html__, и __.md__ для форума) | |
из единого источника на базе Markdown. | |
Система представляет собой базовый `Makefile`, и несколько lua-скриптов ("фильтров"), | |
необходимых для тонкой настройки вывода. | |
Предполагается использовать это наподобие конструктора: для каждого проекта создаётся свой локальный `Makefile`, | |
в котором подключается базовый, и указываются необходимые фильтры (имеющиеся в наборе, либо добавленные локально). | |
Требования: | |
- [pandoc] | |
- [HtmlToFarHelp] (или прямая ссылка на [файл пакета][nupkg]) | |
- [make] или `winget install ezwinports.make` | |
- `Makefile` + cкрипты из данного репозитория. Или [архив](https://gist.github.com/johnd0e/7d00f4d8899ec9920b2b84ceed4a6e02/archive/master.zip). | |
Для чего же нужны фильтры, приведу лишь несколько примеров: | |
- Для презентации какого-либо скрипта на форуме его документацию стоит специально подготовить, в частности: | |
<details> | |
- Поместить все разделы кроме первого в спойлеры, чтобы сэкономить место в посте. | |
- Исправить форматирование при наличии одиночного `*`, поскольку стандартный способ экранирования слешем на форуме не работает. | |
- _DefinitionList_ ([Description List]) не является стандартной фичей маркдауна, его надо заменить на _BulletList_. | |
- Преобразование ссылок: | |
- Движок форума не создаёт внутренние ссылки, поэтому их надо убрать (заменить на просто жирный текст). | |
- Ссылки на справку фара работают только в __hlf__. А в __html__ и _для форума_ их надо заменять на что-то более полезное. | |
- Аналогично со ссылками на локальные __\*.chm__ и пр. | |
</details> | |
Никто в здравом уме не станет сам с этим возиться, но если всё автоматически, то [почему бы и нет][BufferScroll]. | |
- Для __html__ полезно Title не оставлять пустой, а продублировать туда первый Header. | |
- Для __hlf__ -- сформировать индекс справки, и в каждый раздел добавить перекрёстные ссылки на другие | |
(например в верхнем блоке как в справке [LuaCheck]. Или в нижнем, как в [BufferScroll]). | |
Чтобы подключить всё это к своему проекту достаточно `Makefile` подобного примеру в `Makefile.sample`. | |
Всё, теперь при наличии исходного документа в файле с расширением __\*.text__ достаточно запустить команду `make` для создания __\*.hlf__. | |
Или же явно указать цель: `make hlf`, `make html`, `make forum`. | |
В качестве цели также может быть указано имя результирующего файла. | |
[HelpDown Makefile scripts]: https://gist.github.com/7d00f4d8899ec9920b2b84ceed4a6e02 | |
[pandoc]: https://pandoc.org/installing.html | |
[HtmlToFarHelp]: https://www.nuget.org/packages/HtmlToFarHelp | |
[nupkg]: https://www.nuget.org/api/v2/package/HtmlToFarHelp/ | |
[make]: https://sourceforge.net/projects/ezwinports/files/ | |
[Description List]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl | |
[BufferScroll]: https://forum.farmanager.com/viewtopic.php?t=8675 | |
[LuaCheck]: https://forum.farmanager.com/viewtopic.php?f=15&t=9650 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- For hlf: | |
-- Make index page (out of pandoc-generated toc) | |
-- Add refs-block ("other help sections") to each article. | |
-- requires: meta.refsTemplate and --toc | |
-- optional: meta.refsLevel | |
--luacheck: globals Refs meta | |
local function Pandoc (doc) | |
meta = doc.meta | |
if not meta.refsTemplate then | |
--print("addRefs: no refsTemplate, exiting") | |
return | |
end | |
local insertRefs = require(meta.refsTemplate[1].text) | |
if not insertRefs then | |
return | |
end | |
-- add Index section | |
local toc = pandoc.structure.table_of_contents(doc.blocks):walk{Link=function(el) | |
el.attr = pandoc.Attr() -- remove auto-id's "toc-title" | |
return el | |
end} | |
doc.blocks:insert(pandoc.Header(1, "Index", pandoc.Attr("index", nil, {refsTitle="i"}))) | |
doc.blocks:insert(toc) | |
-- | |
Refs = pandoc.List{} -- list of linked articles | |
local refsLevel = meta.refsLevel | |
refsLevel = not refsLevel and 1 or refsLevel[1] and tonumber(refsLevel[1].text) | |
doc.blocks:walk { -- for refs pick all Headers with level<=meta.refsLevel (default 1) | |
Header=function(el) | |
if el.identifier~="" and not el.classes:includes("noref") then | |
if refsLevel and refsLevel<el.level then return end | |
local content, title = el.content | |
if el.attributes.refsTitle then | |
title = pandoc.utils.stringify(content) | |
content = el.attributes.refsTitle | |
end | |
Refs:insert(pandoc.Link(content, el.identifier, title)) | |
end | |
end | |
} | |
-- | |
require"sections"(doc.blocks, insertRefs) | |
return doc | |
end | |
return { | |
{ Pandoc=Pandoc }, | |
{ Div=function(el) return el.content end }, -- HtmlToFarHelp does not support Divs | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Make links to chm possible (in hlf) | |
function Link(el) | |
if el.target:match("^mk:@MSITStore:") then | |
el.target = "start hh "..el.target | |
return el | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- transform DL to BulletList | |
function DefinitionList(el) | |
local items = {} | |
for i,item in ipairs(el.content) do | |
local dt,blocks = table.unpack(item) --term,definitions | |
local first = blocks[1] | |
items[i] = first | |
for j=2,#blocks do | |
first:extend(blocks[j]) | |
end | |
dt:extend{pandoc.Str" "} --actually needed not for gfm but for some other flavors | |
first:insert(1,pandoc.Plain(dt)) | |
end | |
return pandoc.BulletList(items) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- forum: replace <details> with bbcode [spoiler] tag | |
function RawBlock (el) | |
if el.format=="html" then | |
if el.text:match"</?details>" then | |
-- todo <summary> | |
return pandoc.RawBlock("markdown",el.text:gsub("<","["):gsub(">","]"):gsub("details","spoiler")) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Make links to Far own help more useful (in md, html) | |
function Link(el) | |
if el.target:match("^:%w+") then | |
el.target = "hlf"..el.target | |
if el.title=="" then | |
el.title = "See Far help, "..el.target | |
end | |
return el | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Save space wrapping all (except first) sections content inside spoilers | |
-- Sections with header level > meta.foldLevel (when specified) will be absorbed | |
local function wrapSection (blocks, startIdx, endIdx) | |
-- transform headers into plain (but formatted) text | |
blocks[startIdx] = pandoc.Para { | |
pandoc.RawInline("markdown", "[u]"), | |
pandoc.Strong(blocks[startIdx].content), | |
pandoc.RawInline("markdown","[/u]") | |
} | |
blocks[startIdx].content:insert(pandoc.RawInline("markdown", " [spoiler]")) | |
blocks:insert(endIdx, pandoc.RawBlock("markdown", "[/spoiler]")) | |
return endIdx+1 | |
end | |
local first = true | |
return { | |
{ | |
Header=function(el) | |
if first then -- remove redundant first header, as forum topic already has own title | |
first = false | |
return {} | |
end | |
if el.classes:includes("noref") then --e.g. cfgscript note | |
return pandoc.HorizontalRule() | |
end | |
end | |
}, { -- add spoilers | |
Pandoc=function(doc) | |
local foldLevel = doc.meta.foldLevel | |
foldLevel = foldLevel and tonumber(foldLevel[1].text) | |
require"sections"(doc.blocks, wrapSection, function (header) | |
if foldLevel and header.level>foldLevel then | |
return "absorb" | |
end | |
end) | |
return doc | |
end | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- phpBB3 uses own markdown parser (https://s9etextformatter.readthedocs.io/Plugins/Litedown/Syntax/), | |
-- which differs in some minor details. That's why some fixes needed. | |
function Str (el) | |
-- normal way of escaping the asterisk is \*, but that does not work in Litedown. | |
if el.text=="*" then | |
return pandoc.RawInline("markdown","[i]*[/i]") | |
end | |
end | |
function Link (el) | |
-- replace by Emph because forum engine fails to parse such links | |
if el.target:match"^:" then | |
return pandoc.Emph(el.content) | |
end | |
-- remove links as forum engine does not create anchors for headers. | |
if el.target:match"^#" then | |
return pandoc.Strong(el.content) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Grab first header as title, but only if no explicit metadata specified (yaml) | |
local title | |
function Header(el) | |
if title then return end | |
title = pandoc.utils.stringify(el) | |
end | |
function Meta(el) | |
if not el.pagetitle then | |
el.pagetitle = title | |
return el | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ifeq (1,$(words $(MAKEFILE_LIST))) # if not included | |
.DEFAULT_GOAL:=help | |
endif | |
define HELP | |
Makefile for documents converting using pandoc. | |
Source: *.text (extension defined by SOURCE_EXT). | |
Target(s): enumerated in commandline (otherwise can be set in .DEFAULT_GOAL) | |
Usage: | |
make some_doc.html | |
Convert some_doc.text to some_doc.html. | |
Instead of ".html" any other pandoc-supported file type can be used. | |
make html | |
Convert *.text to *.html. | |
Instead of ".html" any other supported extension can be used, incl. hlf (must be enumerated in TARGET_EXT). | |
make some_doc.hlf | |
make hlf | |
Convert to .hlf using pandoc and HtmlToFarHelp. | |
make some_doc.forum | |
make forum | |
Convert to phpBB-flavored markdown (Litedown). | |
make clean | |
Clean current directory from all files with extensions specified in TARGET_EXT. | |
make help | |
This help | |
make install | |
Copy *.lua to $(APPDATA)\pandoc\filters | |
Or to $$(DATA_DIR)\filters (if defined). | |
Notes: | |
1. pandoc.exe and HtmlToFarHelp.exe must be available. | |
It is also possible to define full paths in env variables PANDOC/HTMLTOFARHELP. | |
2. Some conversions may require additional lua filters, which must be present in current directory. | |
Alternatively they can reside in $(DATA_DIR)\filters | |
(See `make install`) | |
3. Some conversions may require lua writers, which must be present in current directory. | |
Alternatively they can reside in $(DATA_DIR)\custom | |
4. The best way to customize this Makefile is including it in own Makefile, adding new rules | |
and (re)defining corresponding variables. | |
endef | |
SOURCE_EXT:=text | |
SOURCE_FORMAT?=--from=markdown-auto_identifiers-raw_tex+autolink_bare_uris | |
TARGET_EXT+=hlfhtml htm html md plain native json forum hlf | |
ifneq (,$(filter $(TARGET_EXT),$(SOURCE_EXT))) | |
$(error TARGET_EXT cannot include SOURCE_EXT) | |
else ifneq (1,$(words $(SOURCE_EXT))) | |
$(error SOURCE_EXT must be single ext) | |
endif | |
#https://pandoc.org/installing.html | |
PANDOC?=pandoc.exe | |
TARGET_FORMAT:= # deduced from extension; defaulting to html | |
FLAGS+=--wrap=preserve | |
EXTRA+=--lua-filter=FarLinks.lua | |
#https://www.nuget.org/packages/HtmlToFarHelp | |
HTMLTOFARHELP?=HtmlToFarHelp.exe | |
SHELL:=$(ComSpec) | |
RM:=del | |
ifdef DATA_DIR | |
FLAGS+= --data-dir=$(DATA_DIR) | |
else | |
DATA_DIR:=$(APPDATA)\pandoc#default | |
endif | |
LUA_PATH:=$(LUA_PATH);$(DATA_DIR)\filters\?.lua;$(DATA_DIR)\filters\?\init.lua | |
# Far Manager help file | |
%.hlf: %.hlfhtml | |
@$(HTMLTOFARHELP) from="$<"; to="$@" | |
$(info $@) | |
# intermediate file for hlf | |
%.hlfhtml: TARGET_FORMAT:= --to=html --no-highlight | |
%.hlfhtml: FLAGS+= --lua-filter=ChmLinks.lua --lua-filter=unDetails.lua | |
%.hlfhtml: EXTRA:= | |
# full-featured html, with headers, styles, ... (otherwise use `htm`) | |
%.html: FLAGS+= --standalone --strip-comments --lua-filter=HeaderToTitle.lua | |
# github-flavored markdown (pandoc --list-extensions=gfm) | |
%.md: TARGET_FORMAT:= --to=gfm --lua-filter=DefinitionToBulletList.lua | |
# prepare text for posting on forum.farmanager.com | |
%.forum: TARGET_FORMAT:=--to=markdown_strict+fenced_code_blocks-raw_html --lua-filter=DefinitionToBulletList.lua | |
%.forum: FLAGS+= --lua-filter=fold.lua --lua-filter=forum.lua --lua-filter=DetailsToSpoiler.lua | |
%.forum: EXTRA:=--shift-heading-level-by=1 --strip-comments | |
#prevent circular dependencies | |
%.text %.lua: ; | |
$(MAKEFILE_LIST): ; | |
.SECONDEXPANSION: #https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html#Secondary-Expansion | |
%: $$(basename %).$(SOURCE_EXT) $(MAKEFILE_LIST) $(wildcard *.lua) | |
@$(PANDOC) $(SOURCE_FORMAT) $(TARGET_FORMAT) $(FLAGS) $(EXTRA) --output=$@ $< | |
$(info $@) | |
.PHONY: $(TARGET_EXT) clean help install | |
# targets like html md hlf... | |
SOURCES:=$(wildcard *.$(SOURCE_EXT)) | |
NAMES:=$(basename $(SOURCES)) | |
$(TARGET_EXT): %: $(addsuffix .%,$(NAMES)) | |
TARGETS_MASK:=$(addprefix *.,$(TARGET_EXT)) | |
clean: | |
$(info $(wildcard $(TARGETS_MASK))) | |
@$(RM) $(TARGETS_MASK) | |
help: | |
$(info $(HELP)) | |
@rem | |
install: $(DATA_DIR)/filters $(addprefix $(DATA_DIR)/filters/, $(wildcard *.lua)) | |
$(DATA_DIR)/filters: | |
mkdir $(subst /,\,$@) | |
$(DATA_DIR)/filters/%: % | |
@rem cmd /c mklink $(subst /,\, $@ $(realpath $<)) | |
copy $< $(subst /,\,$@) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# required user setting | |
BASE:=D:\repo\Makefile | |
PANDOC:=C:\Apps\pandoc\pandoc.exe | |
HTMLTOFARHELP:=$(FARPROFILE)\tools\HtmlToFarHelp\HtmlToFarHelp.exe | |
# plug base Makefile | |
include $(BASE)\Makefile | |
.DEFAULT_GOAL:=hlf | |
# optional local customization | |
%.hlfhtml: FLAGS+=--lua-filter addRefs.lua | |
%: FLAGS+= --toc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--luacheck: globals meta Refs | |
local Label = meta.refsLabel | |
if not Label then -- default template of the links block | |
local doc = pandoc.read[[ | |
--- | |
refsLabel: > | |
- - - | |
Другие разделы справки:\ | |
... | |
]] | |
Label = doc.meta.refsLabel | |
end | |
local function prepRefs (header) -- prepare refs section for current article | |
local refs = Label:walk{} -- copy | |
local inlines = refs[#refs].content | |
-- | |
local links = Refs:filter(function (el) -- remove self from refs | |
return el.target~=header.identifier | |
end) | |
local last = links[#links] | |
for _,el in ipairs(links) do | |
inlines:extend{pandoc.Str"[", el, pandoc.Str"]"} | |
if el~=last then inlines:extend{pandoc.Str",", pandoc.Space()} end | |
end | |
return pandoc.Div(refs) | |
end | |
local function insertRefs (blocks, startIdx, endIdx) | |
local header = blocks[startIdx] | |
if header.identifier=="index" -- skip Index section | |
or header.classes:includes("noref") then --e.g. cfgscript note | |
return | |
end | |
local i = endIdx | |
if blocks[i-1].tag=="Div" then -- insert ref block before div | |
i = i-1 | |
end | |
blocks:insert(i, prepRefs(header)) | |
return endIdx+1 | |
end | |
return insertRefs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- helper script to execute same `callback` function for every section | |
-- to the same section belong blocks beginning by header and ending by last block before next header | |
-- it is possible to skip some header (= absorb it's content into current section), | |
-- with `condition` function, returning `true` | |
return function (blocks, callback, condition) | |
local start | |
local i = 1 | |
repeat | |
local el = blocks[i] | |
if el.tag=="Header" and el.identifier~="" then | |
local skip = condition and condition(el, blocks, i) | |
if not skip then | |
if start then | |
i = callback(blocks, start, i) or i | |
assert(blocks[i]==el,"wrong index returned by callback") | |
end | |
start = i | |
end | |
end | |
i = i+1 | |
until not blocks[i] | |
if start then | |
callback(blocks, start, i) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Remove <details> and <summary> tags | |
-- Useful for hlf, as HtmlToFarHelp does not support them | |
local REMOVE = {} | |
function RawBlock (el) | |
if el.format=="html" then | |
if el.text:match"^</?details>$" or el.text:match"^</?summary>$" then | |
-- todo summary=>strong | |
return REMOVE | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment