@@ -87,67 +87,65 @@ steps:
8787
8888 # Add local src/srcset references from HTML <picture> blocks. The Markdown
8989 # scanner above remains responsible for  references.
90- python3 <<'PY'
91- import json
92- import pathlib
93- from html.parser import HTMLParser
94-
95- refs_path = pathlib.Path("/tmp/gh-aw/data/image-refs.json")
96- refs = json.loads(refs_path.read_text())
97- seen = {(record["file"], record["path"]) for record in refs}
98-
99- def add_ref(source_file, line, alt, image_path):
100- image_path = image_path.strip()
101- if not image_path or image_path.startswith(("http://", "https://", "data:")):
102- return
103- key = (str(source_file), image_path)
104- if key in seen:
105- return
106- seen.add(key)
107- resolved = (source_file.parent / image_path).resolve()
108- refs.append({
109- "file": str(source_file),
110- "line": line,
111- "alt": alt,
112- "path": image_path,
113- "resolved": str(resolved),
114- "exists": resolved.is_file(),
115- })
116-
117- class PictureParser(HTMLParser):
118- def __init__(self, source_file):
119- super().__init__()
120- self.source_file = source_file
121- self.picture_refs = None
122-
123- def handle_starttag(self, tag, attrs):
124- attrs = dict(attrs)
125- if tag == "picture":
126- self.picture_refs = []
127- elif tag == "source" and self.picture_refs is not None:
128- for candidate in attrs.get("srcset", "").split(","):
129- candidate = candidate.strip().split()[0] if candidate.strip() else ""
130- if candidate:
131- self.picture_refs.append((self.getpos()[0], "", candidate))
132- elif tag == "img" and self.picture_refs is not None and attrs.get("src"):
133- self.picture_refs.append(
134- (self.getpos()[0], attrs.get("alt", ""), attrs["src"])
135- )
136-
137- def handle_endtag(self, tag):
138- if tag != "picture" or self.picture_refs is None:
139- return
140- fallback_alt = next((alt for _, alt, _ in self.picture_refs if alt), "")
141- for line, alt, image_path in self.picture_refs:
142- add_ref(self.source_file, line, alt or fallback_alt, image_path)
143- self.picture_refs = None
144-
145- for source_file in sorted(pathlib.Path("workshop").glob("*.md")):
146- parser = PictureParser(source_file)
147- parser.feed(source_file.read_text(encoding="utf-8"))
148-
149- refs_path.write_text(json.dumps(refs, indent=2), encoding="utf-8")
150- PY
90+ python3 -c "$(printf '%s\n' \
91+ 'import json' \
92+ 'import pathlib' \
93+ 'from html.parser import HTMLParser' \
94+ '' \
95+ 'refs_path = pathlib.Path("/tmp/gh-aw/data/image-refs.json")' \
96+ 'refs = json.loads(refs_path.read_text())' \
97+ 'seen = {(record["file"], record["path"]) for record in refs}' \
98+ '' \
99+ 'def add_ref(source_file, line, alt, image_path):' \
100+ ' image_path = image_path.strip()' \
101+ ' if not image_path or image_path.startswith(("http://", "https://", "data:")):' \
102+ ' return' \
103+ ' key = (str(source_file), image_path)' \
104+ ' if key in seen:' \
105+ ' return' \
106+ ' seen.add(key)' \
107+ ' resolved = (source_file.parent / image_path).resolve()' \
108+ ' refs.append({' \
109+ ' "file": str(source_file),' \
110+ ' "line": line,' \
111+ ' "alt": alt,' \
112+ ' "path": image_path,' \
113+ ' "resolved": str(resolved),' \
114+ ' "exists": resolved.is_file(),' \
115+ ' })' \
116+ '' \
117+ 'class PictureParser(HTMLParser):' \
118+ ' def __init__(self, source_file):' \
119+ ' super().__init__()' \
120+ ' self.source_file = source_file' \
121+ ' self.picture_refs = None' \
122+ '' \
123+ ' def handle_starttag(self, tag, attrs):' \
124+ ' attrs = dict(attrs)' \
125+ ' if tag == "picture":' \
126+ ' self.picture_refs = []' \
127+ ' elif tag == "source" and self.picture_refs is not None:' \
128+ ' for candidate in attrs.get("srcset", "").split(","):' \
129+ ' candidate = candidate.strip().split()[0] if candidate.strip() else ""' \
130+ ' if candidate:' \
131+ ' self.picture_refs.append((self.getpos()[0], "", candidate))' \
132+ ' elif tag == "img" and self.picture_refs is not None and attrs.get("src"):' \
133+ ' self.picture_refs.append((self.getpos()[0], attrs.get("alt", ""), attrs["src"]))' \
134+ '' \
135+ ' def handle_endtag(self, tag):' \
136+ ' if tag != "picture" or self.picture_refs is None:' \
137+ ' return' \
138+ ' fallback_alt = next((alt for _, alt, _ in self.picture_refs if alt), "")' \
139+ ' for line, alt, image_path in self.picture_refs:' \
140+ ' add_ref(self.source_file, line, alt or fallback_alt, image_path)' \
141+ ' self.picture_refs = None' \
142+ '' \
143+ 'for source_file in sorted(pathlib.Path("workshop").glob("*.md")):' \
144+ ' parser = PictureParser(source_file)' \
145+ ' parser.feed(source_file.read_text(encoding="utf-8"))' \
146+ '' \
147+ 'refs_path.write_text(json.dumps(refs, indent=2), encoding="utf-8")'
148+ )"
151149
152150 echo "$existing_images" > /tmp/gh-aw/data/existing-images.json
153151
0 commit comments