Skip to content

Commit bf62791

Browse files
authored
Editor tool enhancements (#1018)
- Applied suggestion from make file linter - Reorganized make file and enhanced UX - Fixed some linter findings - Fixed editor config - Documented that we derive the inversions inside the inverted files Signed-off-by: Stefan Hagen <stefan@hagen.link> * Usability boost and POSIX compliance - implemented an auto serial key behavior for the global counter of examples; you can now after insert of a new member simply add a random string to the numbering key to make the key unique. Processing (make invert-examples) will then re-write the keys with a correct and unioque auto-serial number string key. - made the generated JSON files POSIX compliant by adding a trailing newline Signed-off-by: Stefan Hagen <stefan@hagen.link> --------- Signed-off-by: Stefan Hagen <stefan@hagen.link>
1 parent e4d5942 commit bf62791

File tree

9 files changed

+133
-30
lines changed

9 files changed

+133
-30
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.editorconfig # Editor config
1+
# Editor config
22
# http://EditorConfig.org
33

44
# This EditorConfig overrides any parent EditorConfigs

csaf_2.1/prose/edit/Makefile

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,48 @@
1-
#! /usr/bin/env python
1+
#! /usr/bin/env python
22
"""Bread and butter inversion of global example number to example sug mapping."""
33
import json
44
import pathlib
55

66
ETC_PATH = pathlib.Path('etc')
7-
IN_PATH = ETC_PATH / 'example-global-to-local.json'
8-
OUT_PATH = ETC_PATH / 'example-local-to-global.json'
7+
G2L_PATH = ETC_PATH / 'example-global-to-local.json'
8+
L2G_PATH = ETC_PATH / 'example-local-to-global.json'
9+
10+
ENCODING = 'utf-8'
11+
ENC_ERRS = 'ignore'
12+
NL = '\n'
913

1014
if not ETC_PATH.is_dir():
1115
raise RuntimeError('Please execute me inside csaf_2.1/prose/edit/ because I am a simple tool')
1216

13-
with open(IN_PATH, 'rt', encoding='utf-8') as handle:
17+
with open(G2L_PATH, 'rt', encoding=ENCODING, errors=ENC_ERRS) as handle:
1418
data = json.load(handle)
1519

16-
inverted = {v: k for k, v in data.items()}
17-
ordered = {k: inverted[k] for k in sorted(inverted)}
20+
marker_value = "4321"
21+
marker_seen = False
22+
auto_serial = 1
23+
cleansed = {}
24+
for k, v in data.items():
25+
if not marker_seen:
26+
if k == marker_value:
27+
marker_seen = True
28+
cleansed[marker_value] = v
29+
continue
30+
cleansed[str(auto_serial)] = v
31+
auto_serial += 1
32+
33+
with open(G2L_PATH, 'wt', encoding=ENCODING, errors=ENC_ERRS) as handle:
34+
json.dump(cleansed, handle, indent=2)
35+
handle.write(NL) # For POSIX compliance
36+
37+
inverted = {v: k for k, v in cleansed.items()}
38+
ordered = {
39+
'Please do not edit manually!': (
40+
"Instead, call 'make invert-examples' inside the clone-root/csaf_2.1/prose/edit folder."
41+
)
42+
}
43+
for k in sorted(inverted):
44+
ordered[k] = inverted[k]
1845

19-
with open(OUT_PATH, 'wt', encoding='utf-8') as handle:
46+
with open(L2G_PATH, 'wt', encoding=ENCODING, errors=ENC_ERRS) as handle:
2047
json.dump(ordered, handle, indent=2)
48+
handle.write(NL) # For POSIX compliance

csaf_2.1/prose/edit/bin/invert_sec_labels.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#! /usr/bin/env python
1+
#! /usr/bin/env python
22
"""Bread and butter inversion of section numbers to label mapping."""
33
import json
44
import pathlib
@@ -7,10 +7,14 @@
77
IN_PATH = ETC_PATH / 'section-display-to-label.json'
88
OUT_PATH = ETC_PATH / 'section-label-to-display.json'
99

10+
ENCODING = 'utf-8'
11+
ENC_ERRS = 'ignore'
12+
NL = '\n'
13+
1014
if not ETC_PATH.is_dir():
1115
raise RuntimeError('Please execute me inside csaf_2.1/prose/edit/ because I am a simple tool')
1216

13-
with open(IN_PATH, 'rt', encoding='utf-8') as handle:
17+
with open(IN_PATH, 'rt', encoding=ENCODING, errors=ENC_ERRS) as handle:
1418
data = json.load(handle)
1519

1620
unique = {v for v in data.values()}
@@ -26,7 +30,14 @@
2630
raise RuntimeError('Please ensure the section labels are unique')
2731

2832
inverted = {v: k for k, v in data.items()}
29-
ordered = {k: inverted[k] for k in sorted(inverted)}
33+
ordered = {
34+
'Please do not edit manually!': (
35+
"Instead, call 'make invert-sections' inside the clone-root/csaf_2.1/prose/edit folder."
36+
)
37+
}
38+
for k in sorted(inverted):
39+
ordered[k] = inverted[k]
3040

31-
with open(OUT_PATH, 'wt', encoding='utf-8') as handle:
41+
with open(OUT_PATH, 'wt', encoding=ENCODING, errors=ENC_ERRS) as handle:
3242
json.dump(ordered, handle, indent=2)
43+
handle.write(NL) # For POSIX compliance

csaf_2.1/prose/edit/bin/toccata.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def generate_toc(toc_db: list[TOC_ENTRY_TYPE]) -> str:
6464
if pres > past:
6565
patch_me = entries[slot - 1]
6666
there = len('</li>')
67-
entries[slot - 1] = patch_me[:-there] + f'<ul>'
67+
entries[slot - 1] = patch_me[:-there] + '<ul>'
6868
entries.append(f'<li>{num_disp} <a href="#{slug}">{text}</a></li>')
6969
past = pres
7070
continue
@@ -113,6 +113,7 @@ def main(argv: list[str]) -> int:
113113

114114
with open('build/injected.html', 'wt', encoding=ENCODING) as handle:
115115
handle.write(''.join(outgoing))
116+
return 0
116117

117118

118119
if __name__ == '__main__':

csaf_2.1/prose/edit/bin/volatile.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
SPACE = ' '
2929
TM = '™'
3030

31+
DEBUG = bool(os.getenv('DEBUG_VOLATILE', ''))
32+
3133
# Optionally dump the look-up tables (LUT)s for section display and label:
3234
DUMP_LUT = bool(os.getenv('DUMP_LUT', ''))
3335

@@ -417,7 +419,7 @@ def main(argv: list[str]) -> int:
417419
.replace('$text$', text)
418420
.replace('$label$', label)
419421
)
420-
extended = False
422+
extended = 0
421423
if sec_cnt_disp.upper().isupper():
422424
extended = 2 if set(sec_cnt_disp).intersection('0123456789') else 1
423425
if extended == 2:
@@ -480,16 +482,16 @@ def main(argv: list[str]) -> int:
480482
raise RuntimeError(f'bad label for example in ({line.rstrip(NL)})')
481483
section, number = label.split('-eg-', 1)
482484
if section == CS_OF_SLOT[slot]:
483-
print(f'detected local reference for {label} in ({line.rstrip(NL)})')
485+
DEBUG and print(f'detected local reference for {label} in ({line.rstrip(NL)})')
484486
evil_ref = f'\\[[{number}](#{label})\\]' # [1](#a-sec-eg-1)
485487
else:
486-
print(f'detected remote reference for {label} in ({line.rstrip(NL)})')
488+
DEBUG and print(f'detected remote reference for {label} in ({line.rstrip(NL)})')
487489
sec_disp = display_from[section]
488490
evil_ref = (
489491
f'\\[[{number} (of section {sec_disp})](#{label})\\]' # [1 (of section 1.2.3)](#a-sec-eg-1)
490492
)
491493
line = line.replace(sem_ref, evil_ref)
492-
print(line.rstrip(NL))
494+
DEBUG and print(line.rstrip(NL))
493495
lines[slot] = line
494496

