Skip to content

Commit c9915d6

Browse files
committed
dev.markdown-checks: add -s/--special-cases option to allow for various persistent check exceptions via special syntax
1 parent 537dd0a commit c9915d6

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2957,7 +2957,8 @@ Current full list of checks that it runs:
29572957
Useful for maintaining non-mkdocs .md files for git forges and such,
29582958
where otherwise nothing will indicate any potential issues.
29592959

2960-
["Basic markdown syntax/links checks ..." blog post] might have a bit more info/context for this script.
2960+
["Basic markdown syntax/links checks ..." blog post] might have a bit more info/context for this script.\
2961+
See also `-h/--help` for a list of unclear syntax choices and odd special-cases, if any.
29612962

29622963
["Basic markdown syntax/links checks ..." blog post]:
29632964
https://blog.fraggod.net/2024/01/17/basic-markdown-syntaxlinks-checks-after-rst-md-migration.html

desktop/filetag

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ tag_map = dict(
7979
# Code formats
8080
code_ext = {
8181
'py|tac': 'py', 'go': 'go', r'c(c|pp|xx|\+\+)?|hh?|lex|y(acc)?': 'c',
82-
r'js(o?n(\.txt)?)?|ts|coffee': 'js', 'co?nf|cf|cfg|ini': 'conf',
82+
r'js(o?n(\.txt)?)?|tsx?|coffee': 'js', 'co?nf|cf|cfg|ini': 'conf',
8383
'nim': 'nim', 'ex|exs|erl|hrl': 'erlang',
8484
'unit|service|taget|mount|desktop|rules': 'conf',
8585
'[sx]?htm(l[45]?)?|css|less|jade': 'html', 'x[ms]l|xsd|dbk': 'xml',

dev/markdown-checks

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ def md_parse_misc_anchors(md_lines, anchor_map):
194194
return anchors
195195

196196

197-
def md_check_links(md_lines, errs):
197+
def md_check_links(md_lines, errs, sc=False):
198198
'''Parse/check links in a cleaned-up/numbered md lines without code blocks.
199199
Returns {target: [links...]} to run file/path/url/git and such checks on.'''
200-
links, link_urls, st = dict(), dict(), adict(indented_url=None)
200+
links, link_urls, link_urls_ex, st = dict(), dict(), dict(), adict(indented_url=None)
201201

202202
for n, line_raw in md_lines:
203203
if not (line := md_esc_strip(line_raw.strip())): continue
@@ -218,19 +218,28 @@ def md_check_links(md_lines, errs):
218218

219219
for a, b, title in titles:
220220
if not title: continue # [] after image-links and such
221-
if title != title.strip(): continue
222-
link = adict(n=n, title=(title := md_esc_restore(title)), url=None, dups=0)
221+
if sc and title != title.strip(): continue # special-case - links with spaced titles
222+
link = adict(n=n, title=(title := md_esc_restore(title)), url=None)
223223
if urls := list(extract_toplevel(ls := line[b:], '()', False)):
224224
ua, ub, url = urls[0]
225225
if not ua: link.url = md_esc_restore(url)
226-
if (link.url or '').startswith('#'): # these are special - for anchor-checks only
226+
if (link.url or '').startswith('#'): # always special - for anchor-checks only
227227
title = link.title = f'\uf001{link.title}'
228-
if (link_chk := links.get(title)) and (link_chk.url or link.url or link_chk.dups):
229-
errs.append(adict( n=n, t='link_dups',
230-
s=f'Duplicate non-uniform link [{link.title}], matching one on line-{link_chk.n}' ))
231-
link.dups = link_chk.dups + 1
232-
if not link_chk.url: link.url = None # one of them needs an url
233-
links[title] = link
228+
links[title], link_chk = link, links.get(title)
229+
if not link_chk: continue
230+
# Special-case allows explicit-URL links to match uniform ones pointing to anchor
231+
dup_warn = lambda err: errs.append(adict( n=n,
232+
t='link_dups', s=f'Duplicate non-uniform link [{link.title}] {err}' ))
233+
url_sc = (lu := link_urls.get(link.title)) and sc and lu.url.startswith('#')
234+
if link_chk.url and not url_sc: dup_warn(f'on line-{link_chk.n}')
235+
if link.url:
236+
if lud := link_urls_ex.get(title):
237+
warn = f'matching one on line-{lud.n}'
238+
if lud: warn += f' (url-match={int(lu.url == lud.url)})'
239+
dup_warn(warn)
240+
elif not url_sc: dup_warn(f'with one on line-{link_chk.n}')
241+
link_urls_ex[title] = link
242+
if not link_chk.url: link.url = None # propagate missing url for a single check below
234243

235244
link_map = cs.defaultdict(list)
236245
for link in links.values():
@@ -305,8 +314,7 @@ def main(argv=None):
305314
textwrap.dedent(text).strip('\n') + '\n' ).replace('\t', ' ')
306315
parser = argparse.ArgumentParser(
307316
formatter_class=argparse.RawTextHelpFormatter,
308-
usage='%(prog)s [opts] [--] [file.md ...]',
309-
description=dd('''
317+
usage='%(prog)s [opts] [--] [file.md ...]', description=dd('''
310318
Check all specified markdown files for common issues.
311319
Returns non-zero exit code with stderr output if any of the checks detect issues.
312320
@@ -338,6 +346,13 @@ def main(argv=None):
338346
Only #-prefix headers are handled as such, all underlined ones are ignored.
339347
This modifies files and suppresses normal script operation mode.
340348
Exit code is 0 if no anchors were added, and non-zero otherwise.'''))
349+
parser.add_argument('-s', '--special-cases', action='store_true', help=dd('''
350+
Apply following exceptions/special-cases for syntax/checks:\n
351+
- Links with space-prefix/suffix in title, like [ skip this](...) are left unchecked.
352+
- Links with explicit URLs can have same title as header-links (to #<name> anchors).
353+
Allows to point links to a repo script(s), while otherwise to its doc section.\n
354+
Idea is to have this special md sub-syntax to prevent this tool from raising
355+
warnings in places were it normally should, but are known to be non-issues.'''))
341356

342357
opts = parser.parse_args(sys.argv[1:] if argv is None else argv)
343358

@@ -384,7 +399,7 @@ def main(argv=None):
384399
err_code = 1
385400
continue
386401

387-
link_map = md_check_links(md_lines, errs)
402+
link_map = md_check_links(md_lines, errs, sc=opts.special_cases)
388403

389404
anchor_names = dict((a.name, a) for a in anchor_map.values())
390405
anchor_names.update( (a.name, a) for a in

0 commit comments

Comments
 (0)