diff --git a/src/Clause.ts b/src/Clause.ts
index b6ae5b2c..105a76ef 100644
--- a/src/Clause.ts
+++ b/src/Clause.ts
@@ -86,6 +86,10 @@ export default class Clause extends Builder {
this.buildStructuredHeader(header);
}
this.header = header;
+ if (header == null) {
+ this.title = 'UNKNOWN';
+ this.titleHTML = 'UNKNOWN';
+ }
}
buildStructuredHeader(header: Element) {
@@ -240,26 +244,6 @@ export default class Clause extends Builder {
static exit({ node, spec, clauseStack, inAlg, currentId }: Context) {
const clause = clauseStack[clauseStack.length - 1];
- const header = clause.header;
- if (header == null) {
- clause.title = 'UNKNOWN';
- clause.titleHTML = 'UNKNOWN';
- } else {
- const headerClone = header.cloneNode(true) as Element;
- for (const a of headerClone.querySelectorAll('a')) {
- a.replaceWith(...a.childNodes);
- }
- clause.titleHTML = headerClone.innerHTML;
- clause.title = headerClone.textContent;
- if (clause.number) {
- const numElem = clause.spec.doc.createElement('span');
- numElem.setAttribute('class', 'secnum');
- numElem.textContent = clause.number;
- header.insertBefore(clause.spec.doc.createTextNode(' '), header.firstChild);
- header.insertBefore(numElem, header.firstChild);
- }
- }
-
clause.buildExamples();
clause.buildNotes();
diff --git a/src/H1.ts b/src/H1.ts
new file mode 100644
index 00000000..a47459d1
--- /dev/null
+++ b/src/H1.ts
@@ -0,0 +1,30 @@
+import Builder from './Builder';
+import type { Context } from './Context';
+
+export default class H1 extends Builder {
+ static elements = ['H1'];
+
+ static async enter() {
+ // do nothing
+ }
+
+ static async exit({ spec, node, clauseStack }: Context) {
+ const parent = clauseStack[clauseStack.length - 1] || null;
+ if (parent === null || parent.header !== node) {
+ return;
+ }
+ const headerClone = node.cloneNode(true) as Element;
+ for (const a of headerClone.querySelectorAll('a')) {
+ a.replaceWith(...a.childNodes);
+ }
+ parent.titleHTML = headerClone.innerHTML;
+ parent.title = headerClone.textContent;
+ if (parent.number) {
+ const numElem = spec.doc.createElement('span');
+ numElem.setAttribute('class', 'secnum');
+ numElem.textContent = parent.number;
+ node.insertBefore(spec.doc.createTextNode(' '), node.firstChild);
+ node.insertBefore(numElem, node.firstChild);
+ }
+ }
+}
diff --git a/src/Meta.ts b/src/Meta.ts
index f7dd996d..561cff0e 100644
--- a/src/Meta.ts
+++ b/src/Meta.ts
@@ -3,7 +3,8 @@ import type { Context } from './Context';
import Builder from './Builder';
-import { validateEffects } from './utils';
+import { validateEffects, doesEffectPropagateToParent } from './utils';
+import { maybeAddClauseToEffectWorklist } from './Spec';
export default class Meta extends Builder {
static elements = ['EMU-META'];
@@ -20,13 +21,13 @@ export default class Meta extends Builder {
node
);
for (const effect of effects) {
- if (!parent.effects.includes(effect)) {
- parent.effects.push(effect);
- if (!spec._effectWorklist.has(effect)) {
- spec._effectWorklist.set(effect, []);
- }
- spec._effectWorklist.get(effect)!.push(parent);
+ if (!doesEffectPropagateToParent(node, effect)) {
+ continue;
}
+ if (!spec._effectWorklist.has(effect)) {
+ spec._effectWorklist.set(effect, []);
+ }
+ maybeAddClauseToEffectWorklist(effect, parent, spec._effectWorklist.get(effect)!);
}
}
spec._emuMetasToRender.add(node);
diff --git a/src/Spec.ts b/src/Spec.ts
index ab774f9a..a1b5ef5a 100644
--- a/src/Spec.ts
+++ b/src/Spec.ts
@@ -29,6 +29,7 @@ import Xref from './Xref';
import Eqn from './Eqn';
import Biblio from './Biblio';
import Meta from './Meta';
+import H1 from './H1';
import {
autolink,
replacerForNamespace,
@@ -78,6 +79,7 @@ const builders: BuilderInterface[] = [
ProdRef,
Note,
Meta,
+ H1,
];
const visitorMap = builders.reduce((map, T) => {
@@ -258,7 +260,11 @@ function isEmuImportElement(node: Node): node is EmuImportElement {
return node.nodeType === 1 && node.nodeName === 'EMU-IMPORT';
}
-function maybeAddClauseToEffectWorklist(effectName: string, clause: Clause, worklist: Clause[]) {
+export function maybeAddClauseToEffectWorklist(
+ effectName: string,
+ clause: Clause,
+ worklist: Clause[]
+) {
if (
!worklist.includes(clause) &&
clause.canHaveEffect(effectName) &&
diff --git a/src/Xref.ts b/src/Xref.ts
index 16fb973c..ca1475be 100644
--- a/src/Xref.ts
+++ b/src/Xref.ts
@@ -4,7 +4,7 @@ import type * as Biblio from './Biblio';
import type Clause from './Clause';
import Builder from './Builder';
-import { validateEffects } from './utils';
+import { validateEffects, doesEffectPropagateToParent } from './utils';
/*@internal*/
export default class Xref extends Builder {
@@ -91,36 +91,10 @@ export default class Xref extends Builder {
shouldPropagateEffect(effectName: string) {
if (!this.isInvocation) return false;
if (this.clause) {
- // Xrefs should not propagate past explicit fences in parent steps. Fences
- // must be at the beginning of steps.
- //
- // Abstract Closures are considered automatic fences for the user-code
- // effect, since those are effectively nested functions.
- //
- // Calls to Abstract Closures that can call user code must be explicitly
- // marked as such with
The abstract operation FencedEffects takes no arguments. Effects don't propagate past fences in parent steps. A fence must be at the beginning of a step. It performs the following steps when called:
-