Directory in which to place assets when using `--assets=external`. Defaults to "assets".
`--lint-spec`
`lintSpec`
Enforce some style and correctness checks.
`--error-formatter`
The eslint formatter to be used for printing warnings and errors when using `--verbose`. Either the name of a built-in eslint formatter or the package name of an installed eslint compatible formatter.
+
`--max-clause-depth N`
Warn when clauses exceed a nesting depth of N, and cause those clauses to be numbered by incrementing their parent clause's number rather than by nesting a new number within their parent clause.
`--strict`
Exit with an error if there are warnings. Cannot be used with `--watch`.
`--multipage`
Emit a distinct page for each top-level clause.
diff --git a/src/args.ts b/src/args.ts
index f7aa0277..9c4453cc 100644
--- a/src/args.ts
+++ b/src/args.ts
@@ -67,6 +67,12 @@ export const options = [
description:
'The formatter for warnings and errors; either a path prefixed with "." or "./", or package name, of an installed eslint compatible formatter (default: eslint-formatter-codeframe)',
},
+ {
+ name: 'max-clause-depth',
+ type: Number,
+ description:
+ 'The maximum nesting depth for clauses; exceeding this will cause a warning. Defaults to no limit.',
+ },
{
name: 'multipage',
type: Boolean,
diff --git a/src/clauseNums.ts b/src/clauseNums.ts
index f77f1631..143a6c06 100644
--- a/src/clauseNums.ts
+++ b/src/clauseNums.ts
@@ -9,6 +9,8 @@ export default function iterator(spec: Spec): ClauseNumberIterator {
const ids: (string | number[])[] = [];
let inAnnex = false;
let currentLevel = 0;
+ let hasWarnedForExcessNesting = false;
+ const MAX_LEVELS = spec.opts.maxClauseDepth ?? Infinity;
return {
next(clauseStack: Clause[], node: HTMLElement) {
@@ -22,28 +24,47 @@ export default function iterator(spec: Spec): ClauseNumberIterator {
message: 'clauses cannot follow annexes',
});
}
- if (level - currentLevel > 1) {
+ if (level - currentLevel > 1 && (level < MAX_LEVELS || currentLevel < MAX_LEVELS - 1)) {
spec.warn({
type: 'node',
node,
- ruleId: 'skipped-caluse',
+ ruleId: 'skipped-clause',
message: 'clause is being numbered without numbering its parent clause',
});
}
+ if (!hasWarnedForExcessNesting && level + 1 > (spec.opts.maxClauseDepth ?? Infinity)) {
+ spec.warn({
+ type: 'node',
+ node,
+ ruleId: 'max-clause-depth',
+ message: `clause exceeds maximum nesting depth of ${spec.opts.maxClauseDepth}`,
+ });
+ hasWarnedForExcessNesting = true;
+ }
const nextNum = annex ? nextAnnexNum : nextClauseNum;
- if (level === currentLevel) {
- ids[currentLevel] = nextNum(clauseStack, node);
- } else if (level > currentLevel) {
- ids.push(nextNum(clauseStack, node));
+ if (level >= MAX_LEVELS) {
+ if (ids.length === MAX_LEVELS) {
+ const lastLevelIndex = MAX_LEVELS - 1;
+ const lastLevel = ids[lastLevelIndex] as number[];
+ lastLevel[lastLevel.length - 1]++;
+ } else {
+ while (ids.length < MAX_LEVELS) {
+ ids.push([1]);
+ }
+ }
} else {
- ids.length = level + 1;
- ids[level] = nextNum(clauseStack, node);
+ if (level === currentLevel) {
+ ids[currentLevel] = nextNum(clauseStack, node);
+ } else if (level > currentLevel) {
+ ids.push(nextNum(clauseStack, node));
+ } else {
+ ids.length = level + 1;
+ ids[level] = nextNum(clauseStack, node);
+ }
}
-
- currentLevel = level;
-
+ currentLevel = Math.min(level, MAX_LEVELS - 1);
return ids.flat().join('.');
},
};
diff --git a/src/cli.ts b/src/cli.ts
index cf96ee93..fd038dbc 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -113,6 +113,9 @@ const build = debounce(async function build() {
if (args['mark-effects']) {
opts.markEffects = true;
}
+ if (args['max-clause-depth']) {
+ opts.maxClauseDepth = args['max-clause-depth'];
+ }
if (args['no-toc'] != null) {
opts.toc = !args['no-toc'];
}
diff --git a/src/ecmarkup.ts b/src/ecmarkup.ts
index 34aae168..815b37e8 100644
--- a/src/ecmarkup.ts
+++ b/src/ecmarkup.ts
@@ -32,6 +32,7 @@ export interface Options {
copyright?: boolean;
date?: Date;
location?: string;
+ maxClauseDepth?: number;
multipage?: boolean;
extraBiblios?: ExportedBiblio[];
contributors?: string;
diff --git a/test/baselines/generated-reference/max-clause-depth.html b/test/baselines/generated-reference/max-clause-depth.html
new file mode 100644
index 00000000..a9cc5bca
--- /dev/null
+++ b/test/baselines/generated-reference/max-clause-depth.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/baselines/sources/max-clause-depth.html b/test/baselines/sources/max-clause-depth.html
new file mode 100644
index 00000000..3643aeca
--- /dev/null
+++ b/test/baselines/sources/max-clause-depth.html
@@ -0,0 +1,35 @@
+
+
+
+
+