495497
# Process the text display of section refs

csaf_2.1/prose/edit/etc/example-local-to-global.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"Please do not edit manually!": "Instead, call 'make invert-examples' inside the clone-root/csaf_2.1/prose/edit folder.",
23
"acknowledgments-type-example-eg-1": "4",
34
"acknowledgments-type-names-eg-1": "1",
45
"acknowledgments-type-organization-eg-1": "2",
@@ -215,4 +216,4 @@
215216
"vulnerabilities-property-ids-eg-2": "51",
216217
"vulnerability-id-eg-1": "89",
217218
"vulnerability-notes-eg-1": "86"
218-
}
219+
}

csaf_2.1/prose/edit/etc/section-label-to-display.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"Please do not edit manually!": "Instead, call 'make invert-sections' inside the clone-root/csaf_2.1/prose/edit folder.",
23
"acknowledgments": "Appendix A.",
34
"acknowledgments-type": "3.1.1",
45
"acknowledgments-type-example": "3.1.1.5",
@@ -342,4 +343,4 @@
342343
"vulnerabilities-property-title": "3.2.4.16",
343344
"vulnerability-id": "6.1.27.8",
344345
"vulnerability-notes": "6.1.27.5"
345-
}
346+
}

csaf_2.1/prose/edit/makefile

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.POSIX:
2+
.SILENT:
3+
.DEFAULT_GOAL = build
4+
5+
pyversion = py312
6+
linelength = 120
7+
black = black -S -l $(linelength) --target-version $(pyversion) --quiet bin
8+
lint = ruff check bin
9+
types = mypy bin
10+
11+
.PHONY: all
12+
all: lint types build
13+
14+
.PHONY: format
15+
format:
16+
command -v ruff >/dev/null 2>&1 || { echo >&2 "make format requires ruff but it's not installed - you can install with: 'pip install ruff'. Aborting."; exit 1; }
17+
$(lint) --fix
18+
command -v black >/dev/null 2>&1 || { echo >&2 "make format requires black but it's not installed - you can install with: 'pip install black'. Aborting."; exit 1; }
19+
$(black)
20+
21+
.PHONY: lint
22+
lint:
23+
$(lint) --diff
24+
$(black) --check --diff
25+
command -v unmake >/dev/null 2>&1 || { echo >&2 "make lint requires unmake but it's not installed - you can install with: 'cargo install unmake'. Aborting."; exit 1; }
26+
unmake makefile
27+
28+
.PHONY: types
29+
types:
30+
command -v mypy >/dev/null 2>&1 || { echo >&2 "make types requires mypy but it's not installed - you can install with: 'pip install mypy'. Aborting."; exit 1; }
31+
$(types)
32+
33+
.PHONY: inversions
34+
inversions: invert-sections invert-examples
35+
36+
.PHONY: invert-examples
37+
invert-examples: ; bin/invert_eg_labels.py
38+
39+
.PHONY: invert-sections
40+
invert-sections: ; bin/invert_sec_labels.py
41+
42+
.PHONY: render
43+
render: render-html
44+
45+
.PHONY: render-markdown
46+
render-markdown: inversions
47+
bin/volatile.py && \
48+
cp -a build/tmp.md ../share/csaf-v2.1-draft.md && \
49+
printf "Rendered user facing delivery item in markdown format:\n" && \
50+
ls -l ../share/csaf-v2.1-draft.md
51+
52+
.PHONY: render-html
53+
render-html: render-markdown
54+
command -v pandoc >/dev/null 2>&1 || { echo >&2 "make render-html requires pandoc but it's not installed - you can get help on installing at https://pandoc.org. Aborting."; exit 1; }
55+
command -v tidy >/dev/null 2>&1 || { echo >&2 "make render-html requires tidy but it's not installed - you can get help on installing by searching for it on the wild internets. Aborting."; exit 1; }
56+
pandoc -f gfm+definition_lists -t html build/tmp.md --columns=345 \
57+
--css style/base.css --css style/skin.css --standalone -o build/tmp.html && \
58+
bin/toccata.py && \
59+
timeout 2 tidy -config etc/tidy-config.txt build/injected.html -ashtml 2>/dev/null | \
60+
sed 's/<!\[CDATA\[//g; s/\]\]>//g;' > ../share/csaf-v2.1-draft.html && \
61+
printf "Rendered user facing delivery item in html format:\n" && \
62+
ls -l ../share/csaf-v2.1-draft.html
63+
64+
.PHONY: build
65+
build: render status
66+
67+
.PHONY: status
68+
status:
69+
printf "Current version control status:\n"; \
70+
git status

0 commit comments

Comments
 (0)