aboutsummaryrefslogtreecommitdiff
path: root/scripts/gen_help_html.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /scripts/gen_help_html.lua
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.tar.gz
rneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.tar.bz2
rneovim-931bffbda3668ddc609fc1da8f9eb576b170aa52.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'scripts/gen_help_html.lua')
-rw-r--r--scripts/gen_help_html.lua241
1 files changed, 153 insertions, 88 deletions
diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 2563f2f410..633207e018 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -34,6 +34,8 @@ local spell_dict = {
neovim = 'Nvim',
lua = 'Lua',
VimL = 'Vimscript',
+ vimL = 'Vimscript',
+ viml = 'Vimscript',
}
local language = nil
@@ -43,6 +45,7 @@ local M = {}
-- All other files are "legacy" files which require fixed-width layout.
local new_layout = {
['api.txt'] = true,
+ ['lsp.txt'] = true,
['channel.txt'] = true,
['deprecated.txt'] = true,
['develop.txt'] = true,
@@ -57,21 +60,10 @@ local new_layout = {
-- TODO: These known invalid |links| require an update to the relevant docs.
local exclude_invalid = {
- ["'previewpopup'"] = "quickref.txt",
- ["'pvp'"] = "quickref.txt",
["'string'"] = "eval.txt",
Query = 'treesitter.txt',
- ['eq?'] = 'treesitter.txt',
- ['lsp-request'] = 'lsp.txt',
matchit = 'vim_diff.txt',
- ['matchit.txt'] = 'help.txt',
["set!"] = "treesitter.txt",
- ['v:_null_blob'] = 'builtin.txt',
- ['v:_null_dict'] = 'builtin.txt',
- ['v:_null_list'] = 'builtin.txt',
- ['v:_null_string'] = 'builtin.txt',
- ['vim.lsp.buf_request()'] = 'lsp.txt',
- ['vim.lsp.util.get_progress_messages()'] = 'lsp.txt',
}
-- False-positive "invalid URLs".
@@ -90,6 +82,11 @@ local exclude_invalid_urls = {
["http://www.jclark.com/"] = "quickfix.txt",
}
+-- Deprecated, brain-damaged files that I don't care about.
+local ignore_errors = {
+ ['pi_netrw.txt'] = true,
+}
+
local function tofile(fname, text)
local f = io.open(fname, 'w')
if not f then
@@ -145,11 +142,11 @@ local function trim(s, dir)
return vim.fn.trim(s, '\r\t\n ', dir or 0)
end
--- Remove common punctuation from URLs.
---
--- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc
---
--- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
+--- Removes common punctuation from URLs.
+---
+--- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc
+---
+--- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
local function fix_url(url)
local removed_chars = ''
local fixed_url = url
@@ -163,7 +160,7 @@ local function fix_url(url)
return fixed_url, removed_chars
end
--- Checks if a given line is a "noise" line that doesn't look good in HTML form.
+--- Checks if a given line is a "noise" line that doesn't look good in HTML form.
local function is_noise(line, noise_lines)
if (
-- First line is always noise.
@@ -188,7 +185,7 @@ local function is_noise(line, noise_lines)
return false
end
--- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content.
+--- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content.
local function get_bug_url_vimdoc(fname, to_fname, sample_text)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
@@ -201,7 +198,7 @@ local function get_bug_url_vimdoc(fname, to_fname, sample_text)
return bug_url
end
--- Creates a github issue URL at neovim/neovim with prefilled content.
+--- Creates a github issue URL at neovim/neovim with prefilled content.
local function get_bug_url_nvim(fname, to_fname, sample_text, token_name)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
local bug_url = ('https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+'
@@ -216,7 +213,7 @@ local function get_bug_url_nvim(fname, to_fname, sample_text, token_name)
return bug_url
end
--- Gets a "foo.html" name from a "foo.txt" helpfile name.
+--- Gets a "foo.html" name from a "foo.txt" helpfile name.
local function get_helppage(f)
if not f then
return nil
@@ -231,9 +228,9 @@ local function get_helppage(f)
return (f:gsub('%.txt$', '.html'))
end
--- Counts leading spaces (tab=8) to decide the indent size of multiline text.
---
--- Blank lines (empty or whitespace-only) are ignored.
+--- Counts leading spaces (tab=8) to decide the indent size of multiline text.
+---
+--- Blank lines (empty or whitespace-only) are ignored.
local function get_indent(s)
local min_indent = nil
for line in vim.gsplit(s, '\n') do
@@ -245,7 +242,7 @@ local function get_indent(s)
return min_indent or 0
end
--- Removes the common indent level, after expanding tabs to 8 spaces.
+--- Removes the common indent level, after expanding tabs to 8 spaces.
local function trim_indent(s)
local indent_size = get_indent(s)
local trimmed = ''
@@ -256,7 +253,7 @@ local function trim_indent(s)
return trimmed:sub(1, -2)
end
--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string.
+--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string.
local function getbuflinestr(node, bufnr, offset)
local line1, _, line2, _ = node:range()
line1 = line1 - offset
@@ -265,8 +262,8 @@ local function getbuflinestr(node, bufnr, offset)
return table.concat(lines, '\n')
end
--- Gets the whitespace just before `node` from the raw buffer text.
--- Needed for preformatted `old` lines.
+--- Gets the whitespace just before `node` from the raw buffer text.
+--- Needed for preformatted `old` lines.
local function getws(node, bufnr)
local line1, c1, line2, _ = node:range()
local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1]
@@ -283,18 +280,21 @@ local function get_tagname(node, bufnr)
return helppage, tag
end
--- Returns true if the given invalid tagname is a false positive.
+--- Returns true if the given invalid tagname is a false positive.
local function ignore_invalid(s)
return not not (
exclude_invalid[s]
-- Strings like |~/====| appear in various places and the parser thinks they are links, but they
-- are just table borders.
or s:find('===')
- or s:find('---')
+ or s:find('%-%-%-')
)
end
-local function ignore_parse_error(s)
+local function ignore_parse_error(fname, s)
+ if ignore_errors[vim.fs.basename(fname)] then
+ return true
+ end
return (
-- Ignore parse errors for unclosed tag.
-- This is common in vimdocs and is treated as plaintext by :help.
@@ -315,7 +315,7 @@ local function has_ancestor(node, ancestor_name)
return false
end
--- Gets the first matching child node matching `name`.
+--- Gets the first matching child node matching `name`.
local function first(node, name)
for c, _ in node:iter_children() do
if c:named() and c:type() == name then
@@ -337,10 +337,10 @@ local function validate_link(node, bufnr, fname)
return helppage, tagname, ignored
end
--- TODO: port the logic from scripts/check_urls.vim
+--- TODO: port the logic from scripts/check_urls.vim
local function validate_url(text, fname)
local ignored = false
- if vim.fs.basename(fname) == 'pi_netrw.txt' then
+ if ignore_errors[vim.fs.basename(fname)] then
ignored = true
elseif text:find('http%:') and not exclude_invalid_urls[text] then
invalid_urls[text] = vim.fs.basename(fname)
@@ -348,10 +348,12 @@ local function validate_url(text, fname)
return ignored
end
--- Traverses the tree at `root` and checks that |tag| links point to valid helptags.
+--- Traverses the tree at `root` and checks that |tag| links point to valid helptags.
local function visit_validate(root, level, lang_tree, opt, stats)
level = level or 0
local node_name = (root.named and root:named()) and root:type() or nil
+ -- Parent kind (string).
+ local parent = root:parent() and root:parent():type() or nil
local toplevel = level < 1
local function node_text(node)
return vim.treesitter.get_node_text(node or root, opt.buf)
@@ -367,19 +369,21 @@ local function visit_validate(root, level, lang_tree, opt, stats)
end
if node_name == 'ERROR' then
- if ignore_parse_error(text) then
+ if ignore_parse_error(opt.fname, text) then
return
end
-- Store the raw text to give context to the error report.
- local sample_text = not toplevel and getbuflinestr(root, opt.buf, 3) or '[top level!]'
+ local sample_text = not toplevel and getbuflinestr(root, opt.buf, 0) or '[top level!]'
+ -- Flatten the sample text to a single, truncated line.
+ sample_text = vim.trim(sample_text):gsub('[\t\n]', ' '):sub(1, 80)
table.insert(stats.parse_errors, sample_text)
- elseif node_name == 'word' or node_name == 'uppercase_name' then
- if spell_dict[text] then
- if not invalid_spelling[text] then
- invalid_spelling[text] = { vim.fs.basename(opt.fname) }
- else
- table.insert(invalid_spelling[text], vim.fs.basename(opt.fname))
- end
+ elseif (node_name == 'word' or node_name == 'uppercase_name')
+ and (not vim.tbl_contains({'codespan', 'taglink', 'tag'}, parent))
+ then
+ local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation.
+ if spell_dict[text_nopunct] then
+ invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {}
+ invalid_spelling[text_nopunct][vim.fs.basename(opt.fname)] = node_text(root:parent())
end
elseif node_name == 'url' then
local fixed_url, _ = fix_url(trim(text))
@@ -461,6 +465,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', ''))
-- Use the first *tag* node as the heading anchor, if any.
local tagnode = first(root, 'tag')
+ -- Use the *tag* as the heading anchor id, if possible.
local tagname = tagnode and url_encode(node_text(tagnode:child(1), false)) or to_heading_tag(hname)
if node_name == 'h1' or #headings == 0 then
table.insert(headings, { name = hname, subheadings = {}, tag = tagname })
@@ -468,9 +473,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, tag = tagname })
end
local el = node_name == 'h1' and 'h2' or 'h3'
- -- If we are re-using the *tag*, this heading anchor is redundant.
- local a = tagnode and '' or ('<a name="%s"></a>'):format(tagname)
- return ('%s<%s class="help-heading">%s</%s>\n'):format(a, el, text, el)
+ return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(el, tagname, text, el)
elseif node_name == 'column_heading' or node_name == 'column_name' then
if root:has_error() then
return text
@@ -491,7 +494,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return '' -- Discard common "noise" lines.
end
-- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout.
- local div = opt.old and root:child(0) and vim.tbl_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type())
+ local div = opt.old and root:child(0) and vim.list_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type())
return string.format('%s%s', div and trim(text) or text, div and '' or '\n')
elseif node_name == 'line_li' then
local sib = root:prev_sibling()
@@ -522,7 +525,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end
return s
- elseif vim.tbl_contains({'codespan', 'keycode'}, node_name) then
+ elseif vim.list_contains({'codespan', 'keycode'}, node_name) then
if root:has_error() then
return text
end
@@ -538,7 +541,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
elseif node_name == 'language' then
language = node_text(root)
return ''
- elseif node_name == 'code' then
+ elseif node_name == 'code' then -- Highlighted codeblock (child).
if is_blank(text) then
return ''
end
@@ -554,7 +557,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
if root:has_error() then
return text
end
- local in_heading = vim.tbl_contains({'h1', 'h2', 'h3'}, parent)
+ local in_heading = vim.list_contains({'h1', 'h2', 'h3'}, parent)
local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag'
local tagname = node_text(root:child(1), false)
if vim.tbl_count(stats.first_tags) < 2 then
@@ -563,12 +566,15 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return ''
end
local el = in_heading and 'span' or 'code'
- local s = ('%s<a name="%s"></a><%s class="%s">%s</%s>'):format(ws(), url_encode(tagname), el, cssclass, trimmed, el)
+ local encoded_tagname = url_encode(tagname)
+ local s = ('%s<%s id="%s" class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, encoded_tagname, cssclass, encoded_tagname, trimmed, el)
if opt.old then
s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end
if in_heading and prev ~= 'tag' then
+ -- Don't set "id", let the heading use the tag as its "id" (used by search engines).
+ s = ('%s<%s class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, cssclass, encoded_tagname, trimmed, el)
-- Start the <span> container for tags in a heading.
-- This makes "justify-content:space-between" right-align the tags.
-- <h2>foo bar<span>tag1 tag2</span></h2>
@@ -579,7 +585,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
return s
elseif node_name == 'ERROR' then
- if ignore_parse_error(trimmed) then
+ if ignore_parse_error(opt.fname, trimmed) then
return text
end
@@ -601,7 +607,7 @@ local function get_helpfiles(include)
for f, type in vim.fs.dir(dir) do
if (vim.endswith(f, '.txt')
and type == 'file'
- and (not include or vim.tbl_contains(include, f))) then
+ and (not include or vim.list_contains(include, f))) then
local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p')
table.insert(rv, fullpath)
end
@@ -609,7 +615,7 @@ local function get_helpfiles(include)
return rv
end
--- Populates the helptags map.
+--- Populates the helptags map.
local function get_helptags(help_dir)
local m = {}
-- Load a random help file to convince taglist() to do its job.
@@ -624,17 +630,19 @@ local function get_helptags(help_dir)
return m
end
--- Use the help.so parser defined in the build, not whatever happens to be installed on the system.
+--- Use the vimdoc parser defined in the build, not whatever happens to be installed on the system.
local function ensure_runtimepath()
if not vim.o.runtimepath:find('build/lib/nvim/') then
vim.cmd[[set runtimepath^=./build/lib/nvim/]]
end
end
--- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents.
---
--- @returns lang_tree, bufnr
-local function parse_buf(fname)
+--- Opens `fname` in a buffer and gets a treesitter parser for the buffer contents.
+---
+--- @param fname string help file to parse
+--- @param parser_path string? path to non-default vimdoc.so
+--- @returns lang_tree, bufnr
+local function parse_buf(fname, parser_path)
local buf
if type(fname) == 'string' then
vim.cmd('split '..vim.fn.fnameescape(fname)) -- Filename.
@@ -643,21 +651,25 @@ local function parse_buf(fname)
buf = fname
vim.cmd('sbuffer '..tostring(fname)) -- Buffer number.
end
- -- vim.treesitter.require_language('help', './build/lib/nvim/parser/help.so')
- local lang_tree = vim.treesitter.get_parser(buf, 'help')
+ if parser_path then
+ vim.treesitter.language.add('vimdoc', { path = parser_path })
+ end
+ local lang_tree = vim.treesitter.get_parser(buf)
return lang_tree, buf
end
--- Validates one :help file `fname`:
--- - checks that |tag| links point to valid helptags.
--- - recursively counts parse errors ("ERROR" nodes)
---
--- @returns { invalid_links: number, parse_errors: number }
-local function validate_one(fname)
+--- Validates one :help file `fname`:
+--- - checks that |tag| links point to valid helptags.
+--- - recursively counts parse errors ("ERROR" nodes)
+---
+--- @param fname string help file to validate
+--- @param parser_path string? path to non-default vimdoc.so
+--- @returns { invalid_links: number, parse_errors: string[] }
+local function validate_one(fname, parser_path)
local stats = {
parse_errors = {},
}
- local lang_tree, buf = parse_buf(fname)
+ local lang_tree, buf = parse_buf(fname, parser_path)
for _, tree in ipairs(lang_tree:trees()) do
visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname, }, stats)
end
@@ -666,20 +678,21 @@ local function validate_one(fname)
return stats
end
--- Generates HTML from one :help file `fname` and writes the result to `to_fname`.
---
--- @param fname Source :help file
--- @param to_fname Destination .html file
--- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace)
---
--- @returns html, stats
-local function gen_one(fname, to_fname, old, commit)
+--- Generates HTML from one :help file `fname` and writes the result to `to_fname`.
+---
+--- @param fname string Source :help file
+--- @param to_fname string Destination .html file
+--- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace)
+--- @param parser_path string? path to non-default vimdoc.so
+---
+--- @returns html, stats
+local function gen_one(fname, to_fname, old, commit, parser_path)
local stats = {
noise_lines = {},
parse_errors = {},
first_tags = {}, -- Track the first few tags in doc.
}
- local lang_tree, buf = parse_buf(fname)
+ local lang_tree, buf = parse_buf(fname, parser_path)
local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3.
local title = to_titlecase(basename_noext(fname))
@@ -691,11 +704,17 @@ local function gen_one(fname, to_fname, old, commit)
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Neovim user documentation">
+
+ <!-- algolia docsearch https://docsearch.algolia.com/docs/docsearch-v3/ -->
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" />
+ <link rel="preconnect" href="https://X185E15FPG-dsn.algolia.net" crossorigin />
+
<link href="/css/normalize.min.css" rel="stylesheet">
<link href="/css/bootstrap.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="help.css" rel="stylesheet">
<link href="/highlight/styles/neovim.min.css" rel="stylesheet">
+
<script src="/highlight/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<title>%s - Neovim docs</title>
@@ -766,19 +785,20 @@ local function gen_one(fname, to_fname, old, commit)
main = ([[
<header class="container">
<nav class="navbar navbar-expand-lg">
- <div>
+ <div class="container-fluid">
<a href="/" class="navbar-brand" aria-label="logo">
<!--TODO: use <img src="….svg"> here instead. Need one that has green lettering instead of gray. -->
%s
<!--<img src="https://neovim.io/logos/neovim-logo.svg" width="173" height="50" alt="Neovim" />-->
</a>
+ <div id="docsearch"></div> <!-- algolia docsearch https://docsearch.algolia.com/docs/docsearch-v3/ -->
</div>
</nav>
</header>
<div class="container golden-grid help-body">
<div class="col-wide">
- <a name="%s"></a><a name="%s"></a><h1>%s</h1>
+ <a name="%s"></a><h1 id="%s">%s</h1>
<p>
<i>
Nvim <code>:help</code> pages, <a href="https://github.com/neovim/neovim/blob/master/scripts/gen_help_html.lua">generated</a>
@@ -789,7 +809,7 @@ local function gen_one(fname, to_fname, old, commit)
<hr/>
%s
</div>
- ]]):format(logo_svg, stats.first_tags[1] or '', stats.first_tags[2] or '', title, vim.fs.basename(fname), main)
+ ]]):format(logo_svg, stats.first_tags[2] or '', stats.first_tags[1] or '', title, vim.fs.basename(fname), main)
local toc = [[
<div class="col-narrow toc">
@@ -825,6 +845,18 @@ local function gen_one(fname, to_fname, old, commit)
parse_errors: %d %s | <span title="%s">noise_lines: %d</span>
</div>
<div>
+
+ <!-- algolia docsearch https://docsearch.algolia.com/docs/docsearch-v3/ -->
+ <script src="https://cdn.jsdelivr.net/npm/@docsearch/js@3"></script>
+ <script type="module">
+ docsearch({
+ container: '#docsearch',
+ appId: 'X185E15FPG',
+ apiKey: 'b5e6b2f9c636b2b471303205e59832ed',
+ indexName: 'nvim',
+ });
+ </script>
+
</footer>
]]):format(
os.date('%Y-%m-%d %H:%M'), commit, commit:sub(1, 7), #stats.parse_errors, bug_link,
@@ -908,6 +940,7 @@ local function gen_css(fname)
padding-top: 10px;
padding-bottom: 10px;
}
+
.old-help-para {
padding-top: 10px;
padding-bottom: 10px;
@@ -917,6 +950,13 @@ local function gen_css(fname)
font-size: 16px;
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
}
+ .old-help-para pre {
+ /* All text in .old-help-para is formatted as "white-space:pre" so text following <pre> is
+ already visually separated by the linebreak. */
+ margin-bottom: 0;
+ }
+
+ /* TODO: should this rule be deleted? help tags are rendered as <code> or <span>, not <a> */
a.help-tag, a.help-tag:focus, a.help-tag:hover {
color: inherit;
text-decoration: none;
@@ -927,6 +967,17 @@ local function gen_css(fname)
/* Tag pseudo-header common in :help docs. */
.help-tag-right {
color: var(--tag-color);
+ margin-left: auto;
+ margin-right: 0;
+ float: right;
+ }
+ .help-tag a,
+ .help-tag-right a {
+ color: inherit;
+ }
+ .help-tag a:not(:hover),
+ .help-tag-right a:not(:hover) {
+ text-decoration: none;
}
h1 .help-tag, h2 .help-tag, h3 .help-tag {
font-size: smaller;
@@ -967,6 +1018,9 @@ local function gen_css(fname)
font-size: 16px;
margin-top: 10px;
}
+ pre:last-child {
+ margin-bottom: 0;
+ }
pre:hover,
.help-heading:hover {
overflow: visible;
@@ -1038,18 +1092,21 @@ end
--- @param include table|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'}
---
--- @returns info dict
-function M.gen(help_dir, to_dir, include, commit)
+function M.gen(help_dir, to_dir, include, commit, parser_path)
vim.validate{
- help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'},
+ help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
to_dir={to_dir, 's'},
include={include, 't', true},
commit={commit, 's', true},
+ parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'},
}
local err_count = 0
ensure_runtimepath()
- tagmap = get_helptags(help_dir)
+ tagmap = get_helptags(vim.fn.expand(help_dir))
helpfiles = get_helpfiles(include)
+ to_dir = vim.fn.expand(to_dir)
+ parser_path = parser_path and vim.fn.expand(parser_path) or nil
print(('output dir: %s'):format(to_dir))
vim.fn.mkdir(to_dir, 'p')
@@ -1058,7 +1115,7 @@ function M.gen(help_dir, to_dir, include, commit)
for _, f in ipairs(helpfiles) do
local helpfile = vim.fs.basename(f)
local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile))
- local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?')
+ local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?', parser_path)
tofile(to_fname, html)
print(('generated (%-4s errors): %-15s => %s'):format(#stats.parse_errors, helpfile, vim.fs.basename(to_fname)))
err_count = err_count + #stats.parse_errors
@@ -1081,20 +1138,27 @@ end
-- This is 10x faster than gen(), for use in CI.
--
-- @returns results dict
-function M.validate(help_dir, include)
+function M.validate(help_dir, include, parser_path)
vim.validate{
- help_dir={help_dir, function(d) return vim.fn.isdirectory(d) == 1 end, 'valid directory'},
+ help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
include={include, 't', true},
+ parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'},
}
local err_count = 0
+ local files_to_errors = {}
ensure_runtimepath()
- tagmap = get_helptags(help_dir)
+ tagmap = get_helptags(vim.fn.expand(help_dir))
helpfiles = get_helpfiles(include)
+ parser_path = parser_path and vim.fn.expand(parser_path) or nil
for _, f in ipairs(helpfiles) do
local helpfile = vim.fs.basename(f)
- local rv = validate_one(f)
+ local rv = validate_one(f, parser_path)
print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile))
+ if #rv.parse_errors > 0 then
+ files_to_errors[helpfile] = rv.parse_errors
+ vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v) return s..'\n '..v end)))
+ end
err_count = err_count + #rv.parse_errors
end
@@ -1104,6 +1168,7 @@ function M.validate(help_dir, include)
invalid_links = invalid_links,
invalid_urls = invalid_urls,
invalid_spelling = invalid_spelling,
+ parse_errors = files_to_errors,
}
end