Skip to content

Commit

Permalink
Walk the tree rather than use selectors in canonicalizeShortcuts().
Browse files Browse the repository at this point in the history
  • Loading branch information
tabatkins committed Jan 24, 2025
1 parent d514ece commit fc84dc9
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 63 deletions.
2 changes: 1 addition & 1 deletion bikeshed/Spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def processDocument(self) -> Spec:
boilerplate.removeUnwantedBoilerplate(self)
shorthands.run(self)
inlineTags.processTags(self)
u.canonicalizeShortcuts(self)
u.canonicalizeShortcuts(self.body)
u.addImplicitAlgorithms(self)
u.fixManualDefTables(self)
headings.processHeadings(self)
Expand Down
2 changes: 1 addition & 1 deletion bikeshed/conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

def processConditionals(doc: t.SpecT, container: t.ElementT | None = None) -> None:
for el in h.findAll("[include-if], [exclude-if], if-wrapper", container if container is not None else doc):
if el.tag == "if-wrapper" and not h.hasAttr(el, "include-if", "exclude-if"):
if el.tag == "if-wrapper" and not h.hasAnyAttr(el, "include-if", "exclude-if"):
m.die(
"<if-wrapper> elements must have an include-if and/or exclude-if attribute.",
el=el,
Expand Down
2 changes: 2 additions & 0 deletions bikeshed/h/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
fixupIDs,
foldWhitespace,
hasAncestor,
hasAnyAttr,
hasAttr,
hasAttrs,
hasChildElements,
Expand Down Expand Up @@ -60,6 +61,7 @@
removeAttr,
removeClass,
removeNode,
renameAttr,
replaceContents,
replaceMacrosTextly,
replaceNode,
Expand Down
16 changes: 15 additions & 1 deletion bikeshed/h/dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,11 +696,25 @@ def removeAttr(el: t.ElementT, *attrNames: str) -> t.ElementT:
return el


def hasAttr(el: t.ElementT, *attrNames: str) -> bool:
def renameAttr(el: t.ElementT, oldAttr: str, newAttr: str) -> t.ElementT:
# If oldAttr exists on the element, moves its value to newAttr
# and deletes oldAttr. Silently does nothing if oldAttr doesn't exist.
val = el.get(oldAttr)
if val is not None:
el.set(newAttr, val)
removeAttr(el, oldAttr)
return el


def hasAnyAttr(el: t.ElementT, *attrNames: str) -> bool:
# Returns True if the element has at least one of the named attributes
return any(attrName in el.attrib for attrName in attrNames)


def hasAttr(el: t.ElementT, attrName: str) -> bool:
return attrName in el.attrib


def hasAttrs(el: t.ElementT) -> bool:
return bool(el.attrib)

Expand Down
104 changes: 56 additions & 48 deletions bikeshed/unsortedJunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,60 +51,68 @@ def fixManualDefTables(doc: t.SpecT) -> None:
h.replaceContents(cell, newContents)


def canonicalizeShortcuts(doc: t.SpecT) -> None:
def canonicalizeShortcuts(el: t.ElementT) -> None:
# Take all the invalid-HTML shortcuts and fix them.

attrFixup = {
"export": "data-export",
"noexport": "data-noexport",
"link-spec": "data-link-spec",
"spec": "data-link-spec",
"link-status": "data-link-status",
"status": "data-link-status",
"dfn-for": "data-dfn-for",
"link-for": "data-link-for",
"link-for-hint": "data-link-for-hint",
"dfn-type": "data-dfn-type",
"link-type": "data-link-type",
"dfn-force": "data-dfn-force",
"force": "data-dfn-force",
"section": "data-section",
"attribute-info": "data-attribute-info",
"dict-member-info": "data-dict-member-info",
"lt": "data-lt",
"local-lt": "data-local-lt",
"algorithm": "data-algorithm",
"ignore": "data-var-ignore",
}
for el in h.findAll(",".join(f"[{attr}]" for attr in attrFixup), doc):
for attr, fixedAttr in attrFixup.items():
if el.get(attr) is not None:
el.set(fixedAttr, t.cast(str, el.get(attr)))
del el.attrib[attr]

# The next two aren't in the above dict because some of the words conflict with existing attributes on some elements.
h.renameAttr(el, "export", "data-export")
h.renameAttr(el, "noexport", "data-noexport")
h.renameAttr(el, "link-spec", "data-link-spec")
h.renameAttr(el, "spec", "data-link-spec")
h.renameAttr(el, "link-status", "data-link-status")
h.renameAttr(el, "status", "data-link-status")
h.renameAttr(el, "dfn-for", "data-dfn-for")
h.renameAttr(el, "link-for", "data-link-for")
h.renameAttr(el, "link-for-hint", "data-link-for-hint")
h.renameAttr(el, "dfn-type", "data-dfn-type")
h.renameAttr(el, "link-type", "data-link-type")
h.renameAttr(el, "dfn-force", "data-dfn-force")
h.renameAttr(el, "force", "data-dfn-force")
h.renameAttr(el, "section", "data-section")
h.renameAttr(el, "attribute-info", "data-attribute-info")
h.renameAttr(el, "dict-member-info", "data-dict-member-info")
h.renameAttr(el, "lt", "data-lt")
h.renameAttr(el, "local-lt", "data-local-lt")
h.renameAttr(el, "algorithm", "data-algorithm")
h.renameAttr(el, "ignore", "data-var-ignore")

# Some of these attrs conflict with existing real attributes on some elements.
# Instead, limit the search/transforms to the relevant elements.
for el in h.findAll("dfn, h2, h3, h4, h5, h6", doc):
tag = h.tagName(el)
if tag in ("dfn", "h2", "h3", "h4", "h5", "h6"):
for dfnType in config.dfnTypes:
if el.get(dfnType) == "":
del el.attrib[dfnType]
el.set("data-dfn-type", dfnType)
break
for el in h.findAll("a", doc):
if h.hasAttr(el, dfnType):
if el.get(dfnType) == "":
h.removeAttr(el, dfnType)
el.set("data-dfn-type", dfnType)
break
elif dfnType == "type" and el.get(dfnType) in config.dfnTypes:
realDfnType = el.get(dfnType)
m.die(
f"You used type={realDfnType}, which isn't valid. Instead use just {realDfnType} as a boolean attribute, or dfn-type={realDfnType}.",
el=el,
)
h.removeAttr(el, "type")
break

if tag == "a":
for linkType in config.linkTypes:
if el.get(linkType) is not None:
del el.attrib[linkType]
if h.hasAttr(el, linkType):
h.removeAttr(el, linkType)
el.set("data-link-type", linkType)
break
for el in h.findAll(config.dfnElementsSelector + ", a", doc):
if el.get("for") is None:
continue
_for = t.cast(str, el.get("for"))
del el.attrib["for"]
if el.tag == "a":
el.set("data-link-for", _for)
else:
el.set("data-dfn-for", _for)

if (
tag == "a"
or (tag == "dfn" and not h.hasAttr(el, "data-var-ignore"))
or (tag in ("h2", "h3", "h4", "h5", "h6") and h.hasAttr(el, "data-dfn-type"))
):
if h.hasAttr(el, "for"):
if el.tag == "a":
h.renameAttr(el, "for", "data-link-for")
else:
h.renameAttr(el, "for", "data-dfn-for")

for child in h.childElements(el):
canonicalizeShortcuts(child)


def addImplicitAlgorithms(doc: t.SpecT) -> None:
Expand Down
3 changes: 3 additions & 0 deletions tests/github/WICG/sms-one-time-codes/index.console.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
LINE 166:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 186:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 196:5: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 71:39: Multiple possible 'same site' dfn refs.
Arbitrarily chose https://html.spec.whatwg.org/multipage/browsers.html#concept-site-same-site
To auto-select one of the following refs, insert one of these lines into a <pre class=link-defaults> block:
Expand Down
6 changes: 3 additions & 3 deletions tests/github/WICG/sms-one-time-codes/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ <h3 class="heading settled" data-level="3.1" id="authoring"><span class="secno">
</div>
</div>
<h3 class="heading settled" data-level="3.2" id="parsing"><span class="secno">3.2. </span><span class="content">Parsing</span><a class="self-link" href="#parsing"></a></h3>
<p>To <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="parse-an-origin-bound-one-time-code-message" type="abstract-op">parse an origin-bound one-time code message</dfn> from <var>message</var>, run these steps:</p>
<p>To <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="parse-an-origin-bound-one-time-code-message">parse an origin-bound one-time code message</dfn> from <var>message</var>, run these steps:</p>
<ol>
<li data-md>
<p>Let <var>line</var> be the <a data-link-type="dfn" href="#last-line" id="ref-for-last-line">last line</a> of <var>message</var>, and <var>position</var> be 0.</p>
Expand Down Expand Up @@ -791,7 +791,7 @@ <h3 class="heading settled" data-level="3.2" id="parsing"><span class="secno">3.
<li data-md>
<p>Return the <a data-link-type="dfn" href="#origin-bound-one-time-code" id="ref-for-origin-bound-one-time-code①⓪">origin-bound one-time code</a> (<var>top-level origin</var>, <var>embedded origin</var>, <var>code</var>).</p>
</ol>
<p>To <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-marked-token" type="abstract-op">extract a marked token</dfn> from <var>string</var> at <var>position</var> with <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#code-point" id="ref-for-code-point②">code point</a> <var>marker</var>, run the following steps:</p>
<p>To <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-marked-token">extract a marked token</dfn> from <var>string</var> at <var>position</var> with <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#code-point" id="ref-for-code-point②">code point</a> <var>marker</var>, run the following steps:</p>
<ol>
<li data-md>
<p>If <var>position</var> points past the end of <var>string</var>, return failure.</p>
Expand All @@ -808,7 +808,7 @@ <h3 class="heading settled" data-level="3.2" id="parsing"><span class="secno">3.
<li data-md>
<p>Return <var>token</var>.</p>
</ol>
<p>The <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="last-line" type="abstract-op">last line</dfn> of <var>string</var> is the result of running these steps:</p>
<p>The <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="last-line">last line</dfn> of <var>string</var> is the result of running these steps:</p>
<ol>
<li data-md>
<p><a data-link-type="dfn" href="https://infra.spec.whatwg.org/#normalize-newlines" id="ref-for-normalize-newlines">Normalize newlines</a> in <var>string</var>.</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
LINE 147:1: Saw an end tag </div>, but there's no open element corresponding to it.
LINE 191:9: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 210:9: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ <h2 class="heading settled" data-level="8" id="n-bit-decimal-values"><span class
<p>The <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string②">strings</a> <code>"00"</code> and <code>"15"</code> are both <a data-link-type="dfn" href="#four-bit-decimal-value" id="ref-for-four-bit-decimal-value①">four-bit decimal values</a>, whereas <code>"7"</code>, <code>"20"</code>, and <code>"!!11one"</code> are not.</p>
</div>
<div class="algorithm" data-algorithm="extract a four-bit decimal value">
<p>Clients <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-four-bit-decimal-value" type="abstract-op">extract a four-bit decimal value</dfn> from a <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string③">string</a> <var>string</var> by running these steps:</p>
<p>Clients <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-four-bit-decimal-value">extract a four-bit decimal value</dfn> from a <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string③">string</a> <var>string</var> by running these steps:</p>
<ol>
<li data-md>
<p>If <var>string</var>’s <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string-length" id="ref-for-string-length">length</a> is not 2, return failure.</p>
Expand All @@ -991,7 +991,7 @@ <h2 class="heading settled" data-level="8" id="n-bit-decimal-values"><span class
<p>The <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string④">strings</a> <code>"00"</code> and <code>"63"</code> are both <a data-link-type="dfn" href="#six-bit-decimal-value" id="ref-for-six-bit-decimal-value①">six-bit decimal values</a>, whereas <code>"7"</code>, <code>"98"</code>, and <code>"!!11one"</code> are not.</p>
</div>
<div class="algorithm" data-algorithm="extract a six-bit decimal value">
<p>Clients <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-six-bit-decimal-value" type="abstract-op">extract a six-bit decimal value</dfn> from a <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string⑤">string</a> <var>string</var> by running these steps:</p>
<p>Clients <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="extract-a-six-bit-decimal-value">extract a six-bit decimal value</dfn> from a <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string" id="ref-for-string⑤">string</a> <var>string</var> by running these steps:</p>
<ol>
<li data-md>
<p>If <var>string</var>’s <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#string-length" id="ref-for-string-length①">length</a> is not 2, return failure.</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
LINE 121:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 133:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 148:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 155:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 225:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 235:4: You used type=abstract-op, which isn't valid. Instead use just abstract-op as a boolean attribute, or dfn-type=abstract-op.
LINE 301:1: Image doesn't exist, so I couldn't determine its width and height: 'images/storage-access-prompt.png'
LINE 101:325: Multiple possible 'same site' dfn refs.
Arbitrarily chose https://html.spec.whatwg.org/multipage/browsers.html#concept-site-same-site
Expand Down
Loading

0 comments on commit fc84dc9

Please sign in to comment.