|
3 | 3 | import glob |
4 | 4 | import re |
5 | 5 | import subprocess |
6 | | -from markdown_it import MarkdownIt |
7 | 6 | import sys |
8 | 7 | import pglast |
9 | 8 |
|
10 | | -mdp = MarkdownIt() |
11 | | - |
| 9 | +# Match fenced code blocks, including those nested inside mkdocs-material |
| 10 | +# `===` content tabs (which indent the fence by 4+ spaces). The leading |
| 11 | +# indentation is captured so it can be stripped from each code line, and the |
| 12 | +# closing fence must match both the indent and the opening fence marker. |
12 | 13 | pattern = re.compile( |
13 | | - r'(?msi)^(?P<fence>[`~]{3,})[^\n]*\r?\n(?P<code>.*?)^(?P=fence)[ \t]*\r?$' |
| 14 | + r'(?ms)^(?P<indent>[ \t]*)(?P<fence>`{3,}|~{3,})(?P<info>[^\n]*)\r?\n' |
| 15 | + r'(?P<code>.*?)' |
| 16 | + r'^(?P=indent)(?P=fence)[ \t]*\r?$' |
14 | 17 | ) |
15 | 18 |
|
16 | 19 | replication = [ |
|
19 | 22 | ] |
20 | 23 |
|
21 | 24 | def verify(binary): |
22 | | - for file in glob.glob("docs/**/*.md", |
23 | | - recursive=True): |
| 25 | + for file in glob.glob("docs/**/*.md", recursive=True): |
24 | 26 | with open(file, "r") as f: |
25 | 27 | content = f.read() |
26 | | - print(f"Checking {file}") |
27 | | - tokens = mdp.parse(content) |
28 | | - for token in tokens: |
29 | | - if token.type == "fence" and token.info == "toml": |
30 | | - if "[[users]]" in token.content: |
31 | | - check_file(binary, "users", token.content) |
32 | | - elif "[lib]" in token.content: |
33 | | - pass |
| 28 | + print(f"Checking {file}") |
| 29 | + for m in pattern.finditer(content): |
| 30 | + info = m.group("info").strip().lower() |
| 31 | + indent = m.group("indent") |
| 32 | + code = m.group("code") |
| 33 | + if indent: |
| 34 | + # Dedent the code body so configcheck/pglast see clean text. |
| 35 | + stripped_lines = [] |
| 36 | + for line in code.splitlines(keepends=True): |
| 37 | + if line.startswith(indent): |
| 38 | + stripped_lines.append(line[len(indent):]) |
34 | 39 | else: |
35 | | - check_file(binary, "pgdog", token.content) |
36 | | - elif token.type == "fence" and token.info == "postgresql": |
37 | | - try: |
38 | | - pglast.parser.parse_sql(token.content) |
39 | | - except Exception as e: |
40 | | - found = False |
41 | | - for cmd in replication: |
42 | | - if cmd in token.content: |
43 | | - found = True |
44 | | - if not found: |
45 | | - print(token.content) |
46 | | - raise e |
| 40 | + stripped_lines.append(line) |
| 41 | + code = "".join(stripped_lines) |
| 42 | + |
| 43 | + if info == "toml": |
| 44 | + if "[[users]]" in code: |
| 45 | + check_file(binary, "users", code) |
| 46 | + elif "[lib]" in code: |
| 47 | + pass |
| 48 | + else: |
| 49 | + check_file(binary, "pgdog", code) |
| 50 | + elif info == "postgresql": |
| 51 | + try: |
| 52 | + pglast.parser.parse_sql(code) |
| 53 | + except Exception as e: |
| 54 | + found = False |
| 55 | + for cmd in replication: |
| 56 | + if cmd in code: |
| 57 | + found = True |
| 58 | + if not found: |
| 59 | + print(code) |
| 60 | + raise e |
47 | 61 |
|
48 | 62 | def check_file(binary, kind, content): |
49 | 63 | tmp = f"/tmp/pgdog_config_test.toml" |
|
0 commit comments