imbajin commented on code in PR #514:
URL: https://github.com/apache/hugegraph-doc/pull/514#discussion_r4241694231
##########
dist/validate-site-output.py:
##########
@@ -925,6 +940,83 @@ def handle_endtag(self, tag: str) -> None:
if tag in {"main", "article"} and self._content_depth:
self._content_depth -= 1
+ def _check_component_payload(self) -> None:
+ try:
+ payload = json.loads(self._component_json)
+ except (ValueError, RecursionError):
+ self.authored_violations.append("invalid OINK component JSON
payload")
+ return
+ if not isinstance(payload, dict):
+ self.authored_violations.append("OINK component JSON payload must
be an object")
+ return
+ if self._component_source == "data-td-asciinema-config":
+ # Trust only the shortcode schema, not the player's much broader
+ # API (audioUrl, custom drivers, etc. can initiate other requests).
+ option_keys = {"autoPlay", "fit", "loop", "preload", "speed",
"startAt", "poster", "cols", "rows",
+ "idleTimeLimit", "pauseOnMarkers", "markers"}
+ options = payload.get("options")
+ if (set(payload) != {"src", "theme", "options"} or not
isinstance(payload.get("theme"), str)
+ or not isinstance(options, dict) or set(options) -
option_keys):
+ self.authored_violations.append("Asciinema JSON payload does
not match the OINK shortcode schema")
+ return
+ for key, value in options.items():
+ valid = True
+ if key in {"autoPlay", "loop", "preload", "pauseOnMarkers"}:
+ valid = isinstance(value, bool)
+ elif key == "fit":
+ valid = isinstance(value, str) and value in {"width",
"height", "both", "none"}
+ elif key in {"cols", "rows"}:
+ valid = type(value) is int and value > 0
+ elif key in {"speed", "startAt", "idleTimeLimit"}:
+ valid = type(value) in {int, float} and value >= 0 and
(key != "speed" or value > 0)
+ elif key == "poster":
+ # The pinned player _parsePoster accepts terminal text or a
+ # recording timestamp; it does not load an image/URL.
+ valid = isinstance(value, str) and
value.startswith(("npt:", "data:text/plain,"))
+ elif key == "markers":
+ valid = isinstance(value, list) and all(isinstance(item,
list) and len(item) == 2 and
Review Comment:
🧹 Blocking: no. Summary: The validator rejects the marker shape emitted by
the pinned Asciinema shortcode. Evidence: OINK v1.2.0 serializes
markers="10:Boot,25:Configure" as a flat sequence, while this condition
requires nested [time,label] pairs. Please validate the emitted flat sequence
(or align with the pinned schema) and add a fixture based on rendered output.
##########
dist/validate-site-output.py:
##########
@@ -925,6 +940,83 @@ def handle_endtag(self, tag: str) -> None:
if tag in {"main", "article"} and self._content_depth:
self._content_depth -= 1
+ def _check_component_payload(self) -> None:
+ try:
+ payload = json.loads(self._component_json)
+ except (ValueError, RecursionError):
+ self.authored_violations.append("invalid OINK component JSON
payload")
+ return
+ if not isinstance(payload, dict):
+ self.authored_violations.append("OINK component JSON payload must
be an object")
+ return
+ if self._component_source == "data-td-asciinema-config":
+ # Trust only the shortcode schema, not the player's much broader
+ # API (audioUrl, custom drivers, etc. can initiate other requests).
+ option_keys = {"autoPlay", "fit", "loop", "preload", "speed",
"startAt", "poster", "cols", "rows",
+ "idleTimeLimit", "pauseOnMarkers", "markers"}
+ options = payload.get("options")
+ if (set(payload) != {"src", "theme", "options"} or not
isinstance(payload.get("theme"), str)
+ or not isinstance(options, dict) or set(options) -
option_keys):
+ self.authored_violations.append("Asciinema JSON payload does
not match the OINK shortcode schema")
+ return
+ for key, value in options.items():
+ valid = True
+ if key in {"autoPlay", "loop", "preload", "pauseOnMarkers"}:
+ valid = isinstance(value, bool)
+ elif key == "fit":
+ valid = isinstance(value, str) and value in {"width",
"height", "both", "none"}
+ elif key in {"cols", "rows"}:
+ valid = type(value) is int and value > 0
+ elif key in {"speed", "startAt", "idleTimeLimit"}:
+ valid = type(value) in {int, float} and value >= 0 and
(key != "speed" or value > 0)
+ elif key == "poster":
+ # The pinned player _parsePoster accepts terminal text or a
+ # recording timestamp; it does not load an image/URL.
+ valid = isinstance(value, str) and
value.startswith(("npt:", "data:text/plain,"))
+ elif key == "markers":
+ valid = isinstance(value, list) and all(isinstance(item,
list) and len(item) == 2 and
+ type(item[0]) in {int, float} and item[0] >= 0 and
isinstance(item[1], str) for item in value)
+ if not valid:
+ self.authored_violations.append(f"invalid Asciinema
shortcode option: {key}")
+ source = payload.get("src")
+ if not isinstance(source, str) or not source:
+ self.authored_violations.append("Asciinema JSON payload
requires a source URL")
+ else:
+ self.resources.append(("asciinema-config", "src", source))
+ self.urls.append(("src", source))
+ return
+ # ECharts directly loads image:// symbols/icons and image URLs in
+ # graphic styles/rich-text backgrounds. Formatter strings can become
+ # HTML inside its default tooltip renderer and need the authored rules.
+ pending = [("", payload)]
+ while pending:
+ key, value = pending.pop()
+ if isinstance(value, dict):
+ pending.extend(value.items())
+ elif isinstance(value, list):
+ pending.extend((key, item) for item in value)
+ elif isinstance(value, str):
+ resource = value[len("image://"):] if
value.startswith("image://") else value if key in {"image", "src", "url",
"href"} else None
Review Comment:
⚠️ Blocking: yes. Summary: CSS URLs in ECharts options bypass the
external-resource check. Evidence: The pinned ECharts bundle appends
tooltip.extraCssText to tooltip CSS; this traversal only extracts URL-valued
fields and formatter HTML, so background:url(https://example.org/track) is not
added to inline_css_sources or checked by document_security_errors(). Please
inspect CSS-bearing fields such as tooltip.extraCssText with
css_resource_urls() and the same-origin check, and add a regression case.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]