diff --git a/.mocharc.cjs b/.mocharc.cjs index 8e66872..87227d3 100644 --- a/.mocharc.cjs +++ b/.mocharc.cjs @@ -1,5 +1,9 @@ module.exports = { ui: "bdd", - spec: ["test/**/**.spec.ts"], + spec: [ + "test/common/data.spec.ts", + "test/common/heading.spec.ts", + "test/**/**.spec.ts", + ], import: "tsx", }; diff --git a/common/counter.ts b/common/counter.ts index d31d061..e0ee415 100644 --- a/common/counter.ts +++ b/common/counter.ts @@ -1,5 +1,9 @@ -import type { BaseDecoratorOptions, DecoratorOptions } from "./data"; -import { defaultHeadingTuple } from "./data"; +import type { + OrderedDecoratorOptions, + IndependentDecoratorOptions, + IndependentDecoratorSettings, +} from "./data"; +import { getOrderedCustomIdents } from "./data"; import * as presets from "@jsamr/counter-style/presets"; export class Querier { @@ -69,47 +73,12 @@ export class Querier { } } -export class Counter extends Querier { - private decoratorOptions: DecoratorOptions; - - constructor(decoratorOptions?: BaseDecoratorOptions) { +export class OrderedCounter extends Querier implements Counter { + constructor(private decoratorOptions: OrderedDecoratorOptions) { super(decoratorOptions?.allowZeroLevel, decoratorOptions?.maxRecLevel); - if (decoratorOptions) { - if (decoratorOptions.ordered) { - const { - styleType, - delimiter, - trailingDelimiter, - customTrailingDelimiter, - leadingDelimiter, - customLeadingDelimiter, - customIdents, - specifiedString, - ignoreTopLevel, - } = decoratorOptions; - this.decoratorOptions = { - ordered: true, - styleType: styleType || "decimal", - delimiter, - trailingDelimiter, - customTrailingDelimiter, - leadingDelimiter, - customLeadingDelimiter, - customIdents, - specifiedString, - ignoreTopLevel, - }; - } else { - this.decoratorOptions = { - ordered: false, - levelHeadings: decoratorOptions.levelHeadings || [ - ...defaultHeadingTuple, - ], - }; - } - } else { - this.decoratorOptions = { ordered: true, styleType: "decimal" }; // Default to ordered if no options are provided + if (!decoratorOptions.styleType) { + this.decoratorOptions.styleType = "decimal"; // Default to ordered if no options are provided } } @@ -119,49 +88,160 @@ export class Counter extends Querier { return result; } - if (this.decoratorOptions.ordered) { - let results: string[] = []; - const { - styleType, - delimiter = ".", - trailingDelimiter = false, - customTrailingDelimiter = "", - leadingDelimiter = false, - customLeadingDelimiter = "", - specifiedString = "#", - customIdents = [], - ignoreTopLevel = 0, - } = this.decoratorOptions; - const levels = this.handler(level).slice(ignoreTopLevel); + let results: string[] = []; + const { + styleType = "decimal", + delimiter = ".", + trailingDelimiter = false, + customTrailingDelimiter = "", + leadingDelimiter = false, + customLeadingDelimiter = "", + specifiedString = "#", + customIdents = [], + ignoreTopLevel = 0, + } = this.decoratorOptions; + const levels = this.handler(level).slice(ignoreTopLevel); - switch (styleType) { - case "customIdent": - results = levels.map((level) => - level > customIdents.length - ? level.toString() - : customIdents[level - 1] - ); - break; - case "string": - results = levels.map(() => specifiedString.trim() || "#"); - break; - default: - results = levels.map((level) => - presets[styleType].renderCounter(level) - ); - } + switch (styleType) { + case "customIdent": + results = levels.map((level) => + level > customIdents.length + ? level.toString() + : customIdents[level - 1] + ); + break; + case "string": + results = levels.map(() => specifiedString.trim() || "#"); + break; + default: + results = levels.map((level) => + presets[styleType].renderCounter(level) + ); + } - result = results.join(delimiter); - if (result.length > 0) { - result = - (leadingDelimiter ? customLeadingDelimiter || delimiter : "") + - result + - (trailingDelimiter ? customTrailingDelimiter || delimiter : ""); - } - } else { - result = this.decoratorOptions.levelHeadings[level - 1]; + result = results.join(delimiter); + if (result.length > 0) { + result = + (leadingDelimiter ? customLeadingDelimiter || delimiter : "") + + result + + (trailingDelimiter ? customTrailingDelimiter || delimiter : ""); } return result; } } + +export class IndependentCounter extends Querier implements Counter { + constructor(private decoratorOptions: IndependentDecoratorOptions) { + super(decoratorOptions?.allowZeroLevel, decoratorOptions?.maxRecLevel); + } + + decorator(level: number): string { + let result = ""; + if (level < 1 || level > this.maxRecLevel) { + return result; + } + + let results: string[] = []; + let used: Partial; + const { + h1 = {}, + h2 = {}, + h3 = {}, + h4 = {}, + h5 = {}, + h6 = {}, + orderedRecLevel = 6, + ignoreTopLevel = 0, + } = this.decoratorOptions; + let levels = this.handler(level).slice(ignoreTopLevel); + + if (levels.length === 0) { + return result; + } + + const current = Math.min(level, orderedRecLevel); + switch (current) { + case 6: + used = h6; + break; + case 5: + used = h5; + break; + case 4: + used = h4; + break; + case 3: + used = h3; + break; + case 2: + used = h2; + break; + case 1: + default: + used = h1; + break; + } + if (level <= current) { + levels = levels.slice(-1); + } else { + levels = levels.slice(current - ignoreTopLevel - 1); + } + + const { + styleType = "decimal", + delimiter = ".", + trailingDelimiter = false, + customTrailingDelimiter = "", + leadingDelimiter = false, + customLeadingDelimiter = "", + customIdents = "", + specifiedString = "#", + } = used; + + switch (styleType) { + case "customIdent": + results = levels.map((level) => { + const ci = getOrderedCustomIdents(customIdents); + return level > ci.length ? level.toString() : ci[level - 1]; + }); + break; + case "string": + results = levels.map(() => specifiedString.trim() || "#"); + break; + default: + results = levels.map((level) => + presets[styleType].renderCounter(level) + ); + break; + } + + result = results.join(delimiter); + if (result.length > 0) { + result = + (leadingDelimiter ? customLeadingDelimiter || delimiter : "") + + result + + (trailingDelimiter ? customTrailingDelimiter || delimiter : ""); + } + + return result; + } +} + +export class UnorderedCounter implements Counter { + constructor(private levelHeadings: HeadingTuple, private maxRecLevel = 6) {} + + decorator(level: number): string { + let result = ""; + if (level < 1 || level > this.maxRecLevel) { + return result; + } + + result = this.levelHeadings[level - 1]; + return result; + } + + handler(): void { + //* do nothing. + } +} diff --git a/common/data.ts b/common/data.ts index 99fdd61..17102aa 100644 --- a/common/data.ts +++ b/common/data.ts @@ -9,8 +9,7 @@ export type OrderedCounterStyleType = | "customIdent" | "string"; -export interface BaseDecoratorOptions { - ordered: boolean; +export interface OrderedDecoratorOptions { styleType?: OrderedCounterStyleType; delimiter?: string; trailingDelimiter?: boolean; @@ -20,41 +19,60 @@ export interface BaseDecoratorOptions { customIdents?: string[]; specifiedString?: string; ignoreTopLevel?: number; - levelHeadings?: HeadingTuple; allowZeroLevel?: boolean; maxRecLevel?: number; } -interface OrderedDecoratorOptions { - ordered: true; +export interface IndependentDecoratorSettings { styleType: OrderedCounterStyleType; - delimiter?: string; - trailingDelimiter?: boolean; - customTrailingDelimiter?: string; - leadingDelimiter?: boolean; - customLeadingDelimiter?: string; - customIdents?: string[]; - specifiedString?: string; + delimiter: string; + trailingDelimiter: boolean; + customTrailingDelimiter: string; + leadingDelimiter: boolean; + customLeadingDelimiter: string; + customIdents: string; + specifiedString: string; +} + +export interface IndependentDecoratorOptions { + maxRecLevel?: number; + allowZeroLevel?: boolean; ignoreTopLevel?: number; + orderedRecLevel?: number; + + h1?: Partial; + h2?: Partial; + h3?: Partial; + h4?: Partial; + h5?: Partial; + h6?: Partial; } -interface UnorderedDecoratorOptions { - ordered: false; - levelHeadings: HeadingTuple; -} +interface IndependentSettings { + orderedRecLevel: number; -export type DecoratorOptions = - | OrderedDecoratorOptions - | UnorderedDecoratorOptions; + h1: IndependentDecoratorSettings; + h2: IndependentDecoratorSettings; + h3: IndependentDecoratorSettings; + h4: IndependentDecoratorSettings; + h5: IndependentDecoratorSettings; + h6: IndependentDecoratorSettings; +} export interface HeadingDecoratorSettings { enabledInEachNote?: boolean; - ordered: boolean; + decoratorMode?: DecoratorMode; opacity: OpacityOptions; position: PostionOptions; maxRecLevel?: number; + orderedAllowZeroLevel?: boolean; + orderedBasedOnExisting?: boolean; + orderedAlwaysIgnore?: boolean; + orderedIgnoreMaximum?: number; + orderedIgnoreSingle: boolean; + orderedStyleType: OrderedCounterStyleType; orderedDelimiter: string; orderedTrailingDelimiter: boolean; @@ -63,11 +81,8 @@ export interface HeadingDecoratorSettings { orderedCustomLeadingDelimiter?: string; orderedCustomIdents: string; orderedSpecifiedString: string; - orderedAllowZeroLevel?: boolean; - orderedBasedOnExisting?: boolean; - orderedAlwaysIgnore?: boolean; - orderedIgnoreSingle: boolean; - orderedIgnoreMaximum?: number; + + independentSettings?: IndependentSettings; unorderedLevelHeadings: string; } @@ -131,6 +146,8 @@ export const className = { after: "after-heading-decorator", afterInside: "after-inside-heading-decorator", hideSourceNumberSigns: "hide-source-number-signs", + settingContainer: "heading-decorator-setting-container", + settingItem: "heading-decorator-setting-item", }; export const headingsSelector = @@ -143,6 +160,38 @@ export const defaultHeadingTuple: HeadingTuple = [ "H5", "H6", ]; +const defaultCustomidents = + "Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ"; + +function defaultIndependentDecoratorSettings(): IndependentDecoratorSettings { + return { + styleType: "decimal", + delimiter: ".", + trailingDelimiter: false, + customTrailingDelimiter: "", + leadingDelimiter: false, + customLeadingDelimiter: "", + customIdents: defaultCustomidents, + specifiedString: "#", + }; +} + +/** + * Defaults independent settings + * + * @returns independent settings + */ +export function defaultIndependentSettings(): IndependentSettings { + return { + orderedRecLevel: 6, + h1: defaultIndependentDecoratorSettings(), + h2: defaultIndependentDecoratorSettings(), + h3: defaultIndependentDecoratorSettings(), + h4: defaultIndependentDecoratorSettings(), + h5: defaultIndependentDecoratorSettings(), + h6: defaultIndependentDecoratorSettings(), + }; +} /** * Default settings for heading decorator. @@ -155,20 +204,21 @@ export function defaultHeadingDecoratorSettings(): HeadingDecoratorSettings { opacity: 20, position: "before", maxRecLevel: 6, - ordered: true, + decoratorMode: "orderd", orderedDelimiter: ".", orderedTrailingDelimiter: false, orderedCustomTrailingDelimiter: "", orderedLeadingDelimiter: false, orderedCustomLeadingDelimiter: "", orderedStyleType: "decimal", - orderedCustomIdents: "Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ", + orderedCustomIdents: defaultCustomidents, orderedSpecifiedString: "#", orderedAllowZeroLevel: false, orderedBasedOnExisting: false, orderedAlwaysIgnore: false, orderedIgnoreSingle: false, orderedIgnoreMaximum: 6, + independentSettings: defaultIndependentSettings(), unorderedLevelHeadings: defaultHeadingTuple.join(" "), }; } diff --git a/components/editor.ts b/components/editor.ts index f75384b..2f35035 100644 --- a/components/editor.ts +++ b/components/editor.ts @@ -15,7 +15,12 @@ import { getOrderedCustomIdents, findFirstCharacterIndex, } from "../common/data"; -import { Counter, Querier } from "../common/counter"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../common/counter"; import { Heading } from "../common/heading"; /** A StateEffect for updating decorations */ @@ -98,7 +103,7 @@ export class HeadingEditorViewPlugin implements PluginValue { const doc = view.state.doc; const { - ordered, + decoratorMode = "orderd", position, opacity, maxRecLevel, @@ -116,12 +121,19 @@ export class HeadingEditorViewPlugin implements PluginValue { orderedBasedOnExisting, orderedAllowZeroLevel, unorderedLevelHeadings, + independentSettings, } = isLivePreviwMode ? pluginData.previewSettings : pluginData.sourceSettings; - let ignoreTopLevel = 0; - if (ordered) { + let counter: Counter; + if (decoratorMode === "unordered") { + counter = new UnorderedCounter( + getUnorderedLevelHeadings(unorderedLevelHeadings), + maxRecLevel + ); + } else { + let ignoreTopLevel = 0; const ignoreSingle = !orderedAlwaysIgnore && orderedIgnoreSingle; const ignoreLimit = orderedAlwaysIgnore ? orderedIgnoreMaximum : 0; if (ignoreSingle || orderedBasedOnExisting) { @@ -149,23 +161,36 @@ export class HeadingEditorViewPlugin implements PluginValue { if (ignoreTopLevel < ignoreLimit) { ignoreTopLevel = ignoreLimit; } - } - const counter = new Counter({ - ordered, - maxRecLevel, - styleType: orderedStyleType, - delimiter: orderedDelimiter, - trailingDelimiter: orderedTrailingDelimiter, - customTrailingDelimiter: orderedCustomTrailingDelimiter, - leadingDelimiter: orderedLeadingDelimiter, - customLeadingDelimiter: orderedCustomLeadingDelimiter, - customIdents: getOrderedCustomIdents(orderedCustomIdents), - specifiedString: orderedSpecifiedString, - ignoreTopLevel, - allowZeroLevel: orderedAllowZeroLevel, - levelHeadings: getUnorderedLevelHeadings(unorderedLevelHeadings), - }); + if (decoratorMode === "independent") { + counter = new IndependentCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + orderedRecLevel: independentSettings?.orderedRecLevel, + h1: independentSettings?.h1, + h2: independentSettings?.h2, + h3: independentSettings?.h3, + h4: independentSettings?.h4, + h5: independentSettings?.h5, + h6: independentSettings?.h6, + }); + } else { + counter = new OrderedCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + styleType: orderedStyleType, + delimiter: orderedDelimiter, + trailingDelimiter: orderedTrailingDelimiter, + customTrailingDelimiter: orderedCustomTrailingDelimiter, + leadingDelimiter: orderedLeadingDelimiter, + customLeadingDelimiter: orderedCustomLeadingDelimiter, + customIdents: getOrderedCustomIdents(orderedCustomIdents), + specifiedString: orderedSpecifiedString, + }); + } + } const heading = new Heading(); for (let lineIndex = 1; lineIndex <= doc.lines; lineIndex++) { diff --git a/components/file-explorer.ts b/components/file-explorer.ts index 072f4d2..50c26fe 100644 --- a/components/file-explorer.ts +++ b/components/file-explorer.ts @@ -5,7 +5,12 @@ import { getOrderedCustomIdents, getUnorderedLevelHeadings, } from "../common/data"; -import { Querier, Counter } from "../common/counter"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../common/counter"; /** * File Explorer Heading Decorator. @@ -22,9 +27,9 @@ export function fileExplorerHandler( cacheHeadings: HeadingCache[] ): void { const { + decoratorMode = "orderd", opacity, position, - ordered, maxRecLevel, orderedDelimiter, orderedTrailingDelimiter, @@ -40,12 +45,19 @@ export function fileExplorerHandler( orderedBasedOnExisting, orderedAllowZeroLevel, unorderedLevelHeadings, + independentSettings, } = settings; container.classList.add(className.fileExplorerContainer); - let ignoreTopLevel = 0; - if (ordered) { + let counter: Counter; + if (decoratorMode === "unordered") { + counter = new UnorderedCounter( + getUnorderedLevelHeadings(unorderedLevelHeadings), + maxRecLevel + ); + } else { + let ignoreTopLevel = 0; const ignoreSingle = !orderedAlwaysIgnore && orderedIgnoreSingle; const ignoreLimit = orderedAlwaysIgnore ? orderedIgnoreMaximum : 0; if (ignoreSingle || orderedBasedOnExisting) { @@ -61,23 +73,36 @@ export function fileExplorerHandler( if (ignoreTopLevel < ignoreLimit) { ignoreTopLevel = ignoreLimit; } - } - const counter = new Counter({ - ordered, - maxRecLevel, - delimiter: orderedDelimiter, - trailingDelimiter: orderedTrailingDelimiter, - customTrailingDelimiter: orderedCustomTrailingDelimiter, - leadingDelimiter: orderedLeadingDelimiter, - customLeadingDelimiter: orderedCustomLeadingDelimiter, - styleType: orderedStyleType, - customIdents: getOrderedCustomIdents(orderedCustomIdents), - specifiedString: orderedSpecifiedString, - ignoreTopLevel, - allowZeroLevel: orderedAllowZeroLevel, - levelHeadings: getUnorderedLevelHeadings(unorderedLevelHeadings), - }); + if (decoratorMode === "independent") { + counter = new IndependentCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + orderedRecLevel: independentSettings?.orderedRecLevel, + h1: independentSettings?.h1, + h2: independentSettings?.h2, + h3: independentSettings?.h3, + h4: independentSettings?.h4, + h5: independentSettings?.h5, + h6: independentSettings?.h6, + }); + } else { + counter = new OrderedCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + delimiter: orderedDelimiter, + trailingDelimiter: orderedTrailingDelimiter, + customTrailingDelimiter: orderedCustomTrailingDelimiter, + leadingDelimiter: orderedLeadingDelimiter, + customLeadingDelimiter: orderedCustomLeadingDelimiter, + styleType: orderedStyleType, + customIdents: getOrderedCustomIdents(orderedCustomIdents), + specifiedString: orderedSpecifiedString, + }); + } + } const marginMultiplier = parseInt( diff --git a/components/outline.ts b/components/outline.ts index 7207b8a..20d2c83 100644 --- a/components/outline.ts +++ b/components/outline.ts @@ -7,7 +7,12 @@ import { diffLevel, compareMarkdownText, } from "../common/data"; -import { Querier, Counter } from "../common/counter"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../common/counter"; /** * Handle the outline rendering based on the given settings and heading elements. @@ -24,9 +29,9 @@ export function outlineHandler( cacheHeadings: HeadingCache[] ): void { const { + decoratorMode = "orderd", opacity, position, - ordered, maxRecLevel, orderedDelimiter, orderedTrailingDelimiter, @@ -42,12 +47,19 @@ export function outlineHandler( orderedBasedOnExisting, orderedAllowZeroLevel, unorderedLevelHeadings, + independentSettings, } = settings; container.classList.add(className.outlineContainer); - let ignoreTopLevel = 0; - if (ordered) { + let counter: Counter; + if (decoratorMode === "unordered") { + counter = new UnorderedCounter( + getUnorderedLevelHeadings(unorderedLevelHeadings), + maxRecLevel + ); + } else { + let ignoreTopLevel = 0; const ignoreSingle = !orderedAlwaysIgnore && orderedIgnoreSingle; const ignoreLimit = orderedAlwaysIgnore ? orderedIgnoreMaximum : 0; if (ignoreSingle || orderedBasedOnExisting) { @@ -63,23 +75,36 @@ export function outlineHandler( if (ignoreTopLevel < ignoreLimit) { ignoreTopLevel = ignoreLimit; } - } - const counter = new Counter({ - ordered, - maxRecLevel, - delimiter: orderedDelimiter, - trailingDelimiter: orderedTrailingDelimiter, - customTrailingDelimiter: orderedCustomTrailingDelimiter, - leadingDelimiter: orderedLeadingDelimiter, - customLeadingDelimiter: orderedCustomLeadingDelimiter, - styleType: orderedStyleType, - customIdents: getOrderedCustomIdents(orderedCustomIdents), - specifiedString: orderedSpecifiedString, - ignoreTopLevel, - allowZeroLevel: orderedAllowZeroLevel, - levelHeadings: getUnorderedLevelHeadings(unorderedLevelHeadings), - }); + if (decoratorMode === "independent") { + counter = new IndependentCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + orderedRecLevel: independentSettings?.orderedRecLevel, + h1: independentSettings?.h1, + h2: independentSettings?.h2, + h3: independentSettings?.h3, + h4: independentSettings?.h4, + h5: independentSettings?.h5, + h6: independentSettings?.h6, + }); + } else { + counter = new OrderedCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + delimiter: orderedDelimiter, + trailingDelimiter: orderedTrailingDelimiter, + customTrailingDelimiter: orderedCustomTrailingDelimiter, + leadingDelimiter: orderedLeadingDelimiter, + customLeadingDelimiter: orderedCustomLeadingDelimiter, + styleType: orderedStyleType, + customIdents: getOrderedCustomIdents(orderedCustomIdents), + specifiedString: orderedSpecifiedString, + }); + } + } let lastCacheLevel = 0; let lastReadLevel = 0; diff --git a/components/plugin.ts b/components/plugin.ts index 0613ad4..85d1233 100644 --- a/components/plugin.ts +++ b/components/plugin.ts @@ -214,8 +214,10 @@ export class HeadingPlugin extends Plugin { return; } - const { ordered } = readingSettings; - if (ordered) { + const { decoratorMode = "orderd" } = readingSettings; + if (decoratorMode === "unordered") { + readingUnorderedHandler(readingSettings, headingElements); + } else { let sourceContent = fileData; if (!sourceContent) { const file = this.getActiveFile(cxt.sourcePath); @@ -238,8 +240,6 @@ export class HeadingPlugin extends Plugin { headingElements, sourceArr ); - } else { - readingUnorderedHandler(readingSettings, headingElements); } } else { cancelHTMLDecorator(container); diff --git a/components/quiet-outline.ts b/components/quiet-outline.ts index 092b85b..2599779 100644 --- a/components/quiet-outline.ts +++ b/components/quiet-outline.ts @@ -4,7 +4,12 @@ import { getOrderedCustomIdents, getUnorderedLevelHeadings, } from "../common/data"; -import { Querier, Counter } from "../common/counter"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../common/counter"; /** * Handles the quiet outline for a given set of heading elements. @@ -19,9 +24,9 @@ export function quietOutlineHandler( headingElements: NodeListOf ): void { const { + decoratorMode = "orderd", opacity, position, - ordered, maxRecLevel, orderedDelimiter, orderedTrailingDelimiter, @@ -37,12 +42,19 @@ export function quietOutlineHandler( orderedBasedOnExisting, orderedAllowZeroLevel, unorderedLevelHeadings, + independentSettings, } = settings; container.classList.add(className.quietOutlineContainer); - let ignoreTopLevel = 0; - if (ordered) { + let counter: Counter; + if (decoratorMode === "unordered") { + counter = new UnorderedCounter( + getUnorderedLevelHeadings(unorderedLevelHeadings), + maxRecLevel + ); + } else { + let ignoreTopLevel = 0; const ignoreSingle = !orderedAlwaysIgnore && orderedIgnoreSingle; const ignoreLimit = orderedAlwaysIgnore ? orderedIgnoreMaximum : 0; if (ignoreSingle || orderedBasedOnExisting) { @@ -61,23 +73,36 @@ export function quietOutlineHandler( if (ignoreTopLevel < ignoreLimit) { ignoreTopLevel = ignoreLimit; } - } - const counter = new Counter({ - ordered, - maxRecLevel, - delimiter: orderedDelimiter, - trailingDelimiter: orderedTrailingDelimiter, - customTrailingDelimiter: orderedCustomTrailingDelimiter, - leadingDelimiter: orderedLeadingDelimiter, - customLeadingDelimiter: orderedCustomLeadingDelimiter, - styleType: orderedStyleType, - customIdents: getOrderedCustomIdents(orderedCustomIdents), - specifiedString: orderedSpecifiedString, - ignoreTopLevel, - allowZeroLevel: orderedAllowZeroLevel, - levelHeadings: getUnorderedLevelHeadings(unorderedLevelHeadings), - }); + if (decoratorMode === "independent") { + counter = new IndependentCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + orderedRecLevel: independentSettings?.orderedRecLevel, + h1: independentSettings?.h1, + h2: independentSettings?.h2, + h3: independentSettings?.h3, + h4: independentSettings?.h4, + h5: independentSettings?.h5, + h6: independentSettings?.h6, + }); + } else { + counter = new OrderedCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + delimiter: orderedDelimiter, + trailingDelimiter: orderedTrailingDelimiter, + customTrailingDelimiter: orderedCustomTrailingDelimiter, + leadingDelimiter: orderedLeadingDelimiter, + customLeadingDelimiter: orderedCustomLeadingDelimiter, + styleType: orderedStyleType, + customIdents: getOrderedCustomIdents(orderedCustomIdents), + specifiedString: orderedSpecifiedString, + }); + } + } headingElements.forEach((headingEle) => { const level = queryHeadingLevelByQuietOutlineElement(headingEle); diff --git a/components/reading.ts b/components/reading.ts index 9ea570a..ff481c3 100644 --- a/components/reading.ts +++ b/components/reading.ts @@ -7,7 +7,12 @@ import { getUnorderedLevelHeadings, } from "../common/data"; import { Heading } from "../common/heading"; -import { Querier, Counter } from "../common/counter"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../common/counter"; /** * Handles ordered headings of reading view. @@ -24,6 +29,7 @@ export function readingOrderedHandler( sourceArr: string[] ): void { const { + decoratorMode = "orderd", opacity, position, maxRecLevel, @@ -40,6 +46,7 @@ export function readingOrderedHandler( orderedAlwaysIgnore, orderedBasedOnExisting, orderedAllowZeroLevel, + independentSettings, } = settings; let ignoreTopLevel = 0; @@ -70,20 +77,36 @@ export function readingOrderedHandler( ignoreTopLevel = ignoreLimit; } - const counter = new Counter({ - ordered: true, - maxRecLevel, - delimiter: orderedDelimiter, - trailingDelimiter: orderedTrailingDelimiter, - customTrailingDelimiter: orderedCustomTrailingDelimiter, - leadingDelimiter: orderedLeadingDelimiter, - customLeadingDelimiter: orderedCustomLeadingDelimiter, - styleType: orderedStyleType, - customIdents: getOrderedCustomIdents(orderedCustomIdents), - specifiedString: orderedSpecifiedString, - ignoreTopLevel, - allowZeroLevel: orderedAllowZeroLevel, - }); + let counter: Counter; + if (decoratorMode === "independent") { + counter = new IndependentCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + orderedRecLevel: independentSettings?.orderedRecLevel, + h1: independentSettings?.h1, + h2: independentSettings?.h2, + h3: independentSettings?.h3, + h4: independentSettings?.h4, + h5: independentSettings?.h5, + h6: independentSettings?.h6, + }); + } else { + counter = new OrderedCounter({ + maxRecLevel, + ignoreTopLevel, + allowZeroLevel: orderedAllowZeroLevel, + delimiter: orderedDelimiter, + trailingDelimiter: orderedTrailingDelimiter, + customTrailingDelimiter: orderedCustomTrailingDelimiter, + leadingDelimiter: orderedLeadingDelimiter, + customLeadingDelimiter: orderedCustomLeadingDelimiter, + styleType: orderedStyleType, + customIdents: getOrderedCustomIdents(orderedCustomIdents), + specifiedString: orderedSpecifiedString, + }); + } + const heading = new Heading(); let headingIndex = 1; @@ -141,11 +164,10 @@ export function readingUnorderedHandler( ): void { const { opacity, position, maxRecLevel, unorderedLevelHeadings } = settings; - const counter = new Counter({ - ordered: false, - maxRecLevel, - levelHeadings: getUnorderedLevelHeadings(unorderedLevelHeadings), - }); + const counter = new UnorderedCounter( + getUnorderedLevelHeadings(unorderedLevelHeadings), + maxRecLevel + ); headingElements.forEach((headingElement) => { const level = queryHeadingLevelByElement(headingElement); diff --git a/components/setting-tab.ts b/components/setting-tab.ts index 836d010..77ed441 100644 --- a/components/setting-tab.ts +++ b/components/setting-tab.ts @@ -1,6 +1,11 @@ import { App, ButtonComponent, PluginSettingTab, Setting } from "obsidian"; import type { HeadingPlugin } from "./plugin"; -import type { OrderedCounterStyleType } from "../common/data"; +import type { + OrderedCounterStyleType, + HeadingDecoratorSettings, + IndependentDecoratorSettings, +} from "../common/data"; +import { className, defaultIndependentSettings } from "../common/data"; import { orderedStyleTypeOptions } from "../common/options"; import { FolderSuggest } from "./suggest"; @@ -70,12 +75,19 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInReading).onChange((value) => { settings.enabledInReading = value; + value + ? readingConfigContainerEl.show() + : readingConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); + const readingConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let readingConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(readingConfigContainerEl) .setName(i18n.t("setting.enabledInReadingConfig")) .setDesc(i18n.t("setting.enabledInReadingConfigDesc")) .addToggle((toggle) => { @@ -96,7 +108,7 @@ export class HeadingSettingTab extends PluginSettingTab { }); //* readingRenderPolicy - new Setting(containerEl) + new Setting(readingConfigContainerEl) .setName(i18n.t("setting.renderPolicy")) .setDesc(i18n.t("setting.renderPolicyDesc")) .addDropdown((dropdown) => { @@ -114,6 +126,10 @@ export class HeadingSettingTab extends PluginSettingTab { }); }); + if (!settings.enabledInReading) { + readingConfigContainerEl.hide(); + } + new Setting(containerEl) .setName(i18n.t("setting.livePreview")) .setHeading(); @@ -125,12 +141,19 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInPreview).onChange((value) => { settings.enabledInPreview = value; + value + ? previewConfigContainerEl.show() + : previewConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); + const previewConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let previewConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(previewConfigContainerEl) .setName(i18n.t("setting.enabledInPreviewConfig")) .setDesc(i18n.t("setting.enabledInPreviewConfigDesc")) .addToggle((toggle) => { @@ -150,6 +173,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setDisabled(!settings.enabledPreviewSettings); }); + if (!settings.enabledInPreview) { + previewConfigContainerEl.hide(); + } + new Setting(containerEl).setName(i18n.t("setting.sourceMode")).setHeading(); //* enabledInSource @@ -159,12 +186,19 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInSource).onChange((value) => { settings.enabledInSource = value; + value + ? sourceConfigContainerEl.show() + : sourceConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); + const sourceConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let sourceConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(sourceConfigContainerEl) .setName(i18n.t("setting.enabledInSourceConfig")) .setDesc(i18n.t("setting.enabledInSourceConfigDesc")) .addToggle((toggle) => { @@ -185,7 +219,7 @@ export class HeadingSettingTab extends PluginSettingTab { }); //* sourceHideNumberSigns - new Setting(containerEl) + new Setting(sourceConfigContainerEl) .setName(i18n.t("setting.hideNumberSigns")) .setDesc(i18n.t("setting.hideNumberSignsDesc")) .addToggle((toggle) => { @@ -197,6 +231,10 @@ export class HeadingSettingTab extends PluginSettingTab { }); }); + if (!settings.enabledInSource) { + sourceConfigContainerEl.hide(); + } + new Setting(containerEl).setName(i18n.t("setting.outline")).setHeading(); //* enabledInOutline @@ -206,12 +244,19 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInOutline).onChange((value) => { settings.enabledInOutline = value; + value + ? outlineConfigContainerEl.show() + : outlineConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); + const outlineConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let outlineConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(outlineConfigContainerEl) .setName(i18n.t("setting.enabledInOutlineConfig")) .setDesc(i18n.t("setting.enabledInOutlineConfigDesc")) .addToggle((toggle) => { @@ -231,6 +276,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setDisabled(!settings.enabledOutlineSettings); }); + if (!settings.enabledInOutline) { + outlineConfigContainerEl.hide(); + } + new Setting(containerEl) .setName(i18n.t("setting.quietOutline")) .setHeading(); @@ -241,6 +290,9 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInQuietOutline).onChange((value) => { settings.enabledInQuietOutline = value; + value + ? quietOutlineConfigContainerEl.show() + : quietOutlineConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); @@ -259,8 +311,12 @@ export class HeadingSettingTab extends PluginSettingTab { ); enabledInQuietOutlineSetting.descEl.appendChild(enabledInQuietOutlineDesc); + const quietOutlineConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let quietOutlineConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(quietOutlineConfigContainerEl) .setName(i18n.t("setting.enabledInQuietOutlineConfig")) .setDesc(i18n.t("setting.enabledInQuietOutlineConfigDesc")) .addToggle((toggle) => { @@ -282,6 +338,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setDisabled(!settings.enabledQuietOutlineSettings); }); + if (!settings.enabledInQuietOutline) { + quietOutlineConfigContainerEl.hide(); + } + new Setting(containerEl) .setName(i18n.t("setting.fileExplorer")) .setHeading(); @@ -292,6 +352,9 @@ export class HeadingSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(settings.enabledInFileExplorer).onChange((value) => { settings.enabledInFileExplorer = value; + value + ? fileExplorerConfigContainerEl.show() + : fileExplorerConfigContainerEl.hide(); this.plugin.saveSettings(); }) ); @@ -310,8 +373,12 @@ export class HeadingSettingTab extends PluginSettingTab { ); enabledInFileExplorerSetting.descEl.appendChild(enabledInFileExplorerDesc); + const fileExplorerConfigContainerEl = containerEl.createDiv( + className.settingItem + ); + let fileExplorerConfigBtn: ButtonOrUndefined; - new Setting(containerEl) + new Setting(fileExplorerConfigContainerEl) .setName(i18n.t("setting.enabledInFileExplorerConfig")) .setDesc(i18n.t("setting.enabledInFileExplorerConfigDesc")) .addToggle((toggle) => { @@ -333,6 +400,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setDisabled(!settings.enabledFileExplorerSettings); }); + if (!settings.enabledInFileExplorer) { + fileExplorerConfigContainerEl.hide(); + } + new Setting(containerEl).setName(i18n.t("setting.blocklist")).setHeading(); //* folderBlacklist @@ -361,6 +432,10 @@ export class HeadingSettingTab extends PluginSettingTab { return false; } + private isDecoratorModeValue(value: string): value is DecoratorMode { + return ["orderd", "independent", "unordered"].includes(value); + } + private isPositionValue(value: string): value is PostionOptions { return ["before", "after", "before-inside", "after-inside"].includes(value); } @@ -428,16 +503,50 @@ export class HeadingSettingTab extends PluginSettingTab { new Setting(containerEl).setName(i18n.t("setting.effect")).setHeading(); - //* ordered + //* decoratorMode new Setting(containerEl) - .setName(i18n.t("setting.ordered")) - .setDesc(i18n.t("setting.orderedDesc")) - .addToggle((toggle) => - toggle.setValue(settings[settingsType].ordered).onChange((value) => { - settings[settingsType].ordered = value; - this.plugin.saveSettings(); - }) - ); + .setName(i18n.t("setting.decoratorMode")) + .setDesc(i18n.t("setting.decoratorModeDesc")) + .addDropdown((dropdown) => { + const options: Record = { + orderd: i18n.t("setting.ordered"), + independent: i18n.t("setting.independent"), + unordered: i18n.t("setting.unordered"), + }; + dropdown + .addOptions(options) + .setValue(settings[settingsType].decoratorMode || "orderd") + .onChange((value) => { + settings[settingsType].decoratorMode = this.isDecoratorModeValue( + value + ) + ? value + : "orderd"; + + switch (settings[settingsType].decoratorMode) { + case "orderd": + orderedContainerEl.show(); + logicContainerEl.show(); + independentContainerEl.hide(); + unorderedContainerEl.hide(); + break; + case "independent": + independentContainerEl.show(); + logicContainerEl.show(); + orderedContainerEl.hide(); + unorderedContainerEl.hide(); + break; + case "unordered": + unorderedContainerEl.show(); + orderedContainerEl.hide(); + independentContainerEl.hide(); + logicContainerEl.hide(); + break; + } + + this.plugin.saveSettings(); + }); + }); //* opacity new Setting(containerEl) @@ -502,6 +611,51 @@ export class HeadingSettingTab extends PluginSettingTab { .setDynamicTooltip(); }); + const orderedContainerEl = containerEl.createDiv( + className.settingContainer + ); + this.orderedSettings(orderedContainerEl, settings[settingsType]); + if ( + settings[settingsType].decoratorMode && + settings[settingsType].decoratorMode !== "orderd" + ) { + orderedContainerEl.hide(); + } + + const independentContainerEl = containerEl.createDiv( + className.settingContainer + ); + this.independentSettings(independentContainerEl, settings[settingsType]); + if (settings[settingsType].decoratorMode !== "independent") { + independentContainerEl.hide(); + } + + const unorderedContainerEl = containerEl.createDiv( + className.settingContainer + ); + this.unorderedSettings(unorderedContainerEl, settings[settingsType]); + if (settings[settingsType].decoratorMode !== "unordered") { + unorderedContainerEl.hide(); + } + + const logicContainerEl = containerEl.createDiv(className.settingContainer); + this.logicSettings(logicContainerEl, settings[settingsType]); + if (settings[settingsType].decoratorMode === "unordered") { + logicContainerEl.hide(); + } + + //* Scroll back to the top + containerEl.scrollTo({ top: 0, behavior: "smooth" }); + } + + private orderedSettings( + containerEl: HTMLElement, + settings: HeadingDecoratorSettings + ) { + const { + plugin: { i18n }, + } = this; + new Setting(containerEl).setName(i18n.t("setting.ordered")).setHeading(); //* orderedStyleType @@ -511,10 +665,23 @@ export class HeadingSettingTab extends PluginSettingTab { .addDropdown((dropdown) => dropdown .addOptions(orderedStyleTypeOptions) - .setValue(settings[settingsType].orderedStyleType) - .onChange((value) => { - settings[settingsType].orderedStyleType = - value as OrderedCounterStyleType; + .setValue(settings.orderedStyleType) + .onChange((value: OrderedCounterStyleType) => { + settings.orderedStyleType = value; + switch (value) { + case "customIdent": + orderedCustomIdentsContainerEl.show(); + orderedSpecifiedStringContainerEl.hide(); + break; + case "string": + orderedSpecifiedStringContainerEl.show(); + orderedCustomIdentsContainerEl.hide(); + break; + default: + orderedCustomIdentsContainerEl.hide(); + orderedSpecifiedStringContainerEl.hide(); + break; + } this.plugin.saveSettings(); }) ); @@ -524,12 +691,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setName(i18n.t("setting.orderedDelimiter")) .setDesc(i18n.t("setting.orderedDelimiterDesc")) .addText((text) => - text - .setValue(settings[settingsType].orderedDelimiter) - .onChange((value) => { - settings[settingsType].orderedDelimiter = value; - this.plugin.saveSettings(); - }) + text.setValue(settings.orderedDelimiter).onChange((value) => { + settings.orderedDelimiter = value; + this.plugin.saveSettings(); + }) ); //* orderedTrailingDelimiter @@ -537,78 +702,217 @@ export class HeadingSettingTab extends PluginSettingTab { .setName(i18n.t("setting.orderedTrailingDelimiter")) .setDesc(i18n.t("setting.orderedTrailingDelimiterDesc")) .addToggle((toggle) => - toggle - .setValue(settings[settingsType].orderedTrailingDelimiter) - .onChange((value) => { - settings[settingsType].orderedTrailingDelimiter = value; - this.plugin.saveSettings(); - }) + toggle.setValue(settings.orderedTrailingDelimiter).onChange((value) => { + settings.orderedTrailingDelimiter = value; + value + ? orderedCustomTrailingDelimiterContainerEl.show() + : orderedCustomTrailingDelimiterContainerEl.hide(); + this.plugin.saveSettings(); + }) ); + const orderedCustomTrailingDelimiterContainerEl = containerEl.createDiv( + className.settingItem + ); + //* orderedCustomTrailingDelimiter - new Setting(containerEl) + new Setting(orderedCustomTrailingDelimiterContainerEl) .setName(i18n.t("setting.orderedCustomTrailingDelimiter")) .setDesc(i18n.t("setting.orderedCustomTrailingDelimiterDesc")) .addText((text) => { text - .setValue(settings[settingsType].orderedCustomTrailingDelimiter || "") + .setValue(settings.orderedCustomTrailingDelimiter || "") .onChange((value) => { - settings[settingsType].orderedCustomTrailingDelimiter = value; + settings.orderedCustomTrailingDelimiter = value; this.plugin.saveSettings(); }); }); + if (!settings.orderedTrailingDelimiter) { + orderedCustomTrailingDelimiterContainerEl.hide(); + } + //* orderedLeadingDelimiter new Setting(containerEl) .setName(i18n.t("setting.orderedLeadingDelimiter")) .setDesc(i18n.t("setting.orderedLeadingDelimiterDesc")) .addToggle((toggle) => toggle - .setValue(settings[settingsType].orderedLeadingDelimiter || false) + .setValue(settings.orderedLeadingDelimiter || false) .onChange((value) => { - settings[settingsType].orderedLeadingDelimiter = value; + settings.orderedLeadingDelimiter = value; + value + ? orderedCustomLeadingDelimiterContainerEl.show() + : orderedCustomLeadingDelimiterContainerEl.hide(); this.plugin.saveSettings(); }) ); + const orderedCustomLeadingDelimiterContainerEl = containerEl.createDiv( + className.settingItem + ); + //* orderedCustomLeadingDelimiter - new Setting(containerEl) + new Setting(orderedCustomLeadingDelimiterContainerEl) .setName(i18n.t("setting.orderedCustomLeadingDelimiter")) .setDesc(i18n.t("setting.orderedCustomLeadingDelimiterDesc")) .addText((text) => { text - .setValue(settings[settingsType].orderedCustomLeadingDelimiter || "") + .setValue(settings.orderedCustomLeadingDelimiter || "") .onChange((value) => { - settings[settingsType].orderedCustomLeadingDelimiter = value; + settings.orderedCustomLeadingDelimiter = value; this.plugin.saveSettings(); }); }); + if (!settings.orderedLeadingDelimiter) { + orderedCustomLeadingDelimiterContainerEl.hide(); + } + + const orderedCustomIdentsContainerEl = containerEl.createDiv( + className.settingItem + ); + //* orderedCustomIdents - new Setting(containerEl) + new Setting(orderedCustomIdentsContainerEl) .setName(i18n.t("setting.orderedCustomIdents")) .setDesc(i18n.t("setting.orderedCustomIdentsDesc")) .addText((text) => - text - .setValue(settings[settingsType].orderedCustomIdents) - .onChange((value) => { - settings[settingsType].orderedCustomIdents = value; - this.plugin.saveSettings(); - }) + text.setValue(settings.orderedCustomIdents).onChange((value) => { + settings.orderedCustomIdents = value; + this.plugin.saveSettings(); + }) ); + if (settings.orderedStyleType !== "customIdent") { + orderedCustomIdentsContainerEl.hide(); + } + + const orderedSpecifiedStringContainerEl = containerEl.createDiv( + className.settingItem + ); + //* orderedSpecifiedString - new Setting(containerEl) + new Setting(orderedSpecifiedStringContainerEl) .setName(i18n.t("setting.orderedSpecifiedString")) .setDesc(i18n.t("setting.orderedSpecifiedStringDesc")) .addText((text) => - text - .setValue(settings[settingsType].orderedSpecifiedString) + text.setValue(settings.orderedSpecifiedString).onChange((value) => { + settings.orderedSpecifiedString = value; + this.plugin.saveSettings(); + }) + ); + + if (settings.orderedStyleType !== "string") { + orderedSpecifiedStringContainerEl.hide(); + } + } + + private independentSettings( + containerEl: HTMLElement, + settings: HeadingDecoratorSettings + ) { + const { + plugin: { i18n }, + } = this; + + if (!settings.independentSettings) { + settings.independentSettings = defaultIndependentSettings(); + } + + new Setting(containerEl) + .setName(i18n.t("setting.independent")) + .setHeading(); + + //* orderedRecLevel + new Setting(containerEl) + .setName(i18n.t("setting.orderedRecLevel")) + .setDesc(i18n.t("setting.orderedRecLevelDesc")) + .addSlider((slider) => { + slider + .setLimits(2, 6, 1) + .setValue(settings.independentSettings!.orderedRecLevel) .onChange((value) => { - settings[settingsType].orderedSpecifiedString = value; + settings.independentSettings!.orderedRecLevel = value; this.plugin.saveSettings(); }) + .setDynamicTooltip(); + }); + + //* h1 + new Setting(containerEl).setName(i18n.t("setting.h1")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h1 + ); + + //* h2 + new Setting(containerEl).setName(i18n.t("setting.h2")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h2 + ); + + //* h3 + new Setting(containerEl).setName(i18n.t("setting.h3")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h3 + ); + + //* h4 + new Setting(containerEl).setName(i18n.t("setting.h4")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h4 + ); + + //* h5 + new Setting(containerEl).setName(i18n.t("setting.h5")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h5 + ); + + //* h6 + new Setting(containerEl).setName(i18n.t("setting.h6")).setHeading(); + this.independentDecoratorSettings( + containerEl, + settings.independentSettings!.h6 + ); + } + + private unorderedSettings( + containerEl: HTMLElement, + settings: HeadingDecoratorSettings + ) { + const { + plugin: { i18n }, + } = this; + + new Setting(containerEl).setName(i18n.t("setting.unordered")).setHeading(); + + //* unorderedLevelHeadings + new Setting(containerEl) + .setName(i18n.t("setting.unorderedLevelHeadings")) + .setDesc(i18n.t("setting.unorderedLevelHeadingsDesc")) + .addText((text) => + text.setValue(settings.unorderedLevelHeadings).onChange((value) => { + settings.unorderedLevelHeadings = value; + this.plugin.saveSettings(); + }) ); + } + + private logicSettings( + containerEl: HTMLElement, + settings: HeadingDecoratorSettings + ) { + const { + plugin: { i18n }, + } = this; + + new Setting(containerEl).setName(i18n.t("setting.logic")).setHeading(); //* orderedAllowZeroLevel new Setting(containerEl) @@ -616,9 +920,9 @@ export class HeadingSettingTab extends PluginSettingTab { .setDesc(i18n.t("setting.orderedAllowZeroLevelDesc")) .addToggle((toggle) => toggle - .setValue(settings[settingsType].orderedAllowZeroLevel ?? false) + .setValue(settings.orderedAllowZeroLevel ?? false) .onChange((value) => { - settings[settingsType].orderedAllowZeroLevel = value; + settings.orderedAllowZeroLevel = value; this.plugin.saveSettings(); }) ); @@ -629,9 +933,9 @@ export class HeadingSettingTab extends PluginSettingTab { .setDesc(i18n.t("setting.orderedBasedOnExistingDesc")) .addToggle((toggle) => toggle - .setValue(settings[settingsType].orderedBasedOnExisting ?? false) + .setValue(settings.orderedBasedOnExisting ?? false) .onChange((value) => { - settings[settingsType].orderedBasedOnExisting = value; + settings.orderedBasedOnExisting = value; this.plugin.saveSettings(); }) ); @@ -642,9 +946,9 @@ export class HeadingSettingTab extends PluginSettingTab { .setDesc(i18n.t("setting.orderedAlwaysIgnoreDesc")) .addToggle((toggle) => toggle - .setValue(settings[settingsType].orderedAlwaysIgnore ?? false) + .setValue(settings.orderedAlwaysIgnore ?? false) .onChange((value) => { - settings[settingsType].orderedAlwaysIgnore = value; + settings.orderedAlwaysIgnore = value; this.plugin.saveSettings(); }) ); @@ -654,12 +958,10 @@ export class HeadingSettingTab extends PluginSettingTab { .setName(i18n.t("setting.orderedIgnoreSingle")) .setDesc(i18n.t("setting.orderedIgnoreSingleDesc")) .addToggle((toggle) => - toggle - .setValue(settings[settingsType].orderedIgnoreSingle) - .onChange((value) => { - settings[settingsType].orderedIgnoreSingle = value; - this.plugin.saveSettings(); - }) + toggle.setValue(settings.orderedIgnoreSingle).onChange((value) => { + settings.orderedIgnoreSingle = value; + this.plugin.saveSettings(); + }) ); //* orderedIgnoreMaximum @@ -669,31 +971,13 @@ export class HeadingSettingTab extends PluginSettingTab { .addSlider((slider) => slider .setLimits(1, 6, 1) - .setValue(settings[settingsType].orderedIgnoreMaximum ?? 6) + .setValue(settings.orderedIgnoreMaximum ?? 6) .onChange((value) => { - settings[settingsType].orderedIgnoreMaximum = value; + settings.orderedIgnoreMaximum = value; this.plugin.saveSettings(); }) .setDynamicTooltip() ); - - new Setting(containerEl).setName(i18n.t("setting.unordered")).setHeading(); - - //* unorderedLevelHeadings - new Setting(containerEl) - .setName(i18n.t("setting.unorderedLevelHeadings")) - .setDesc(i18n.t("setting.unorderedLevelHeadingsDesc")) - .addText((text) => - text - .setValue(settings[settingsType].unorderedLevelHeadings) - .onChange((value) => { - settings[settingsType].unorderedLevelHeadings = value; - this.plugin.saveSettings(); - }) - ); - - //* Scroll back to the top - containerEl.scrollTo({ top: 0, behavior: "smooth" }); } private manageFolderBlacklist(scrollToTop = false) { @@ -826,4 +1110,162 @@ export class HeadingSettingTab extends PluginSettingTab { containerEl.scrollTo({ top: 0, behavior: "smooth" }); } } + + private independentDecoratorSettings( + containerEl: HTMLElement, + settings: IndependentDecoratorSettings + ) { + const { + plugin: { i18n }, + } = this; + + //* styleType + new Setting(containerEl) + .setName(i18n.t("setting.orderedStyleType")) + .setDesc(i18n.t("setting.orderedStyleTypeDesc")) + .addDropdown((dropdown) => + dropdown + .addOptions(orderedStyleTypeOptions) + .setValue(settings.styleType) + .onChange((value: OrderedCounterStyleType) => { + settings.styleType = value; + switch (value) { + case "customIdent": + customIdentsContainerEl.show(); + specifiedStringContainerEl.hide(); + break; + case "string": + specifiedStringContainerEl.show(); + customIdentsContainerEl.hide(); + break; + default: + customIdentsContainerEl.hide(); + specifiedStringContainerEl.hide(); + break; + } + this.plugin.saveSettings(); + }) + ); + + //* delimiter + new Setting(containerEl) + .setName(i18n.t("setting.orderedDelimiter")) + .setDesc(i18n.t("setting.orderedDelimiterDesc")) + .addText((text) => + text.setValue(settings.delimiter).onChange((value) => { + settings.delimiter = value; + this.plugin.saveSettings(); + }) + ); + + //* trailingDelimiter + new Setting(containerEl) + .setName(i18n.t("setting.orderedTrailingDelimiter")) + .setDesc(i18n.t("setting.orderedTrailingDelimiterDesc")) + .addToggle((toggle) => + toggle.setValue(settings.trailingDelimiter).onChange((value) => { + settings.trailingDelimiter = value; + value + ? customTrailingDelimiterContainerEl.show() + : customTrailingDelimiterContainerEl.hide(); + this.plugin.saveSettings(); + }) + ); + + const customTrailingDelimiterContainerEl = containerEl.createDiv( + className.settingItem + ); + + //* customTrailingDelimiter + new Setting(customTrailingDelimiterContainerEl) + .setName(i18n.t("setting.orderedCustomTrailingDelimiter")) + .setDesc(i18n.t("setting.orderedCustomTrailingDelimiterDesc")) + .addText((text) => { + text + .setValue(settings.customTrailingDelimiter || "") + .onChange((value) => { + settings.customTrailingDelimiter = value; + this.plugin.saveSettings(); + }); + }); + + if (!settings.trailingDelimiter) { + customTrailingDelimiterContainerEl.hide(); + } + + //* leadingDelimiter + new Setting(containerEl) + .setName(i18n.t("setting.orderedLeadingDelimiter")) + .setDesc(i18n.t("setting.orderedLeadingDelimiterDesc")) + .addToggle((toggle) => + toggle + .setValue(settings.leadingDelimiter || false) + .onChange((value) => { + settings.leadingDelimiter = value; + value + ? customLeadingDelimiterContainerEl.show() + : customLeadingDelimiterContainerEl.hide(); + this.plugin.saveSettings(); + }) + ); + + const customLeadingDelimiterContainerEl = containerEl.createDiv( + className.settingItem + ); + + //* customLeadingDelimiter + new Setting(customLeadingDelimiterContainerEl) + .setName(i18n.t("setting.orderedCustomLeadingDelimiter")) + .setDesc(i18n.t("setting.orderedCustomLeadingDelimiterDesc")) + .addText((text) => { + text + .setValue(settings.customLeadingDelimiter || "") + .onChange((value) => { + settings.customLeadingDelimiter = value; + this.plugin.saveSettings(); + }); + }); + + if (!settings.leadingDelimiter) { + customLeadingDelimiterContainerEl.hide(); + } + + const customIdentsContainerEl = containerEl.createDiv( + className.settingItem + ); + + //* customIdents + new Setting(customIdentsContainerEl) + .setName(i18n.t("setting.orderedCustomIdents")) + .setDesc(i18n.t("setting.orderedCustomIdentsDesc")) + .addText((text) => + text.setValue(settings.customIdents).onChange((value) => { + settings.customIdents = value; + this.plugin.saveSettings(); + }) + ); + + if (settings.styleType !== "customIdent") { + customIdentsContainerEl.hide(); + } + + const specifiedStringContainerEl = containerEl.createDiv( + className.settingItem + ); + + //* specifiedString + new Setting(specifiedStringContainerEl) + .setName(i18n.t("setting.orderedSpecifiedString")) + .setDesc(i18n.t("setting.orderedSpecifiedStringDesc")) + .addText((text) => + text.setValue(settings.specifiedString).onChange((value) => { + settings.specifiedString = value; + this.plugin.saveSettings(); + }) + ); + + if (settings.styleType !== "string") { + specifiedStringContainerEl.hide(); + } + } } diff --git a/locales/en.json b/locales/en.json index 4325c25..3acfaf3 100644 --- a/locales/en.json +++ b/locales/en.json @@ -98,8 +98,8 @@ "enabledInEachNote": "Enabled in each note", "enabledInEachNoteDesc": "Toggle this setting to enable the decoration of headings in each note.", "effect": "Effect", - "ordered": "Ordered", - "orderedDesc": "Toggle this setting to enable the decoration of headings as an ordered or unordered list.", + "decoratorMode": "Mode", + "decoratorModeDesc": "Toggle this setting to decorate headings as ordered list, independent list, or unordered list.", "opacity": "Opacity", "opacityDesc": "Set the opacity of the heading decorator. The value is the form of percentage.", "position": "Position", @@ -110,32 +110,36 @@ "after": "After the heading", "beforeInside": "Before the heading (inside)", "afterInside": "After the heading (inside)", + "ordered": "Ordered", "orderedStyleType": "Style type", - "orderedStyleTypeDesc": "Set the style type for ordered list.", + "orderedStyleTypeDesc": "Set the style type for decorator.", "orderedDelimiter": "Delimiter", - "orderedDelimiterDesc": "Set the delimiter for ordered list.", + "orderedDelimiterDesc": "Set the delimiter for decorator.", "orderedTrailingDelimiter": "Trailing delimiter", - "orderedTrailingDelimiterDesc": "Set whether to add a trailing delimiter for ordered list.", + "orderedTrailingDelimiterDesc": "Set whether to add a trailing delimiter for decorator.", "orderedCustomTrailingDelimiter": "Custom trailing delimiter", - "orderedCustomTrailingDelimiterDesc": "Ignore the delimiter of the ordered list, customize another trailing delimiter.", + "orderedCustomTrailingDelimiterDesc": "Ignore the delimiter of the decorator, customize another trailing delimiter.", "orderedLeadingDelimiter": "Leading delimiter", - "orderedLeadingDelimiterDesc": "Set whether to add a leading delimiter for ordered list.", + "orderedLeadingDelimiterDesc": "Set whether to add a leading delimiter for decorator.", "orderedCustomLeadingDelimiter": "Custom leading delimiter", - "orderedCustomLeadingDelimiterDesc": "Ignore the delimiter of the ordered list, customize another leading delimiter.", + "orderedCustomLeadingDelimiterDesc": "Ignore the delimiter of the decorator, customize another leading delimiter.", "orderedCustomIdents": "Custom list styles", - "orderedCustomIdentsDesc": "For the \"Custom list styles\" option. Set custom list styles for ordered list. Use spaces to separate entries.", + "orderedCustomIdentsDesc": "For the \"Custom list styles\" option. Set custom list styles for decorator. Use spaces to separate entries.", "orderedSpecifiedString": "Specified string", - "orderedSpecifiedStringDesc": "For the \"Specified string\" option. Set a specified string for ordered list.", + "orderedSpecifiedStringDesc": "For the \"Specified string\" option. Set a specified string for decorator.", "orderedAllowZeroLevel": "Allow zero level", "orderedAllowZeroLevelDesc": "If the next heading is more than one level higher, the omitted level is zero instead of one.", "orderedBasedOnExisting": "Based on the existing highest level", - "orderedBasedOnExistingDesc": "Use the highest level of headings in the note as the base for ordered list.", + "orderedBasedOnExistingDesc": "Use the highest level of headings in the note as the base for building decorators.", "orderedAlwaysIgnore": "Always ignore the top-level headings", - "orderedAlwaysIgnoreDesc": "Exclude the top-level heading when building ordered lists. controlled by the \"Maximum number of ignored levels\" option.", + "orderedAlwaysIgnoreDesc": "Exclude the top-level heading when building decorators. controlled by the \"Maximum number of ignored levels\" option.", "orderedIgnoreSingle": "Ignore the single heading at the top-level", - "orderedIgnoreSingleDesc": "If the top-level has only a single heading, exclude it when building an ordered list. controlled by the \"Maximum number of ignored levels\" option.", + "orderedIgnoreSingleDesc": "If the top-level has only a single heading, exclude it when building decorators. controlled by the \"Maximum number of ignored levels\" option.", "orderedIgnoreMaximum": "Maximum number of ignored levels", "orderedIgnoreMaximumDesc": "When enabling the option to ignore top-level headings, specify the maximum number of levels to ignore.", + "independent": "Independent", + "orderedRecLevel": "Level using ordered list", + "orderedRecLevelDesc": "When the heading level exceeds the specified level, build it as an ordered list.", "unordered": "Unordered", "unorderedLevelHeadings": "Level headings", "unorderedLevelHeadingsDesc": "Set the names for each level. The value is 6 entries separated by spaces.", @@ -149,6 +153,13 @@ "folderBlocklistAddTip": "Add a new folder to the blocklist", "fileRegexBlocklistIndex": "Note name regex blocklist {index}", "fileRegexBlocklistPlaceholder": "e.g., /^daily.*/i", - "fileRegexBlocklistAddTip": "Add a new note name regex blocklist" + "fileRegexBlocklistAddTip": "Add a new note name regex blocklist", + "logic": "Logic", + "h1": "H1", + "h2": "H2", + "h3": "H3", + "h4": "H4", + "h5": "H5", + "h6": "H6" } } diff --git a/locales/zh-TW.json b/locales/zh-TW.json index d8d7f5c..c37acc8 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -98,11 +98,11 @@ "enabledInEachNote": "在每個筆記中啟用", "enabledInEachNoteDesc": "切換此設定以啟用每個筆記中標題的裝飾。", "effect": "效果", - "ordered": "有序列表", - "orderedDesc": "切換此設定可將標題裝飾為有序或無序列表。", - "opacity": "不透明度", + "decoratorMode": "裝飾器的模式", + "decoratorModeDesc": "切換此設定可將標題裝飾為有序列表、獨立層級或無序列表。", + "opacity": "裝飾器的不透明度", "opacityDesc": "設定標題裝飾器的不透明度。值是百分比的形式。", - "position": "位置", + "position": "裝飾器的位置", "positionDesc": "設定標題裝飾器的位置。", "maxRecLevel": "所識別的最大級別", "maxRecLevelDesc": "指定所識別標題的最大級別,不處理高於此級別的標題。", @@ -110,32 +110,36 @@ "after": "在標題之後", "beforeInside": "在標題之前 (內部)", "afterInside": "在標題之後 (內部)", + "ordered": "有序列表", "orderedStyleType": "樣式型別", - "orderedStyleTypeDesc": "設定有序列表的樣式型別。", + "orderedStyleTypeDesc": "設定裝飾器的樣式型別。", "orderedDelimiter": "分隔符", - "orderedDelimiterDesc": "設定有序列表的分隔符。", + "orderedDelimiterDesc": "設定裝飾器的分隔符。", "orderedTrailingDelimiter": "尾隨分隔符", - "orderedTrailingDelimiterDesc": "設定是否為有序列表補全尾隨分隔符。", + "orderedTrailingDelimiterDesc": "設定是否為裝飾器補全尾隨分隔符。", "orderedCustomTrailingDelimiter": "自定義尾隨分隔符", - "orderedCustomTrailingDelimiterDesc": "忽略有序列表的分隔符,自定義一個其他的尾隨分隔符。", + "orderedCustomTrailingDelimiterDesc": "忽略裝飾器的分隔符,自定義一個其他的尾隨分隔符。", "orderedLeadingDelimiter": "前導分隔符", - "orderedLeadingDelimiterDesc": "設定是否為有序列表新增前導分隔符。", + "orderedLeadingDelimiterDesc": "設定是否為裝飾器新增前導分隔符。", "orderedCustomLeadingDelimiter": "自定義前導分隔符", - "orderedCustomLeadingDelimiterDesc": "忽略有序列表的分隔符,自定義一個其他的前導分隔符。", + "orderedCustomLeadingDelimiterDesc": "忽略裝飾器的分隔符,自定義一個其他的前導分隔符。", "orderedCustomIdents": "自定義列表樣式", - "orderedCustomIdentsDesc": "針對\"自定義列表樣式\"選項。為有序列表設定自定義列表樣式。使用空格分隔條目。", + "orderedCustomIdentsDesc": "針對\"自定義列表樣式\"選項。為裝飾器設定自定義列表樣式。使用空格分隔條目。", "orderedSpecifiedString": "指定字串", - "orderedSpecifiedStringDesc": "針對\"指定字串\"選項。為有序列表設定指定的字串。", + "orderedSpecifiedStringDesc": "針對\"指定字串\"選項。為裝飾器設定指定的字串。", "orderedAllowZeroLevel": "允許零級別", "orderedAllowZeroLevelDesc": "如果下一個標題高出一個以上的級別,則省略的級別為零而不是一。", "orderedBasedOnExisting": "基於現有的最高級別", - "orderedBasedOnExistingDesc": "使用筆記中最高級別的標題作為有序列表的基礎。", + "orderedBasedOnExistingDesc": "使用筆記中最高級別的標題作為構建裝飾器的基礎。", "orderedAlwaysIgnore": "始終忽略頂層的標題", - "orderedAlwaysIgnoreDesc": "在構建有序列表時將頂層的標題排除掉,受\"忽略的最大層級數量\"選項控制。", + "orderedAlwaysIgnoreDesc": "在構建裝飾器時將頂層的標題排除掉,受\"忽略的最大層級數量\"選項控制。", "orderedIgnoreSingle": "忽略頂層的獨立標題", - "orderedIgnoreSingleDesc": "如果頂層只有一個標題,則在構建有序列表時將其排除。受\"忽略的最大層級數量\"選項控制。", + "orderedIgnoreSingleDesc": "如果頂層只有一個標題,則在構建裝飾器時將其排除。受\"忽略的最大層級數量\"選項控制。", "orderedIgnoreMaximum": "忽略的最大層級數量", "orderedIgnoreMaximumDesc": "在啟用忽略頂層標題的選項時,指定可忽略的最大層級數量。", + "independent": "獨立層級", + "orderedRecLevel": "使用有序列表的級別", + "orderedRecLevelDesc": "標題級別超出指定級別後按有序列表進行構建。", "unordered": "無序列表", "unorderedLevelHeadings": "級別標題", "unorderedLevelHeadingsDesc": "設定每個級別的名稱。值為 6 個條目,以空格分隔。", @@ -149,6 +153,13 @@ "folderBlocklistAddTip": "新增新的資料夾到阻止列表", "fileRegexBlocklistIndex": "筆記名稱正則表示式阻止列表 {index}", "fileRegexBlocklistPlaceholder": "例如:/^daily.*/i", - "fileRegexBlocklistAddTip": "新增新的筆記名稱正則表示式到阻止列表" + "fileRegexBlocklistAddTip": "新增新的筆記名稱正則表示式到阻止列表", + "logic": "邏輯控制", + "h1": "H1 級別", + "h2": "H2 級別", + "h3": "H3 級別", + "h4": "H4 級別", + "h5": "H5 級別", + "h6": "H6 級別" } } diff --git a/locales/zh.json b/locales/zh.json index 4afb1cf..ee3b06e 100644 --- a/locales/zh.json +++ b/locales/zh.json @@ -98,11 +98,11 @@ "enabledInEachNote": "在每个笔记中启用", "enabledInEachNoteDesc": "切换此设置以启用每个笔记中标题的装饰。", "effect": "效果", - "ordered": "有序列表", - "orderedDesc": "切换此设置可将标题装饰为有序或无序列表。", - "opacity": "不透明度", + "decoratorMode": "装饰器的模式", + "decoratorModeDesc": "切换此设置可将标题装饰为有序列表、独立层级或无序列表。", + "opacity": "装饰器的不透明度", "opacityDesc": "设置标题装饰器的不透明度。值是百分比的形式。", - "position": "位置", + "position": "装饰器的位置", "positionDesc": "设置标题装饰器的位置。", "maxRecLevel": "所识别的最大级别", "maxRecLevelDesc": "指定所识别标题的最大级别,不处理高于此级别的标题。", @@ -110,32 +110,36 @@ "after": "在标题之后", "beforeInside": "在标题之前 (内部)", "afterInside": "在标题之后 (内部)", + "ordered": "有序列表", "orderedStyleType": "样式类型", - "orderedStyleTypeDesc": "设置有序列表的样式类型。", + "orderedStyleTypeDesc": "设置装饰器的样式类型。", "orderedDelimiter": "分隔符", - "orderedDelimiterDesc": "设置有序列表的分隔符。", + "orderedDelimiterDesc": "设置装饰器的分隔符。", "orderedTrailingDelimiter": "尾随分隔符", - "orderedTrailingDelimiterDesc": "设置是否为有序列表添加尾随分隔符。", + "orderedTrailingDelimiterDesc": "设置是否为装饰器添加尾随分隔符。", "orderedCustomTrailingDelimiter": "自定义尾随分隔符", - "orderedCustomTrailingDelimiterDesc": "忽略有序列表的分隔符,自定义一个其他的尾随分隔符。", + "orderedCustomTrailingDelimiterDesc": "忽略装饰器的分隔符,自定义一个其他的尾随分隔符。", "orderedLeadingDelimiter": "前导分隔符", - "orderedLeadingDelimiterDesc": "设置是否为有序列表添加前导分隔符。", + "orderedLeadingDelimiterDesc": "设置是否为装饰器添加前导分隔符。", "orderedCustomLeadingDelimiter": "自定义前导分隔符", - "orderedCustomLeadingDelimiterDesc": "忽略有序列表的分隔符,自定义一个其他的前导分隔符。", + "orderedCustomLeadingDelimiterDesc": "忽略装饰器的分隔符,自定义一个其他的前导分隔符。", "orderedCustomIdents": "自定义列表样式", - "orderedCustomIdentsDesc": "针对\"自定义列表样式\"选项。为有序列表设置自定义列表样式。使用空格分隔条目。", + "orderedCustomIdentsDesc": "针对\"自定义列表样式\"选项。为装饰器设置自定义列表样式。使用空格分隔条目。", "orderedSpecifiedString": "指定字符串", - "orderedSpecifiedStringDesc": "针对\"指定字符串\"选项。为有序列表设置指定的字符串。", + "orderedSpecifiedStringDesc": "针对\"指定字符串\"选项。为装饰器设置指定的字符串。", "orderedAllowZeroLevel": "允许零级别", "orderedAllowZeroLevelDesc": "如果下一个标题高出一个以上的级别,则省略的级别为零而不是一。", "orderedBasedOnExisting": "基于现有的最高级别", - "orderedBasedOnExistingDesc": "使用笔记中最高级别的标题作为有序列表的基础。", + "orderedBasedOnExistingDesc": "使用笔记中最高级别的标题作为构建装饰器的基础。", "orderedAlwaysIgnore": "始终忽略顶层的标题", - "orderedAlwaysIgnoreDesc": "在构建有序列表时将顶层的标题排除掉,受\"忽略的最大层级数量\"选项控制。", + "orderedAlwaysIgnoreDesc": "在构建装饰器时将顶层的标题排除掉,受\"忽略的最大层级数量\"选项控制。", "orderedIgnoreSingle": "忽略顶层的独立标题", - "orderedIgnoreSingleDesc": "如果顶层只有一个标题,则在构建有序列表时将其排除。受\"忽略的最大层级数量\"选项控制。", + "orderedIgnoreSingleDesc": "如果顶层只有一个标题,则在构建装饰器时将其排除。受\"忽略的最大层级数量\"选项控制。", "orderedIgnoreMaximum": "忽略的最大层级数量", "orderedIgnoreMaximumDesc": "在启用忽略顶层标题的选项时,指定可忽略的最大层级数量。", + "independent": "独立层级", + "orderedRecLevel": "使用有序列表的级别", + "orderedRecLevelDesc": "标题级别超出指定级别后按有序列表进行构建。", "unordered": "无序列表", "unorderedLevelHeadings": "级别标题", "unorderedLevelHeadingsDesc": "设置每个级别的名称。值为 6 个条目,以空格分隔。", @@ -149,6 +153,13 @@ "folderBlocklistAddTip": "添加新的文件夹到阻止列表", "fileRegexBlocklistIndex": "笔记名称正则表达式阻止列表 {index}", "fileRegexBlocklistPlaceholder": "例如:/^daily.*/i", - "fileRegexBlocklistAddTip": "添加新的笔记名称正则表达式到阻止列表" + "fileRegexBlocklistAddTip": "添加新的笔记名称正则表达式到阻止列表", + "logic": "逻辑控制", + "h1": "H1 级别", + "h2": "H2 级别", + "h3": "H3 级别", + "h4": "H4 级别", + "h5": "H5 级别", + "h6": "H6 级别" } } diff --git a/styles.css b/styles.css index aa42c55..ca51359 100644 --- a/styles.css +++ b/styles.css @@ -443,3 +443,19 @@ body { opacity: 100%; } /* file-explorer start */ + +/* setting start */ +body .heading-decorator-setting-container, +.heading-decorator-setting-item + .setting-item-heading { + margin-top: 0.75em; +} + +body .heading-decorator-setting-container .setting-item-heading:first-child { + padding-top: 0.75em; +} + +body .heading-decorator-setting-item { + padding-top: 0.75em; + border-top: 1px solid var(--background-modifier-border); +} +/* setting end */ diff --git a/test/common/counter.spec.ts b/test/common/counter.spec.ts index a641059..96956fc 100644 --- a/test/common/counter.spec.ts +++ b/test/common/counter.spec.ts @@ -1,1231 +1,1449 @@ import "mocha"; import { expect } from "chai"; -import { Counter, Querier } from "../../common/counter"; +import type { IndependentDecoratorSettings } from "../../common/data"; +import { + Querier, + UnorderedCounter, + OrderedCounter, + IndependentCounter, +} from "../../common/counter"; describe("common/counter", function () { - it("Querier.handler", function () { - const querier1 = new Querier(); - - expect(querier1.handler(-1)).to.be.empty; - expect(querier1.handler(0)).to.be.empty; - expect(querier1.handler(7)).to.be.empty; - - expect(querier1.handler(1)).to.deep.equal([1]); - expect(querier1.handler(2)).to.deep.equal([1, 1]); - expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); - - expect(querier1.handler(1)).to.deep.equal([2]); - expect(querier1.handler(2)).to.deep.equal([2, 1]); - expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); - - expect(querier1.handler(2)).to.deep.equal([2, 2]); - expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); - - expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 1, 1, 1]); - - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 1, 1]); - - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 2]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 1]); - - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 2]); - - const querier2 = new Querier(); - - expect(querier2.handler(2)).to.deep.equal([1, 1]); - expect(querier2.handler(3)).to.deep.equal([1, 1, 1]); - expect(querier2.handler(4)).to.deep.equal([1, 1, 1, 1]); - expect(querier2.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); - expect(querier2.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); - - expect(querier2.handler(2)).to.deep.equal([1, 2]); - expect(querier2.handler(3)).to.deep.equal([1, 2, 1]); - expect(querier2.handler(4)).to.deep.equal([1, 2, 1, 1]); - expect(querier2.handler(5)).to.deep.equal([1, 2, 1, 1, 1]); - expect(querier2.handler(6)).to.deep.equal([1, 2, 1, 1, 1, 1]); - - expect(querier2.handler(4)).to.deep.equal([1, 2, 1, 2]); - expect(querier2.handler(5)).to.deep.equal([1, 2, 1, 2, 1]); - expect(querier2.handler(6)).to.deep.equal([1, 2, 1, 2, 1, 1]); - - const querier3 = new Querier(); - - expect(querier3.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); - expect(querier3.handler(2)).to.deep.equal([1, 2]); - expect(querier3.handler(1)).to.deep.equal([2]); - expect(querier3.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); - - const querier4 = new Querier(); - - expect(querier4.handler(1)).to.deep.equal([1]); - expect(querier4.handler(3)).to.deep.equal([1, 1, 1]); - expect(querier4.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); - expect(querier4.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 2]); - - expect(querier4.handler(1)).to.deep.equal([2]); - expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier4.handler(3)).to.deep.equal([2, 1, 2]); - expect(querier4.handler(6)).to.deep.equal([2, 1, 2, 1, 1, 1]); - - expect(querier4.handler(2)).to.deep.equal([2, 2]); - expect(querier4.handler(3)).to.deep.equal([2, 2, 1]); - expect(querier4.handler(4)).to.deep.equal([2, 2, 1, 1]); - expect(querier4.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); - expect(querier4.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); - }); - - it("Querier.handler with allowZeroLevel", function () { - const querier1 = new Querier(true); - - expect(querier1.handler(-1)).to.be.empty; - expect(querier1.handler(0)).to.be.empty; - expect(querier1.handler(7)).to.be.empty; - - expect(querier1.handler(1)).to.deep.equal([1]); - expect(querier1.handler(2)).to.deep.equal([1, 1]); - expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); - - expect(querier1.handler(1)).to.deep.equal([2]); - expect(querier1.handler(2)).to.deep.equal([2, 1]); - expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); - - expect(querier1.handler(2)).to.deep.equal([2, 2]); - expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); - - expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 1, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 1, 1, 1]); - - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 1]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 1, 1]); - - expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 2]); - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 1]); - - expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 2]); - - const querier2 = new Querier(true); - - expect(querier2.handler(2)).to.deep.equal([0, 1]); - expect(querier2.handler(3)).to.deep.equal([0, 1, 1]); - expect(querier2.handler(4)).to.deep.equal([0, 1, 1, 1]); - expect(querier2.handler(5)).to.deep.equal([0, 1, 1, 1, 1]); - expect(querier2.handler(6)).to.deep.equal([0, 1, 1, 1, 1, 1]); - - expect(querier2.handler(2)).to.deep.equal([0, 2]); - expect(querier2.handler(3)).to.deep.equal([0, 2, 1]); - expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 1]); - expect(querier2.handler(5)).to.deep.equal([0, 2, 1, 1, 1]); - expect(querier2.handler(6)).to.deep.equal([0, 2, 1, 1, 1, 1]); - - expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 2]); - expect(querier2.handler(5)).to.deep.equal([0, 2, 1, 2, 1]); - expect(querier2.handler(6)).to.deep.equal([0, 2, 1, 2, 1, 1]); - - const querier3 = new Querier(true); - - expect(querier3.handler(6)).to.deep.equal([0, 0, 0, 0, 0, 1]); - expect(querier3.handler(2)).to.deep.equal([0, 1]); - expect(querier3.handler(1)).to.deep.equal([1]); - expect(querier3.handler(6)).to.deep.equal([1, 0, 0, 0, 0, 1]); - - const querier4 = new Querier(true); - - expect(querier4.handler(1)).to.deep.equal([1]); - expect(querier4.handler(3)).to.deep.equal([1, 0, 1]); - expect(querier4.handler(6)).to.deep.equal([1, 0, 1, 0, 0, 1]); - expect(querier4.handler(6)).to.deep.equal([1, 0, 1, 0, 0, 2]); - - expect(querier4.handler(1)).to.deep.equal([2]); - expect(querier4.handler(3)).to.deep.equal([2, 0, 1]); - expect(querier4.handler(3)).to.deep.equal([2, 0, 2]); - expect(querier4.handler(6)).to.deep.equal([2, 0, 2, 0, 0, 1]); - - expect(querier4.handler(2)).to.deep.equal([2, 1]); - expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier4.handler(4)).to.deep.equal([2, 1, 1, 1]); - expect(querier4.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); - expect(querier4.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); - }); - - it("Querier.handler with maxRecLevel", function () { - const querier1 = new Querier(false, 4); - - expect(querier1.handler(-1)).to.be.empty; - expect(querier1.handler(0)).to.be.empty; - expect(querier1.handler(7)).to.be.empty; - - expect(querier1.handler(1)).to.deep.equal([1]); - expect(querier1.handler(2)).to.deep.equal([1, 1]); - expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(1)).to.deep.equal([2]); - expect(querier1.handler(2)).to.deep.equal([2, 1]); - expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(2)).to.deep.equal([2, 2]); - expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(5)).to.be.empty; - expect(querier1.handler(6)).to.be.empty; - - expect(querier1.handler(6)).to.be.empty; - - const querier2 = new Querier(true, 4); - - expect(querier2.handler(2)).to.deep.equal([0, 1]); - expect(querier2.handler(3)).to.deep.equal([0, 1, 1]); - expect(querier2.handler(4)).to.deep.equal([0, 1, 1, 1]); - expect(querier2.handler(5)).to.be.empty; - expect(querier2.handler(6)).to.be.empty; - - expect(querier2.handler(2)).to.deep.equal([0, 2]); - expect(querier2.handler(3)).to.deep.equal([0, 2, 1]); - expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 1]); - expect(querier2.handler(5)).to.be.empty; - expect(querier2.handler(6)).to.be.empty; - - expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 2]); - expect(querier2.handler(5)).to.be.empty; - expect(querier2.handler(6)).to.be.empty; - - const querier3 = new Querier(true, 3); - - expect(querier3.handler(6)).to.be.empty; - expect(querier3.handler(2)).to.deep.equal([0, 1]); - expect(querier3.handler(1)).to.deep.equal([1]); - expect(querier3.handler(6)).to.be.empty; - - const querier4 = new Querier(true, 3); - - expect(querier4.handler(1)).to.deep.equal([1]); - expect(querier4.handler(3)).to.deep.equal([1, 0, 1]); - expect(querier4.handler(6)).to.be.empty; - expect(querier4.handler(6)).to.be.empty; - - expect(querier4.handler(1)).to.deep.equal([2]); - expect(querier4.handler(3)).to.deep.equal([2, 0, 1]); - expect(querier4.handler(3)).to.deep.equal([2, 0, 2]); - expect(querier4.handler(6)).to.be.empty; - - expect(querier4.handler(2)).to.deep.equal([2, 1]); - expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); - expect(querier4.handler(4)).to.be.empty; - expect(querier4.handler(5)).to.be.empty; - expect(querier4.handler(6)).to.be.empty; - }); - - it("Querier.query()", function () { - const querier1 = new Querier(); - expect(querier1.query()).to.equal(5); - - querier1.handler(1); - expect(querier1.query()).to.equal(0); - - querier1.handler(2); - expect(querier1.query()).to.equal(0); - - querier1.handler(3); - expect(querier1.query()).to.equal(0); - - querier1.handler(4); - expect(querier1.query()).to.equal(0); - - querier1.handler(5); - expect(querier1.query()).to.equal(0); - - querier1.handler(6); - expect(querier1.query()).to.equal(0); - - querier1.handler(6); - expect(querier1.query()).to.equal(0); - - querier1.handler(5); - expect(querier1.query()).to.equal(0); - - querier1.handler(4); - expect(querier1.query()).to.equal(0); - - querier1.handler(3); - expect(querier1.query()).to.equal(0); - - querier1.handler(2); - expect(querier1.query()).to.equal(0); - - querier1.handler(1); - expect(querier1.query()).to.equal(0); - - querier1.handler(0); - expect(querier1.query()).to.equal(0); - - querier1.handler(-1); - expect(querier1.query()).to.equal(0); - - const querier2 = new Querier(); - - querier2.handler(6); - expect(querier2.query()).to.equal(5); - - querier2.handler(2); - expect(querier2.query()).to.equal(1); - - querier2.handler(1); - expect(querier2.query()).to.equal(0); - - const querier3 = new Querier(); - - querier3.handler(6); - expect(querier3.query()).to.equal(5); - - querier3.handler(3); - expect(querier3.query()).to.equal(2); - - querier3.handler(4); - expect(querier3.query()).to.equal(2); - - const querier4 = new Querier(); - - querier4.handler(3); - expect(querier4.query()).to.equal(2); - - querier4.handler(4); - expect(querier4.query()).to.equal(2); - - querier4.handler(5); - expect(querier4.query()).to.equal(2); - - querier4.handler(6); - expect(querier4.query()).to.equal(2); - - querier4.handler(4); - expect(querier4.query()).to.equal(2); - - querier4.handler(3); - expect(querier4.query()).to.equal(2); - - const querier5 = new Querier(); - - querier5.handler(2); - expect(querier5.query()).to.equal(1); - - querier5.handler(6); - expect(querier5.query()).to.equal(1); - - querier5.handler(2); - expect(querier5.query()).to.equal(1); - - querier5.handler(1); - expect(querier5.query()).to.equal(0); - }); - - it("Querier.query(ignoreSingle = true)", function () { - const querier1 = new Querier(); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(1); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(2); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(3); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(4); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(5); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true)).to.equal(5); - - querier1.handler(5); - expect(querier1.query(true)).to.equal(4); - - querier1.handler(4); - expect(querier1.query(true)).to.equal(3); - - querier1.handler(3); - expect(querier1.query(true)).to.equal(2); - - querier1.handler(2); - expect(querier1.query(true)).to.equal(1); - - querier1.handler(1); - expect(querier1.query(true)).to.equal(0); - - const querier2 = new Querier(); - - querier2.handler(6); - expect(querier2.query(true)).to.equal(6); - - querier2.handler(2); - expect(querier2.query(true)).to.equal(1); - - querier2.handler(1); - expect(querier2.query(true)).to.equal(0); - - const querier3 = new Querier(); - - querier3.handler(6); - expect(querier3.query(true)).to.equal(6); - - querier3.handler(3); - expect(querier3.query(true)).to.equal(2); - - querier3.handler(4); - expect(querier3.query(true)).to.equal(2); - - const querier4 = new Querier(); - - querier4.handler(3); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(4); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(5); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(6); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(4); - expect(querier4.query(true)).to.equal(3); - - querier4.handler(3); - expect(querier4.query(true)).to.equal(2); - }); - - it("Querier.query(ignoreSingle = true) with allowZeroLevel", function () { - const querier1 = new Querier(true); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(1); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(2); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(3); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(4); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(5); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true)).to.equal(5); - - querier1.handler(5); - expect(querier1.query(true)).to.equal(4); - - querier1.handler(4); - expect(querier1.query(true)).to.equal(3); - - querier1.handler(3); - expect(querier1.query(true)).to.equal(2); - - querier1.handler(2); - expect(querier1.query(true)).to.equal(1); - - querier1.handler(1); - expect(querier1.query(true)).to.equal(0); - - const querier2 = new Querier(true); - - querier2.handler(6); - expect(querier2.query(true)).to.equal(6); - - querier2.handler(2); - expect(querier2.query(true)).to.equal(1); - - querier2.handler(1); - expect(querier2.query(true)).to.equal(0); - - const querier3 = new Querier(true); - - querier3.handler(6); - expect(querier3.query(true)).to.equal(6); - - querier3.handler(3); - expect(querier3.query(true)).to.equal(2); - - querier3.handler(4); - expect(querier3.query(true)).to.equal(2); - - const querier4 = new Querier(true); - - querier4.handler(3); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(4); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(5); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(6); - expect(querier4.query(true)).to.equal(6); - - querier4.handler(4); - expect(querier4.query(true)).to.equal(3); - - querier4.handler(3); - expect(querier4.query(true)).to.equal(2); - }); - - it("Querier.query(ignoreSingle = true) with ignoreMaximum parameter", function () { - const querier1 = new Querier(); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(1); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(2); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(3); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(4); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(5); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true, 6)).to.equal(6); - - querier1.handler(6); - expect(querier1.query(true, 6)).to.equal(5); - - querier1.handler(5); - expect(querier1.query(true, 6)).to.equal(4); - - querier1.handler(4); - expect(querier1.query(true, 6)).to.equal(3); - - querier1.handler(3); - expect(querier1.query(true, 6)).to.equal(2); - - querier1.handler(2); - expect(querier1.query(true, 6)).to.equal(1); - - querier1.handler(1); - expect(querier1.query(true, 6)).to.equal(0); - - const querier2 = new Querier(); - - querier2.handler(6); - expect(querier2.query(true, 2)).to.equal(2); - - querier2.handler(2); - expect(querier2.query(true, 2)).to.equal(1); - - querier2.handler(1); - expect(querier2.query(true, 2)).to.equal(0); - - const querier3 = new Querier(); - - querier3.handler(6); - expect(querier3.query(true, 1)).to.equal(1); - - querier3.handler(3); - expect(querier3.query(true, 1)).to.equal(1); - - querier3.handler(4); - expect(querier3.query(true, 1)).to.equal(1); - - const querier4 = new Querier(); - - querier4.handler(3); - expect(querier4.query(true, 1)).to.equal(1); - - querier4.handler(4); - expect(querier4.query(true, 1)).to.equal(1); - - querier4.handler(5); - expect(querier4.query(true, 1)).to.equal(1); - - querier4.handler(6); - expect(querier4.query(true, 1)).to.equal(1); - - querier4.handler(4); - expect(querier4.query(true, 1)).to.equal(1); - - querier4.handler(3); - expect(querier4.query(true, 1)).to.equal(1); - }); - - it("Counter.decorator with default", function () { - const counter1 = new Counter(); - expect(counter1.decorator(-1)).to.be.empty; - expect(counter1.decorator(0)).to.empty; - expect(counter1.decorator(1)).to.equal("1"); - expect(counter1.decorator(2)).to.equal("1.1"); - expect(counter1.decorator(3)).to.equal("1.1.1"); - expect(counter1.decorator(4)).to.equal("1.1.1.1"); - expect(counter1.decorator(5)).to.equal("1.1.1.1.1"); - expect(counter1.decorator(6)).to.equal("1.1.1.1.1.1"); - expect(counter1.decorator(7)).to.empty; - - const counter2 = new Counter(); - expect(counter2.decorator(3)).to.equal("1.1.1"); - expect(counter2.decorator(4)).to.equal("1.1.1.1"); - expect(counter2.decorator(5)).to.equal("1.1.1.1.1"); - expect(counter2.decorator(6)).to.equal("1.1.1.1.1.1"); - expect(counter2.decorator(7)).to.empty; - expect(counter2.decorator(1)).to.equal("2"); - expect(counter2.decorator(2)).to.equal("2.1"); - expect(counter2.decorator(6)).to.equal("2.1.1.1.1.1"); - }); - - it("Counter.decorator with unordered", function () { - const counter = new Counter({ - ordered: false, - levelHeadings: ["H1", "H2", "H3", "H4", "H5", "H6"], + describe("Querier", function () { + it("Querier.handler", function () { + const querier1 = new Querier(); + + expect(querier1.handler(-1)).to.be.empty; + expect(querier1.handler(0)).to.be.empty; + expect(querier1.handler(7)).to.be.empty; + + expect(querier1.handler(1)).to.deep.equal([1]); + expect(querier1.handler(2)).to.deep.equal([1, 1]); + expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); + + expect(querier1.handler(1)).to.deep.equal([2]); + expect(querier1.handler(2)).to.deep.equal([2, 1]); + expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); + + expect(querier1.handler(2)).to.deep.equal([2, 2]); + expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); + + expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 1, 1, 1]); + + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 1, 1]); + + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 2]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 1]); + + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 2]); + + const querier2 = new Querier(); + + expect(querier2.handler(2)).to.deep.equal([1, 1]); + expect(querier2.handler(3)).to.deep.equal([1, 1, 1]); + expect(querier2.handler(4)).to.deep.equal([1, 1, 1, 1]); + expect(querier2.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); + expect(querier2.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); + + expect(querier2.handler(2)).to.deep.equal([1, 2]); + expect(querier2.handler(3)).to.deep.equal([1, 2, 1]); + expect(querier2.handler(4)).to.deep.equal([1, 2, 1, 1]); + expect(querier2.handler(5)).to.deep.equal([1, 2, 1, 1, 1]); + expect(querier2.handler(6)).to.deep.equal([1, 2, 1, 1, 1, 1]); + + expect(querier2.handler(4)).to.deep.equal([1, 2, 1, 2]); + expect(querier2.handler(5)).to.deep.equal([1, 2, 1, 2, 1]); + expect(querier2.handler(6)).to.deep.equal([1, 2, 1, 2, 1, 1]); + + const querier3 = new Querier(); + + expect(querier3.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); + expect(querier3.handler(2)).to.deep.equal([1, 2]); + expect(querier3.handler(1)).to.deep.equal([2]); + expect(querier3.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); + + const querier4 = new Querier(); + + expect(querier4.handler(1)).to.deep.equal([1]); + expect(querier4.handler(3)).to.deep.equal([1, 1, 1]); + expect(querier4.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); + expect(querier4.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 2]); + + expect(querier4.handler(1)).to.deep.equal([2]); + expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier4.handler(3)).to.deep.equal([2, 1, 2]); + expect(querier4.handler(6)).to.deep.equal([2, 1, 2, 1, 1, 1]); + + expect(querier4.handler(2)).to.deep.equal([2, 2]); + expect(querier4.handler(3)).to.deep.equal([2, 2, 1]); + expect(querier4.handler(4)).to.deep.equal([2, 2, 1, 1]); + expect(querier4.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); + expect(querier4.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); }); - expect(counter.decorator(-1)).to.be.empty; - expect(counter.decorator(0)).to.empty; - expect(counter.decorator(1)).to.equal("H1"); - expect(counter.decorator(2)).to.equal("H2"); - expect(counter.decorator(3)).to.equal("H3"); - expect(counter.decorator(4)).to.equal("H4"); - expect(counter.decorator(5)).to.equal("H5"); - expect(counter.decorator(6)).to.equal("H6"); - expect(counter.decorator(7)).to.empty; - }); - it("Counter.decorator with decimal styleType", function () { - const counter = new Counter({ - ordered: true, - styleType: "decimal", + it("Querier.handler with allowZeroLevel", function () { + const querier1 = new Querier(true); + + expect(querier1.handler(-1)).to.be.empty; + expect(querier1.handler(0)).to.be.empty; + expect(querier1.handler(7)).to.be.empty; + + expect(querier1.handler(1)).to.deep.equal([1]); + expect(querier1.handler(2)).to.deep.equal([1, 1]); + expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([1, 1, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([1, 1, 1, 1, 1, 1]); + + expect(querier1.handler(1)).to.deep.equal([2]); + expect(querier1.handler(2)).to.deep.equal([2, 1]); + expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); + + expect(querier1.handler(2)).to.deep.equal([2, 2]); + expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 1, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 1, 1, 1, 1]); + + expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 1, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 1, 1, 1]); + + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 1]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 1, 1]); + + expect(querier1.handler(5)).to.deep.equal([2, 2, 2, 2, 2]); + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 1]); + + expect(querier1.handler(6)).to.deep.equal([2, 2, 2, 2, 2, 2]); + + const querier2 = new Querier(true); + + expect(querier2.handler(2)).to.deep.equal([0, 1]); + expect(querier2.handler(3)).to.deep.equal([0, 1, 1]); + expect(querier2.handler(4)).to.deep.equal([0, 1, 1, 1]); + expect(querier2.handler(5)).to.deep.equal([0, 1, 1, 1, 1]); + expect(querier2.handler(6)).to.deep.equal([0, 1, 1, 1, 1, 1]); + + expect(querier2.handler(2)).to.deep.equal([0, 2]); + expect(querier2.handler(3)).to.deep.equal([0, 2, 1]); + expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 1]); + expect(querier2.handler(5)).to.deep.equal([0, 2, 1, 1, 1]); + expect(querier2.handler(6)).to.deep.equal([0, 2, 1, 1, 1, 1]); + + expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 2]); + expect(querier2.handler(5)).to.deep.equal([0, 2, 1, 2, 1]); + expect(querier2.handler(6)).to.deep.equal([0, 2, 1, 2, 1, 1]); + + const querier3 = new Querier(true); + + expect(querier3.handler(6)).to.deep.equal([0, 0, 0, 0, 0, 1]); + expect(querier3.handler(2)).to.deep.equal([0, 1]); + expect(querier3.handler(1)).to.deep.equal([1]); + expect(querier3.handler(6)).to.deep.equal([1, 0, 0, 0, 0, 1]); + + const querier4 = new Querier(true); + + expect(querier4.handler(1)).to.deep.equal([1]); + expect(querier4.handler(3)).to.deep.equal([1, 0, 1]); + expect(querier4.handler(6)).to.deep.equal([1, 0, 1, 0, 0, 1]); + expect(querier4.handler(6)).to.deep.equal([1, 0, 1, 0, 0, 2]); + + expect(querier4.handler(1)).to.deep.equal([2]); + expect(querier4.handler(3)).to.deep.equal([2, 0, 1]); + expect(querier4.handler(3)).to.deep.equal([2, 0, 2]); + expect(querier4.handler(6)).to.deep.equal([2, 0, 2, 0, 0, 1]); + + expect(querier4.handler(2)).to.deep.equal([2, 1]); + expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier4.handler(4)).to.deep.equal([2, 1, 1, 1]); + expect(querier4.handler(5)).to.deep.equal([2, 1, 1, 1, 1]); + expect(querier4.handler(6)).to.deep.equal([2, 1, 1, 1, 1, 1]); }); - expect(counter.decorator(-1)).to.be.empty; - expect(counter.decorator(0)).to.be.empty; - expect(counter.decorator(1)).to.equal("1"); - expect(counter.decorator(2)).to.equal("1.1"); - expect(counter.decorator(2)).to.equal("1.2"); - expect(counter.decorator(2)).to.equal("1.3"); - expect(counter.decorator(2)).to.equal("1.4"); - expect(counter.decorator(2)).to.equal("1.5"); - expect(counter.decorator(2)).to.equal("1.6"); - expect(counter.decorator(2)).to.equal("1.7"); - expect(counter.decorator(2)).to.equal("1.8"); - expect(counter.decorator(2)).to.equal("1.9"); - expect(counter.decorator(2)).to.equal("1.10"); - expect(counter.decorator(2)).to.equal("1.11"); - expect(counter.decorator(1)).to.equal("2"); - expect(counter.decorator(7)).to.be.empty; - }); - it("Counter.decorator with lowerAlpha styleType", function () { - const counter = new Counter({ - ordered: true, - styleType: "lowerAlpha", + it("Querier.handler with maxRecLevel", function () { + const querier1 = new Querier(false, 4); + + expect(querier1.handler(-1)).to.be.empty; + expect(querier1.handler(0)).to.be.empty; + expect(querier1.handler(7)).to.be.empty; + + expect(querier1.handler(1)).to.deep.equal([1]); + expect(querier1.handler(2)).to.deep.equal([1, 1]); + expect(querier1.handler(3)).to.deep.equal([1, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([1, 1, 1, 1]); + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(1)).to.deep.equal([2]); + expect(querier1.handler(2)).to.deep.equal([2, 1]); + expect(querier1.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 1, 1, 1]); + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(2)).to.deep.equal([2, 2]); + expect(querier1.handler(3)).to.deep.equal([2, 2, 1]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 1, 1]); + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(3)).to.deep.equal([2, 2, 2]); + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 1]); + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(4)).to.deep.equal([2, 2, 2, 2]); + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(5)).to.be.empty; + expect(querier1.handler(6)).to.be.empty; + + expect(querier1.handler(6)).to.be.empty; + + const querier2 = new Querier(true, 4); + + expect(querier2.handler(2)).to.deep.equal([0, 1]); + expect(querier2.handler(3)).to.deep.equal([0, 1, 1]); + expect(querier2.handler(4)).to.deep.equal([0, 1, 1, 1]); + expect(querier2.handler(5)).to.be.empty; + expect(querier2.handler(6)).to.be.empty; + + expect(querier2.handler(2)).to.deep.equal([0, 2]); + expect(querier2.handler(3)).to.deep.equal([0, 2, 1]); + expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 1]); + expect(querier2.handler(5)).to.be.empty; + expect(querier2.handler(6)).to.be.empty; + + expect(querier2.handler(4)).to.deep.equal([0, 2, 1, 2]); + expect(querier2.handler(5)).to.be.empty; + expect(querier2.handler(6)).to.be.empty; + + const querier3 = new Querier(true, 3); + + expect(querier3.handler(6)).to.be.empty; + expect(querier3.handler(2)).to.deep.equal([0, 1]); + expect(querier3.handler(1)).to.deep.equal([1]); + expect(querier3.handler(6)).to.be.empty; + + const querier4 = new Querier(true, 3); + + expect(querier4.handler(1)).to.deep.equal([1]); + expect(querier4.handler(3)).to.deep.equal([1, 0, 1]); + expect(querier4.handler(6)).to.be.empty; + expect(querier4.handler(6)).to.be.empty; + + expect(querier4.handler(1)).to.deep.equal([2]); + expect(querier4.handler(3)).to.deep.equal([2, 0, 1]); + expect(querier4.handler(3)).to.deep.equal([2, 0, 2]); + expect(querier4.handler(6)).to.be.empty; + + expect(querier4.handler(2)).to.deep.equal([2, 1]); + expect(querier4.handler(3)).to.deep.equal([2, 1, 1]); + expect(querier4.handler(4)).to.be.empty; + expect(querier4.handler(5)).to.be.empty; + expect(querier4.handler(6)).to.be.empty; + }); + + it("Querier.query()", function () { + const querier1 = new Querier(); + expect(querier1.query()).to.equal(5); + + querier1.handler(1); + expect(querier1.query()).to.equal(0); + + querier1.handler(2); + expect(querier1.query()).to.equal(0); + + querier1.handler(3); + expect(querier1.query()).to.equal(0); + + querier1.handler(4); + expect(querier1.query()).to.equal(0); + + querier1.handler(5); + expect(querier1.query()).to.equal(0); + + querier1.handler(6); + expect(querier1.query()).to.equal(0); + + querier1.handler(6); + expect(querier1.query()).to.equal(0); + + querier1.handler(5); + expect(querier1.query()).to.equal(0); + + querier1.handler(4); + expect(querier1.query()).to.equal(0); + + querier1.handler(3); + expect(querier1.query()).to.equal(0); + + querier1.handler(2); + expect(querier1.query()).to.equal(0); + + querier1.handler(1); + expect(querier1.query()).to.equal(0); + + querier1.handler(0); + expect(querier1.query()).to.equal(0); + + querier1.handler(-1); + expect(querier1.query()).to.equal(0); + + const querier2 = new Querier(); + + querier2.handler(6); + expect(querier2.query()).to.equal(5); + + querier2.handler(2); + expect(querier2.query()).to.equal(1); + + querier2.handler(1); + expect(querier2.query()).to.equal(0); + + const querier3 = new Querier(); + + querier3.handler(6); + expect(querier3.query()).to.equal(5); + + querier3.handler(3); + expect(querier3.query()).to.equal(2); + + querier3.handler(4); + expect(querier3.query()).to.equal(2); + + const querier4 = new Querier(); + + querier4.handler(3); + expect(querier4.query()).to.equal(2); + + querier4.handler(4); + expect(querier4.query()).to.equal(2); + + querier4.handler(5); + expect(querier4.query()).to.equal(2); + + querier4.handler(6); + expect(querier4.query()).to.equal(2); + + querier4.handler(4); + expect(querier4.query()).to.equal(2); + + querier4.handler(3); + expect(querier4.query()).to.equal(2); + + const querier5 = new Querier(); + + querier5.handler(2); + expect(querier5.query()).to.equal(1); + + querier5.handler(6); + expect(querier5.query()).to.equal(1); + + querier5.handler(2); + expect(querier5.query()).to.equal(1); + + querier5.handler(1); + expect(querier5.query()).to.equal(0); + }); + + it("Querier.query(ignoreSingle = true)", function () { + const querier1 = new Querier(); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(1); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(2); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(3); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(4); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(5); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true)).to.equal(5); + + querier1.handler(5); + expect(querier1.query(true)).to.equal(4); + + querier1.handler(4); + expect(querier1.query(true)).to.equal(3); + + querier1.handler(3); + expect(querier1.query(true)).to.equal(2); + + querier1.handler(2); + expect(querier1.query(true)).to.equal(1); + + querier1.handler(1); + expect(querier1.query(true)).to.equal(0); + + const querier2 = new Querier(); + + querier2.handler(6); + expect(querier2.query(true)).to.equal(6); + + querier2.handler(2); + expect(querier2.query(true)).to.equal(1); + + querier2.handler(1); + expect(querier2.query(true)).to.equal(0); + + const querier3 = new Querier(); + + querier3.handler(6); + expect(querier3.query(true)).to.equal(6); + + querier3.handler(3); + expect(querier3.query(true)).to.equal(2); + + querier3.handler(4); + expect(querier3.query(true)).to.equal(2); + + const querier4 = new Querier(); + + querier4.handler(3); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(4); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(5); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(6); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(4); + expect(querier4.query(true)).to.equal(3); + + querier4.handler(3); + expect(querier4.query(true)).to.equal(2); + }); + + it("Querier.query(ignoreSingle = true) with allowZeroLevel", function () { + const querier1 = new Querier(true); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(1); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(2); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(3); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(4); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(5); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true)).to.equal(5); + + querier1.handler(5); + expect(querier1.query(true)).to.equal(4); + + querier1.handler(4); + expect(querier1.query(true)).to.equal(3); + + querier1.handler(3); + expect(querier1.query(true)).to.equal(2); + + querier1.handler(2); + expect(querier1.query(true)).to.equal(1); + + querier1.handler(1); + expect(querier1.query(true)).to.equal(0); + + const querier2 = new Querier(true); + + querier2.handler(6); + expect(querier2.query(true)).to.equal(6); + + querier2.handler(2); + expect(querier2.query(true)).to.equal(1); + + querier2.handler(1); + expect(querier2.query(true)).to.equal(0); + + const querier3 = new Querier(true); + + querier3.handler(6); + expect(querier3.query(true)).to.equal(6); + + querier3.handler(3); + expect(querier3.query(true)).to.equal(2); + + querier3.handler(4); + expect(querier3.query(true)).to.equal(2); + + const querier4 = new Querier(true); + + querier4.handler(3); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(4); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(5); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(6); + expect(querier4.query(true)).to.equal(6); + + querier4.handler(4); + expect(querier4.query(true)).to.equal(3); + + querier4.handler(3); + expect(querier4.query(true)).to.equal(2); + }); + + it("Querier.query(ignoreSingle = true) with ignoreMaximum parameter", function () { + const querier1 = new Querier(); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(1); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(2); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(3); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(4); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(5); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true, 6)).to.equal(6); + + querier1.handler(6); + expect(querier1.query(true, 6)).to.equal(5); + + querier1.handler(5); + expect(querier1.query(true, 6)).to.equal(4); + + querier1.handler(4); + expect(querier1.query(true, 6)).to.equal(3); + + querier1.handler(3); + expect(querier1.query(true, 6)).to.equal(2); + + querier1.handler(2); + expect(querier1.query(true, 6)).to.equal(1); + + querier1.handler(1); + expect(querier1.query(true, 6)).to.equal(0); + + const querier2 = new Querier(); + + querier2.handler(6); + expect(querier2.query(true, 2)).to.equal(2); + + querier2.handler(2); + expect(querier2.query(true, 2)).to.equal(1); + + querier2.handler(1); + expect(querier2.query(true, 2)).to.equal(0); + + const querier3 = new Querier(); + + querier3.handler(6); + expect(querier3.query(true, 1)).to.equal(1); + + querier3.handler(3); + expect(querier3.query(true, 1)).to.equal(1); + + querier3.handler(4); + expect(querier3.query(true, 1)).to.equal(1); + + const querier4 = new Querier(); + + querier4.handler(3); + expect(querier4.query(true, 1)).to.equal(1); + + querier4.handler(4); + expect(querier4.query(true, 1)).to.equal(1); + + querier4.handler(5); + expect(querier4.query(true, 1)).to.equal(1); + + querier4.handler(6); + expect(querier4.query(true, 1)).to.equal(1); + + querier4.handler(4); + expect(querier4.query(true, 1)).to.equal(1); + + querier4.handler(3); + expect(querier4.query(true, 1)).to.equal(1); }); - expect(counter.decorator(1)).to.equal("a"); - expect(counter.decorator(2)).to.equal("a.a"); - expect(counter.decorator(2)).to.equal("a.b"); - expect(counter.decorator(2)).to.equal("a.c"); - expect(counter.decorator(2)).to.equal("a.d"); - expect(counter.decorator(2)).to.equal("a.e"); - expect(counter.decorator(2)).to.equal("a.f"); - expect(counter.decorator(2)).to.equal("a.g"); - expect(counter.decorator(2)).to.equal("a.h"); - expect(counter.decorator(2)).to.equal("a.i"); - expect(counter.decorator(2)).to.equal("a.j"); - expect(counter.decorator(2)).to.equal("a.k"); - expect(counter.decorator(2)).to.equal("a.l"); - expect(counter.decorator(2)).to.equal("a.m"); - expect(counter.decorator(2)).to.equal("a.n"); - expect(counter.decorator(2)).to.equal("a.o"); - expect(counter.decorator(2)).to.equal("a.p"); - expect(counter.decorator(2)).to.equal("a.q"); - expect(counter.decorator(2)).to.equal("a.r"); - expect(counter.decorator(2)).to.equal("a.s"); - expect(counter.decorator(2)).to.equal("a.t"); - expect(counter.decorator(2)).to.equal("a.u"); - expect(counter.decorator(2)).to.equal("a.v"); - expect(counter.decorator(2)).to.equal("a.w"); - expect(counter.decorator(2)).to.equal("a.x"); - expect(counter.decorator(2)).to.equal("a.y"); - expect(counter.decorator(2)).to.equal("a.z"); - expect(counter.decorator(2)).to.equal("a.aa"); - expect(counter.decorator(2)).to.equal("a.ab"); - expect(counter.decorator(1)).to.equal("b"); - expect(counter.decorator(7)).to.be.empty; }); - it("Counter.decorator with upperAlpha styleType", function () { - const counter = new Counter({ - ordered: true, + describe("UnorderedCounter", function () { + const list: HeadingTuple = ["H1", "H2", "H3", "H4", "H5", "H6"]; + + it("UnorderedCounter.decorator", function () { + const counter = new UnorderedCounter(list); + expect(counter.decorator(-1)).to.be.empty; + expect(counter.decorator(0)).to.empty; + expect(counter.decorator(1)).to.equal("H1"); + expect(counter.decorator(2)).to.equal("H2"); + expect(counter.decorator(3)).to.equal("H3"); + expect(counter.decorator(4)).to.equal("H4"); + expect(counter.decorator(5)).to.equal("H5"); + expect(counter.decorator(6)).to.equal("H6"); + expect(counter.decorator(7)).to.empty; + }); + + it("UnorderedCounter.decorator with maxRecLevel", function () { + const counter = new UnorderedCounter(list, 4); + expect(counter.decorator(-1)).to.be.empty; + expect(counter.decorator(0)).to.empty; + expect(counter.decorator(1)).to.equal("H1"); + expect(counter.decorator(2)).to.equal("H2"); + expect(counter.decorator(3)).to.equal("H3"); + expect(counter.decorator(4)).to.equal("H4"); + expect(counter.decorator(5)).to.be.empty; + expect(counter.decorator(6)).to.be.empty; + expect(counter.decorator(7)).to.empty; + }); + }); + + describe("OrderedCounter", function () { + it("OrderedCounter.decorator with decimal styleType", function () { + const counter = new OrderedCounter({ + styleType: "decimal", + }); + expect(counter.decorator(-1)).to.be.empty; + expect(counter.decorator(0)).to.be.empty; + expect(counter.decorator(1)).to.equal("1"); + expect(counter.decorator(2)).to.equal("1.1"); + expect(counter.decorator(2)).to.equal("1.2"); + expect(counter.decorator(2)).to.equal("1.3"); + expect(counter.decorator(2)).to.equal("1.4"); + expect(counter.decorator(2)).to.equal("1.5"); + expect(counter.decorator(2)).to.equal("1.6"); + expect(counter.decorator(2)).to.equal("1.7"); + expect(counter.decorator(2)).to.equal("1.8"); + expect(counter.decorator(2)).to.equal("1.9"); + expect(counter.decorator(2)).to.equal("1.10"); + expect(counter.decorator(2)).to.equal("1.11"); + expect(counter.decorator(1)).to.equal("2"); + expect(counter.decorator(7)).to.be.empty; + }); + + it("OrderedCounter.decorator with lowerAlpha styleType", function () { + const counter = new OrderedCounter({ + styleType: "lowerAlpha", + }); + expect(counter.decorator(1)).to.equal("a"); + expect(counter.decorator(2)).to.equal("a.a"); + expect(counter.decorator(2)).to.equal("a.b"); + expect(counter.decorator(2)).to.equal("a.c"); + expect(counter.decorator(2)).to.equal("a.d"); + expect(counter.decorator(2)).to.equal("a.e"); + expect(counter.decorator(2)).to.equal("a.f"); + expect(counter.decorator(2)).to.equal("a.g"); + expect(counter.decorator(2)).to.equal("a.h"); + expect(counter.decorator(2)).to.equal("a.i"); + expect(counter.decorator(2)).to.equal("a.j"); + expect(counter.decorator(2)).to.equal("a.k"); + expect(counter.decorator(2)).to.equal("a.l"); + expect(counter.decorator(2)).to.equal("a.m"); + expect(counter.decorator(2)).to.equal("a.n"); + expect(counter.decorator(2)).to.equal("a.o"); + expect(counter.decorator(2)).to.equal("a.p"); + expect(counter.decorator(2)).to.equal("a.q"); + expect(counter.decorator(2)).to.equal("a.r"); + expect(counter.decorator(2)).to.equal("a.s"); + expect(counter.decorator(2)).to.equal("a.t"); + expect(counter.decorator(2)).to.equal("a.u"); + expect(counter.decorator(2)).to.equal("a.v"); + expect(counter.decorator(2)).to.equal("a.w"); + expect(counter.decorator(2)).to.equal("a.x"); + expect(counter.decorator(2)).to.equal("a.y"); + expect(counter.decorator(2)).to.equal("a.z"); + expect(counter.decorator(2)).to.equal("a.aa"); + expect(counter.decorator(2)).to.equal("a.ab"); + expect(counter.decorator(1)).to.equal("b"); + expect(counter.decorator(7)).to.be.empty; + }); + + it("OrderedCounter.decorator with upperAlpha styleType", function () { + const counter = new OrderedCounter({ + styleType: "upperAlpha", + }); + expect(counter.decorator(1)).to.equal("A"); + expect(counter.decorator(2)).to.equal("A.A"); + expect(counter.decorator(2)).to.equal("A.B"); + expect(counter.decorator(2)).to.equal("A.C"); + expect(counter.decorator(2)).to.equal("A.D"); + expect(counter.decorator(2)).to.equal("A.E"); + expect(counter.decorator(2)).to.equal("A.F"); + expect(counter.decorator(2)).to.equal("A.G"); + expect(counter.decorator(2)).to.equal("A.H"); + expect(counter.decorator(2)).to.equal("A.I"); + expect(counter.decorator(2)).to.equal("A.J"); + expect(counter.decorator(2)).to.equal("A.K"); + expect(counter.decorator(2)).to.equal("A.L"); + expect(counter.decorator(2)).to.equal("A.M"); + expect(counter.decorator(2)).to.equal("A.N"); + expect(counter.decorator(2)).to.equal("A.O"); + expect(counter.decorator(2)).to.equal("A.P"); + expect(counter.decorator(2)).to.equal("A.Q"); + expect(counter.decorator(2)).to.equal("A.R"); + expect(counter.decorator(2)).to.equal("A.S"); + expect(counter.decorator(2)).to.equal("A.T"); + expect(counter.decorator(2)).to.equal("A.U"); + expect(counter.decorator(2)).to.equal("A.V"); + expect(counter.decorator(2)).to.equal("A.W"); + expect(counter.decorator(2)).to.equal("A.X"); + expect(counter.decorator(2)).to.equal("A.Y"); + expect(counter.decorator(2)).to.equal("A.Z"); + expect(counter.decorator(2)).to.equal("A.AA"); + expect(counter.decorator(2)).to.equal("A.AB"); + expect(counter.decorator(1)).to.equal("B"); + expect(counter.decorator(7)).to.be.empty; + }); + + it("OrderedCounter.decorator with cjkDecimal styleType", function () { + const counter = new OrderedCounter({ + styleType: "cjkDecimal", + }); + expect(counter.decorator(1)).to.equal("一"); + expect(counter.decorator(2)).to.equal("一.一"); + expect(counter.decorator(2)).to.equal("一.二"); + expect(counter.decorator(2)).to.equal("一.三"); + expect(counter.decorator(2)).to.equal("一.四"); + expect(counter.decorator(2)).to.equal("一.五"); + expect(counter.decorator(2)).to.equal("一.六"); + expect(counter.decorator(2)).to.equal("一.七"); + expect(counter.decorator(2)).to.equal("一.八"); + expect(counter.decorator(2)).to.equal("一.九"); + expect(counter.decorator(2)).to.equal("一.一〇"); + expect(counter.decorator(2)).to.equal("一.一一"); + expect(counter.decorator(2)).to.equal("一.一二"); + expect(counter.decorator(1)).to.equal("二"); + }); + + it("OrderedCounter.decorator with customIdent styleType", function () { + const counter1 = new OrderedCounter({ + styleType: "customIdent", + customIdents: [], + }); + expect(counter1.decorator(1)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("1.1"); + expect(counter1.decorator(3)).to.equal("1.1.1"); + expect(counter1.decorator(4)).to.equal("1.1.1.1"); + expect(counter1.decorator(5)).to.equal("1.1.1.1.1"); + expect(counter1.decorator(6)).to.equal("1.1.1.1.1.1"); + expect(counter1.decorator(2)).to.equal("1.2"); + + const counter2 = new OrderedCounter({ + styleType: "customIdent", + customIdents: ["Ⓐ", "Ⓑ", "Ⓒ"], + }); + expect(counter2.decorator(1)).to.equal("Ⓐ"); + expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓐ"); + expect(counter2.decorator(3)).to.equal("Ⓐ.Ⓐ.Ⓐ"); + expect(counter2.decorator(4)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ"); + expect(counter2.decorator(5)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ"); + expect(counter2.decorator(6)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ"); + expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓑ"); + expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓒ"); + expect(counter2.decorator(2)).to.equal("Ⓐ.4"); + expect(counter2.decorator(2)).to.equal("Ⓐ.5"); + expect(counter2.decorator(2)).to.equal("Ⓐ.6"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓐ"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓑ"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓒ"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.4"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.5"); + expect(counter2.decorator(3)).to.equal("Ⓐ.6.6"); + }); + + it("OrderedCounter.decorator with string styleType", function () { + const counter1 = new OrderedCounter({ + styleType: "string", + }); + expect(counter1.decorator(1)).to.equal("#"); + expect(counter1.decorator(2)).to.equal("#.#"); + expect(counter1.decorator(3)).to.equal("#.#.#"); + + const counter2 = new OrderedCounter({ + styleType: "string", + specifiedString: "*", + }); + expect(counter2.decorator(1)).to.equal("*"); + expect(counter2.decorator(2)).to.equal("*.*"); + expect(counter2.decorator(3)).to.equal("*.*.*"); + + const counter3 = new OrderedCounter({ + styleType: "string", + specifiedString: "", + }); + expect(counter3.decorator(1)).to.equal("#"); + expect(counter3.decorator(2)).to.equal("#.#"); + expect(counter3.decorator(3)).to.equal("#.#.#"); + }); + + it("OrderedCounter.decorator with custom delimiter", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + }); + expect(counter1.decorator(1)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("1.1"); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + delimiter: ",", + }); + expect(counter2.decorator(1)).to.equal("1"); + expect(counter2.decorator(2)).to.equal("1,1"); + + const counter3 = new OrderedCounter({ + styleType: "decimal", + delimiter: "", + }); + expect(counter3.decorator(1)).to.equal("1"); + expect(counter3.decorator(2)).to.equal("11"); + + const counter4 = new OrderedCounter({ + styleType: "string", + specifiedString: "#", + delimiter: "", + }); + expect(counter4.decorator(1)).to.equal("#"); + expect(counter4.decorator(2)).to.equal("##"); + }); + + it("OrderedCounter.decorator with trailing delimiter", function () { + const counter = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + trailingDelimiter: true, + }); + + expect(counter.decorator(1)).to.equal("1."); + expect(counter.decorator(2)).to.equal("1.1."); + }); + + it("OrderedCounter.decorator with custom trailing delimiter", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customTrailingDelimiter: "", + trailingDelimiter: true, + }); + + expect(counter1.decorator(1)).to.equal("1."); + expect(counter1.decorator(2)).to.equal("1.1."); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customTrailingDelimiter: "|", + trailingDelimiter: true, + }); + + expect(counter2.decorator(1)).to.equal("1|"); + expect(counter2.decorator(2)).to.equal("1.1|"); + }); + + it("OrderedCounter.decorator with custom leading delimiter", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customLeadingDelimiter: "", + leadingDelimiter: true, + }); + + expect(counter1.decorator(1)).to.equal(".1"); + expect(counter1.decorator(2)).to.equal(".1.1"); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customLeadingDelimiter: "|", + leadingDelimiter: true, + }); + + expect(counter2.decorator(1)).to.equal("|1"); + expect(counter2.decorator(2)).to.equal("|1.1"); + }); + + it("OrderedCounter.decorator with custom leading delimiter and trailing delimiter", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customTrailingDelimiter: "", + trailingDelimiter: true, + customLeadingDelimiter: "", + leadingDelimiter: true, + }); + + expect(counter1.decorator(1)).to.equal(".1."); + expect(counter1.decorator(2)).to.equal(".1.1."); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + delimiter: ".", + customTrailingDelimiter: ")", + trailingDelimiter: true, + customLeadingDelimiter: "(", + leadingDelimiter: true, + }); + + expect(counter2.decorator(1)).to.equal("(1)"); + expect(counter2.decorator(2)).to.equal("(1.1)"); + }); + + it("OrderedCounter.decorator with ignoreTopLevel", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + ignoreTopLevel: 1, + }); + expect(counter1.decorator(1)).to.be.empty; + expect(counter1.decorator(2)).to.equal("1"); + expect(counter1.decorator(3)).to.equal("1.1"); + expect(counter1.decorator(4)).to.equal("1.1.1"); + expect(counter1.decorator(5)).to.equal("1.1.1.1"); + expect(counter1.decorator(6)).to.equal("1.1.1.1.1"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("2"); + expect(counter1.decorator(3)).to.equal("2.1"); + expect(counter1.decorator(4)).to.equal("2.1.1"); + expect(counter1.decorator(5)).to.equal("2.1.1.1"); + expect(counter1.decorator(6)).to.equal("2.1.1.1.1"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("3"); + expect(counter1.decorator(6)).to.equal("3.1.1.1.1"); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + ignoreTopLevel: 2, + }); + expect(counter2.decorator(1)).to.be.empty; + expect(counter2.decorator(2)).to.be.empty; + expect(counter2.decorator(3)).to.equal("1"); + expect(counter2.decorator(4)).to.equal("1.1"); + expect(counter2.decorator(5)).to.equal("1.1.1"); + expect(counter2.decorator(6)).to.equal("1.1.1.1"); + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(3)).to.equal("2"); + expect(counter2.decorator(6)).to.equal("2.1.1.1"); + + const counter3 = new OrderedCounter({ + styleType: "decimal", + ignoreTopLevel: 2, + }); + expect(counter3.decorator(3)).to.equal("1"); + expect(counter3.decorator(4)).to.equal("1.1"); + expect(counter3.decorator(5)).to.equal("1.1.1"); + expect(counter3.decorator(6)).to.equal("1.1.1.1"); + expect(counter3.decorator(3)).to.equal("2"); + expect(counter3.decorator(6)).to.equal("2.1.1.1"); + + const counter4 = new OrderedCounter({ + styleType: "decimal", + trailingDelimiter: true, + ignoreTopLevel: 2, + }); + expect(counter4.decorator(1)).to.be.empty; + expect(counter4.decorator(2)).to.be.empty; + expect(counter4.decorator(3)).to.equal("1."); + expect(counter4.decorator(4)).to.equal("1.1."); + expect(counter4.decorator(5)).to.equal("1.1.1."); + expect(counter4.decorator(6)).to.equal("1.1.1.1."); + expect(counter4.decorator(3)).to.equal("2."); + expect(counter4.decorator(4)).to.equal("2.1."); + expect(counter4.decorator(5)).to.equal("2.1.1."); + expect(counter4.decorator(6)).to.equal("2.1.1.1."); + expect(counter4.decorator(3)).to.equal("3."); + expect(counter4.decorator(6)).to.equal("3.1.1.1."); + }); + + it("OrderedCounter.decorator with allowZeroLevel", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + }); + + expect(counter1.decorator(3)).to.equal("0.0.1"); + expect(counter1.decorator(4)).to.equal("0.0.1.1"); + expect(counter1.decorator(5)).to.equal("0.0.1.1.1"); + expect(counter1.decorator(6)).to.equal("0.0.1.1.1.1"); + + expect(counter1.decorator(3)).to.equal("0.0.2"); + expect(counter1.decorator(4)).to.equal("0.0.2.1"); + expect(counter1.decorator(5)).to.equal("0.0.2.1.1"); + expect(counter1.decorator(6)).to.equal("0.0.2.1.1.1"); + + expect(counter1.decorator(2)).to.equal("0.1"); + expect(counter1.decorator(5)).to.equal("0.1.0.0.1"); + expect(counter1.decorator(6)).to.equal("0.1.0.0.1.1"); + + const counter2 = new OrderedCounter({ + styleType: "lowerAlpha", + allowZeroLevel: true, + }); + + expect(counter2.decorator(3)).to.equal("0.0.a"); + expect(counter2.decorator(4)).to.equal("0.0.a.a"); + + const counter3 = new OrderedCounter({ + styleType: "cjkDecimal", + allowZeroLevel: true, + }); + + expect(counter3.decorator(3)).to.equal("〇.〇.一"); + expect(counter3.decorator(4)).to.equal("〇.〇.一.一"); + }); + + it("OrderedCounter.decorator with allowZeroLevel and ignoreTopLevel", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + ignoreTopLevel: 1, + }); + expect(counter1.decorator(1)).to.be.empty; + expect(counter1.decorator(2)).to.equal("1"); + expect(counter1.decorator(3)).to.equal("1.1"); + expect(counter1.decorator(4)).to.equal("1.1.1"); + expect(counter1.decorator(5)).to.equal("1.1.1.1"); + expect(counter1.decorator(6)).to.equal("1.1.1.1.1"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("2"); + expect(counter1.decorator(3)).to.equal("2.1"); + expect(counter1.decorator(4)).to.equal("2.1.1"); + expect(counter1.decorator(5)).to.equal("2.1.1.1"); + expect(counter1.decorator(6)).to.equal("2.1.1.1.1"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("3"); + expect(counter1.decorator(6)).to.equal("3.0.0.0.1"); + + const counter2 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + ignoreTopLevel: 2, + }); + expect(counter2.decorator(1)).to.be.empty; + expect(counter2.decorator(2)).to.be.empty; + expect(counter2.decorator(3)).to.equal("1"); + expect(counter2.decorator(4)).to.equal("1.1"); + expect(counter2.decorator(5)).to.equal("1.1.1"); + expect(counter2.decorator(6)).to.equal("1.1.1.1"); + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(3)).to.equal("2"); + expect(counter2.decorator(6)).to.equal("2.0.0.1"); + + const counter3 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + ignoreTopLevel: 2, + }); + expect(counter3.decorator(3)).to.equal("1"); + expect(counter3.decorator(4)).to.equal("1.1"); + expect(counter3.decorator(5)).to.equal("1.1.1"); + expect(counter3.decorator(6)).to.equal("1.1.1.1"); + expect(counter3.decorator(3)).to.equal("2"); + expect(counter3.decorator(6)).to.equal("2.0.0.1"); + + const counter4 = new OrderedCounter({ + styleType: "decimal", + trailingDelimiter: true, + allowZeroLevel: true, + ignoreTopLevel: 2, + }); + expect(counter4.decorator(1)).to.be.empty; + expect(counter4.decorator(2)).to.be.empty; + expect(counter4.decorator(3)).to.equal("1."); + expect(counter4.decorator(4)).to.equal("1.1."); + expect(counter4.decorator(5)).to.equal("1.1.1."); + expect(counter4.decorator(6)).to.equal("1.1.1.1."); + expect(counter4.decorator(3)).to.equal("2."); + expect(counter4.decorator(4)).to.equal("2.1."); + expect(counter4.decorator(5)).to.equal("2.1.1."); + expect(counter4.decorator(6)).to.equal("2.1.1.1."); + expect(counter4.decorator(3)).to.equal("3."); + expect(counter4.decorator(6)).to.equal("3.0.0.1."); + }); + + it("OrderedCounter.decorator with maxRecLevel", function () { + const counter1 = new OrderedCounter({ + styleType: "decimal", + maxRecLevel: 4, + }); + expect(counter1.decorator(1)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("1.1"); + expect(counter1.decorator(3)).to.equal("1.1.1"); + expect(counter1.decorator(4)).to.equal("1.1.1.1"); + expect(counter1.decorator(5)).to.be.empty; + expect(counter1.decorator(6)).to.be.empty; + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("1.2"); + expect(counter1.decorator(3)).to.equal("1.2.1"); + expect(counter1.decorator(4)).to.equal("1.2.1.1"); + expect(counter1.decorator(5)).to.be.empty; + expect(counter1.decorator(6)).to.be.empty; + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("1.3"); + expect(counter1.decorator(6)).to.be.empty; + + const counter2 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + ignoreTopLevel: 2, + maxRecLevel: 4, + }); + expect(counter2.decorator(1)).to.be.empty; + expect(counter2.decorator(2)).to.be.empty; + expect(counter2.decorator(3)).to.equal("1"); + expect(counter2.decorator(4)).to.equal("1.1"); + expect(counter2.decorator(5)).to.be.empty; + expect(counter2.decorator(6)).to.be.empty; + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(3)).to.equal("2"); + expect(counter2.decorator(6)).to.be.empty; + + const counter3 = new OrderedCounter({ + styleType: "decimal", + allowZeroLevel: true, + ignoreTopLevel: 2, + maxRecLevel: 3, + }); + expect(counter3.decorator(3)).to.equal("1"); + expect(counter3.decorator(4)).to.be.empty; + expect(counter3.decorator(5)).to.be.empty; + expect(counter3.decorator(6)).to.be.empty; + expect(counter3.decorator(3)).to.equal("2"); + expect(counter3.decorator(6)).to.be.empty; + + const counter4 = new OrderedCounter({ + styleType: "decimal", + trailingDelimiter: true, + allowZeroLevel: true, + ignoreTopLevel: 2, + maxRecLevel: 4, + }); + expect(counter4.decorator(1)).to.be.empty; + expect(counter4.decorator(2)).to.be.empty; + expect(counter4.decorator(3)).to.equal("1."); + expect(counter4.decorator(4)).to.equal("1.1."); + expect(counter4.decorator(5)).to.be.empty; + expect(counter4.decorator(6)).to.be.empty; + expect(counter4.decorator(3)).to.equal("2."); + expect(counter4.decorator(4)).to.equal("2.1."); + expect(counter4.decorator(5)).to.be.empty; + expect(counter4.decorator(6)).to.be.empty; + expect(counter4.decorator(3)).to.equal("3."); + expect(counter4.decorator(6)).to.be.empty; + }); + }); + + describe("IndependentCounter", function () { + const h1: Partial = { styleType: "upperAlpha", - }); - expect(counter.decorator(1)).to.equal("A"); - expect(counter.decorator(2)).to.equal("A.A"); - expect(counter.decorator(2)).to.equal("A.B"); - expect(counter.decorator(2)).to.equal("A.C"); - expect(counter.decorator(2)).to.equal("A.D"); - expect(counter.decorator(2)).to.equal("A.E"); - expect(counter.decorator(2)).to.equal("A.F"); - expect(counter.decorator(2)).to.equal("A.G"); - expect(counter.decorator(2)).to.equal("A.H"); - expect(counter.decorator(2)).to.equal("A.I"); - expect(counter.decorator(2)).to.equal("A.J"); - expect(counter.decorator(2)).to.equal("A.K"); - expect(counter.decorator(2)).to.equal("A.L"); - expect(counter.decorator(2)).to.equal("A.M"); - expect(counter.decorator(2)).to.equal("A.N"); - expect(counter.decorator(2)).to.equal("A.O"); - expect(counter.decorator(2)).to.equal("A.P"); - expect(counter.decorator(2)).to.equal("A.Q"); - expect(counter.decorator(2)).to.equal("A.R"); - expect(counter.decorator(2)).to.equal("A.S"); - expect(counter.decorator(2)).to.equal("A.T"); - expect(counter.decorator(2)).to.equal("A.U"); - expect(counter.decorator(2)).to.equal("A.V"); - expect(counter.decorator(2)).to.equal("A.W"); - expect(counter.decorator(2)).to.equal("A.X"); - expect(counter.decorator(2)).to.equal("A.Y"); - expect(counter.decorator(2)).to.equal("A.Z"); - expect(counter.decorator(2)).to.equal("A.AA"); - expect(counter.decorator(2)).to.equal("A.AB"); - expect(counter.decorator(1)).to.equal("B"); - expect(counter.decorator(7)).to.be.empty; - }); - - it("Counter.decorator with cjkDecimal styleType", function () { - const counter = new Counter({ - ordered: true, - styleType: "cjkDecimal", - }); - expect(counter.decorator(1)).to.equal("一"); - expect(counter.decorator(2)).to.equal("一.一"); - expect(counter.decorator(2)).to.equal("一.二"); - expect(counter.decorator(2)).to.equal("一.三"); - expect(counter.decorator(2)).to.equal("一.四"); - expect(counter.decorator(2)).to.equal("一.五"); - expect(counter.decorator(2)).to.equal("一.六"); - expect(counter.decorator(2)).to.equal("一.七"); - expect(counter.decorator(2)).to.equal("一.八"); - expect(counter.decorator(2)).to.equal("一.九"); - expect(counter.decorator(2)).to.equal("一.一〇"); - expect(counter.decorator(2)).to.equal("一.一一"); - expect(counter.decorator(2)).to.equal("一.一二"); - expect(counter.decorator(1)).to.equal("二"); - }); - - it("Counter.decorator with customIdent styleType", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "customIdent", - customIdents: [], - }); - expect(counter1.decorator(1)).to.equal("1"); - expect(counter1.decorator(2)).to.equal("1.1"); - expect(counter1.decorator(3)).to.equal("1.1.1"); - expect(counter1.decorator(4)).to.equal("1.1.1.1"); - expect(counter1.decorator(5)).to.equal("1.1.1.1.1"); - expect(counter1.decorator(6)).to.equal("1.1.1.1.1.1"); - expect(counter1.decorator(2)).to.equal("1.2"); - - const counter2 = new Counter({ - ordered: true, - styleType: "customIdent", - customIdents: ["Ⓐ", "Ⓑ", "Ⓒ"], - }); - expect(counter2.decorator(1)).to.equal("Ⓐ"); - expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓐ"); - expect(counter2.decorator(3)).to.equal("Ⓐ.Ⓐ.Ⓐ"); - expect(counter2.decorator(4)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ"); - expect(counter2.decorator(5)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ"); - expect(counter2.decorator(6)).to.equal("Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ.Ⓐ"); - expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓑ"); - expect(counter2.decorator(2)).to.equal("Ⓐ.Ⓒ"); - expect(counter2.decorator(2)).to.equal("Ⓐ.4"); - expect(counter2.decorator(2)).to.equal("Ⓐ.5"); - expect(counter2.decorator(2)).to.equal("Ⓐ.6"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓐ"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓑ"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.Ⓒ"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.4"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.5"); - expect(counter2.decorator(3)).to.equal("Ⓐ.6.6"); - }); - - it("Counter.decorator with string styleType", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "string", - }); - expect(counter1.decorator(1)).to.equal("#"); - expect(counter1.decorator(2)).to.equal("#.#"); - expect(counter1.decorator(3)).to.equal("#.#.#"); - - const counter2 = new Counter({ - ordered: true, - styleType: "string", - specifiedString: "*", - }); - expect(counter2.decorator(1)).to.equal("*"); - expect(counter2.decorator(2)).to.equal("*.*"); - expect(counter2.decorator(3)).to.equal("*.*.*"); - - const counter3 = new Counter({ - ordered: true, - styleType: "string", - specifiedString: "", - }); - expect(counter3.decorator(1)).to.equal("#"); - expect(counter3.decorator(2)).to.equal("#.#"); - expect(counter3.decorator(3)).to.equal("#.#.#"); - }); - - it("Counter.decorator with custom delimiter", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - }); - expect(counter1.decorator(1)).to.equal("1"); - expect(counter1.decorator(2)).to.equal("1.1"); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ",", - }); - expect(counter2.decorator(1)).to.equal("1"); - expect(counter2.decorator(2)).to.equal("1,1"); - - const counter3 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: "", - }); - expect(counter3.decorator(1)).to.equal("1"); - expect(counter3.decorator(2)).to.equal("11"); - - const counter4 = new Counter({ - ordered: true, - styleType: "string", - specifiedString: "#", - delimiter: "", - }); - expect(counter4.decorator(1)).to.equal("#"); - expect(counter4.decorator(2)).to.equal("##"); - }); - - it("Counter.decorator with trailing delimiter", function () { - const counter = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - trailingDelimiter: true, - }); - - expect(counter.decorator(1)).to.equal("1."); - expect(counter.decorator(2)).to.equal("1.1."); - }); - - it("Counter.decorator with custom trailing delimiter", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customTrailingDelimiter: "", - trailingDelimiter: true, - }); - - expect(counter1.decorator(1)).to.equal("1."); - expect(counter1.decorator(2)).to.equal("1.1."); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customTrailingDelimiter: "|", - trailingDelimiter: true, - }); - - expect(counter2.decorator(1)).to.equal("1|"); - expect(counter2.decorator(2)).to.equal("1.1|"); - }); - - it("Counter.decorator with custom leading delimiter", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customLeadingDelimiter: "", - leadingDelimiter: true, - }); - - expect(counter1.decorator(1)).to.equal(".1"); - expect(counter1.decorator(2)).to.equal(".1.1"); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customLeadingDelimiter: "|", - leadingDelimiter: true, - }); - - expect(counter2.decorator(1)).to.equal("|1"); - expect(counter2.decorator(2)).to.equal("|1.1"); - }); - - it("Counter.decorator with custom leading delimiter and trailing delimiter", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customTrailingDelimiter: "", - trailingDelimiter: true, - customLeadingDelimiter: "", - leadingDelimiter: true, - }); - - expect(counter1.decorator(1)).to.equal(".1."); - expect(counter1.decorator(2)).to.equal(".1.1."); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - delimiter: ".", - customTrailingDelimiter: ")", - trailingDelimiter: true, - customLeadingDelimiter: "(", - leadingDelimiter: true, - }); - - expect(counter2.decorator(1)).to.equal("(1)"); - expect(counter2.decorator(2)).to.equal("(1.1)"); - }); - - it("Counter.decorator with ignoreTopLevel", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - ignoreTopLevel: 1, - }); - expect(counter1.decorator(1)).to.be.empty; - expect(counter1.decorator(2)).to.equal("1"); - expect(counter1.decorator(3)).to.equal("1.1"); - expect(counter1.decorator(4)).to.equal("1.1.1"); - expect(counter1.decorator(5)).to.equal("1.1.1.1"); - expect(counter1.decorator(6)).to.equal("1.1.1.1.1"); - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("2"); - expect(counter1.decorator(3)).to.equal("2.1"); - expect(counter1.decorator(4)).to.equal("2.1.1"); - expect(counter1.decorator(5)).to.equal("2.1.1.1"); - expect(counter1.decorator(6)).to.equal("2.1.1.1.1"); - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("3"); - expect(counter1.decorator(6)).to.equal("3.1.1.1.1"); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - ignoreTopLevel: 2, - }); - expect(counter2.decorator(1)).to.be.empty; - expect(counter2.decorator(2)).to.be.empty; - expect(counter2.decorator(3)).to.equal("1"); - expect(counter2.decorator(4)).to.equal("1.1"); - expect(counter2.decorator(5)).to.equal("1.1.1"); - expect(counter2.decorator(6)).to.equal("1.1.1.1"); - expect(counter2.decorator(7)).to.be.empty; - expect(counter2.decorator(3)).to.equal("2"); - expect(counter2.decorator(6)).to.equal("2.1.1.1"); - - const counter3 = new Counter({ - ordered: true, - styleType: "decimal", - ignoreTopLevel: 2, - }); - expect(counter3.decorator(3)).to.equal("1"); - expect(counter3.decorator(4)).to.equal("1.1"); - expect(counter3.decorator(5)).to.equal("1.1.1"); - expect(counter3.decorator(6)).to.equal("1.1.1.1"); - expect(counter3.decorator(3)).to.equal("2"); - expect(counter3.decorator(6)).to.equal("2.1.1.1"); - - const counter4 = new Counter({ - ordered: true, - styleType: "decimal", - trailingDelimiter: true, - ignoreTopLevel: 2, - }); - expect(counter4.decorator(1)).to.be.empty; - expect(counter4.decorator(2)).to.be.empty; - expect(counter4.decorator(3)).to.equal("1."); - expect(counter4.decorator(4)).to.equal("1.1."); - expect(counter4.decorator(5)).to.equal("1.1.1."); - expect(counter4.decorator(6)).to.equal("1.1.1.1."); - expect(counter4.decorator(3)).to.equal("2."); - expect(counter4.decorator(4)).to.equal("2.1."); - expect(counter4.decorator(5)).to.equal("2.1.1."); - expect(counter4.decorator(6)).to.equal("2.1.1.1."); - expect(counter4.decorator(3)).to.equal("3."); - expect(counter4.decorator(6)).to.equal("3.1.1.1."); - }); - - it("Counter.decorator with allowZeroLevel", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - }); - - expect(counter1.decorator(3)).to.equal("0.0.1"); - expect(counter1.decorator(4)).to.equal("0.0.1.1"); - expect(counter1.decorator(5)).to.equal("0.0.1.1.1"); - expect(counter1.decorator(6)).to.equal("0.0.1.1.1.1"); - - expect(counter1.decorator(3)).to.equal("0.0.2"); - expect(counter1.decorator(4)).to.equal("0.0.2.1"); - expect(counter1.decorator(5)).to.equal("0.0.2.1.1"); - expect(counter1.decorator(6)).to.equal("0.0.2.1.1.1"); - - expect(counter1.decorator(2)).to.equal("0.1"); - expect(counter1.decorator(5)).to.equal("0.1.0.0.1"); - expect(counter1.decorator(6)).to.equal("0.1.0.0.1.1"); - - const counter2 = new Counter({ - ordered: true, + }; + const h2: Partial = { styleType: "lowerAlpha", - allowZeroLevel: true, - }); - - expect(counter2.decorator(3)).to.equal("0.0.a"); - expect(counter2.decorator(4)).to.equal("0.0.a.a"); - - const counter3 = new Counter({ - ordered: true, + }; + const h3: Partial = { + styleType: "decimal", + trailingDelimiter: true, + }; + const h4: Partial = { + styleType: "decimalLeadingZero", + delimiter: ",", + trailingDelimiter: true, + }; + const h5: Partial = { styleType: "cjkDecimal", - allowZeroLevel: true, - }); - - expect(counter3.decorator(3)).to.equal("〇.〇.一"); - expect(counter3.decorator(4)).to.equal("〇.〇.一.一"); - }); - - it("Counter.decorator with allowZeroLevel and ignoreTopLevel", function () { - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - ignoreTopLevel: 1, - }); - expect(counter1.decorator(1)).to.be.empty; - expect(counter1.decorator(2)).to.equal("1"); - expect(counter1.decorator(3)).to.equal("1.1"); - expect(counter1.decorator(4)).to.equal("1.1.1"); - expect(counter1.decorator(5)).to.equal("1.1.1.1"); - expect(counter1.decorator(6)).to.equal("1.1.1.1.1"); - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("2"); - expect(counter1.decorator(3)).to.equal("2.1"); - expect(counter1.decorator(4)).to.equal("2.1.1"); - expect(counter1.decorator(5)).to.equal("2.1.1.1"); - expect(counter1.decorator(6)).to.equal("2.1.1.1.1"); - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("3"); - expect(counter1.decorator(6)).to.equal("3.0.0.0.1"); - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - ignoreTopLevel: 2, - }); - expect(counter2.decorator(1)).to.be.empty; - expect(counter2.decorator(2)).to.be.empty; - expect(counter2.decorator(3)).to.equal("1"); - expect(counter2.decorator(4)).to.equal("1.1"); - expect(counter2.decorator(5)).to.equal("1.1.1"); - expect(counter2.decorator(6)).to.equal("1.1.1.1"); - expect(counter2.decorator(7)).to.be.empty; - expect(counter2.decorator(3)).to.equal("2"); - expect(counter2.decorator(6)).to.equal("2.0.0.1"); - - const counter3 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - ignoreTopLevel: 2, - }); - expect(counter3.decorator(3)).to.equal("1"); - expect(counter3.decorator(4)).to.equal("1.1"); - expect(counter3.decorator(5)).to.equal("1.1.1"); - expect(counter3.decorator(6)).to.equal("1.1.1.1"); - expect(counter3.decorator(3)).to.equal("2"); - expect(counter3.decorator(6)).to.equal("2.0.0.1"); - - const counter4 = new Counter({ - ordered: true, - styleType: "decimal", + delimiter: "、", trailingDelimiter: true, - allowZeroLevel: true, - ignoreTopLevel: 2, - }); - expect(counter4.decorator(1)).to.be.empty; - expect(counter4.decorator(2)).to.be.empty; - expect(counter4.decorator(3)).to.equal("1."); - expect(counter4.decorator(4)).to.equal("1.1."); - expect(counter4.decorator(5)).to.equal("1.1.1."); - expect(counter4.decorator(6)).to.equal("1.1.1.1."); - expect(counter4.decorator(3)).to.equal("2."); - expect(counter4.decorator(4)).to.equal("2.1."); - expect(counter4.decorator(5)).to.equal("2.1.1."); - expect(counter4.decorator(6)).to.equal("2.1.1.1."); - expect(counter4.decorator(3)).to.equal("3."); - expect(counter4.decorator(6)).to.equal("3.0.0.1."); - }); - - it("Counter.decorator with maxRecLevel", function () { - const counter = new Counter({ - ordered: false, - levelHeadings: ["H1", "H2", "H3", "H4", "H5", "H6"], - maxRecLevel: 4, - }); - expect(counter.decorator(-1)).to.be.empty; - expect(counter.decorator(0)).to.empty; - expect(counter.decorator(1)).to.equal("H1"); - expect(counter.decorator(2)).to.equal("H2"); - expect(counter.decorator(3)).to.equal("H3"); - expect(counter.decorator(4)).to.equal("H4"); - expect(counter.decorator(5)).to.be.empty; - expect(counter.decorator(6)).to.be.empty; - expect(counter.decorator(7)).to.empty; - - const counter1 = new Counter({ - ordered: true, - styleType: "decimal", - maxRecLevel: 4, - }); - expect(counter1.decorator(1)).to.equal("1"); - expect(counter1.decorator(2)).to.equal("1.1"); - expect(counter1.decorator(3)).to.equal("1.1.1"); - expect(counter1.decorator(4)).to.equal("1.1.1.1"); - expect(counter1.decorator(5)).to.be.empty; - expect(counter1.decorator(6)).to.be.empty; - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("1.2"); - expect(counter1.decorator(3)).to.equal("1.2.1"); - expect(counter1.decorator(4)).to.equal("1.2.1.1"); - expect(counter1.decorator(5)).to.be.empty; - expect(counter1.decorator(6)).to.be.empty; - expect(counter1.decorator(7)).to.be.empty; - expect(counter1.decorator(2)).to.equal("1.3"); - expect(counter1.decorator(6)).to.be.empty; - - const counter2 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - ignoreTopLevel: 2, - maxRecLevel: 4, - }); - expect(counter2.decorator(1)).to.be.empty; - expect(counter2.decorator(2)).to.be.empty; - expect(counter2.decorator(3)).to.equal("1"); - expect(counter2.decorator(4)).to.equal("1.1"); - expect(counter2.decorator(5)).to.be.empty; - expect(counter2.decorator(6)).to.be.empty; - expect(counter2.decorator(7)).to.be.empty; - expect(counter2.decorator(3)).to.equal("2"); - expect(counter2.decorator(6)).to.be.empty; - - const counter3 = new Counter({ - ordered: true, - styleType: "decimal", - allowZeroLevel: true, - ignoreTopLevel: 2, - maxRecLevel: 3, - }); - expect(counter3.decorator(3)).to.equal("1"); - expect(counter3.decorator(4)).to.be.empty; - expect(counter3.decorator(5)).to.be.empty; - expect(counter3.decorator(6)).to.be.empty; - expect(counter3.decorator(3)).to.equal("2"); - expect(counter3.decorator(6)).to.be.empty; - - const counter4 = new Counter({ - ordered: true, - styleType: "decimal", + customTrailingDelimiter: "|", + }; + const h6: Partial = { + styleType: "lowerGreek", + delimiter: "/", trailingDelimiter: true, - allowZeroLevel: true, - ignoreTopLevel: 2, - maxRecLevel: 4, + customTrailingDelimiter: ")", + leadingDelimiter: true, + customLeadingDelimiter: "(", + }; + + it("IndependentCounter.decorator", function () { + const counter1 = new IndependentCounter({}); + expect(counter1.decorator(-1)).to.be.empty; + expect(counter1.decorator(0)).to.be.empty; + expect(counter1.decorator(1)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("2"); + expect(counter1.decorator(2)).to.equal("3"); + expect(counter1.decorator(2)).to.equal("4"); + expect(counter1.decorator(2)).to.equal("5"); + expect(counter1.decorator(3)).to.equal("1"); + expect(counter1.decorator(4)).to.equal("1"); + expect(counter1.decorator(5)).to.equal("1"); + expect(counter1.decorator(6)).to.equal("1"); + expect(counter1.decorator(1)).to.equal("2"); + expect(counter1.decorator(2)).to.equal("1"); + expect(counter1.decorator(3)).to.equal("1"); + expect(counter1.decorator(2)).to.equal("2"); + + const counter2 = new IndependentCounter({ + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter2.decorator(-1)).to.be.empty; + expect(counter2.decorator(0)).to.be.empty; + expect(counter2.decorator(1)).to.equal("A"); + expect(counter2.decorator(2)).to.equal("a"); + expect(counter2.decorator(2)).to.equal("b"); + expect(counter2.decorator(2)).to.equal("c"); + expect(counter2.decorator(2)).to.equal("d"); + expect(counter2.decorator(2)).to.equal("e"); + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(4)).to.equal("01,"); + expect(counter2.decorator(5)).to.equal("一|"); + expect(counter2.decorator(6)).to.equal("(α)"); + expect(counter2.decorator(1)).to.equal("B"); + expect(counter2.decorator(2)).to.equal("a"); + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(2)).to.equal("b"); + }); + + it("IndependentCounter.decorator with ignoreTopLevel", function () { + const counter1 = new IndependentCounter({ + ignoreTopLevel: 1, + h1: h1, + h2: h2, + h3: h3, + h4: h4, + h5: h5, + h6: h6, + }); + + expect(counter1.decorator(1)).to.be.empty; + expect(counter1.decorator(2)).to.equal("a"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("01,"); + expect(counter1.decorator(5)).to.equal("一|"); + expect(counter1.decorator(6)).to.equal("(α)"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("b"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("01,"); + expect(counter1.decorator(5)).to.equal("一|"); + expect(counter1.decorator(6)).to.equal("(α)"); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("c"); + expect(counter1.decorator(6)).to.equal("(α)"); + + const counter2 = new IndependentCounter({ + ignoreTopLevel: 2, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter2.decorator(1)).to.be.empty; + expect(counter2.decorator(2)).to.be.empty; + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(4)).to.equal("01,"); + expect(counter2.decorator(5)).to.equal("一|"); + expect(counter2.decorator(6)).to.equal("(α)"); + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(3)).to.equal("2."); + expect(counter2.decorator(6)).to.equal("(α)"); + }); + + it("IndependentCounter.decorator with allowZeroLevel", function () { + const counter = new IndependentCounter({ + allowZeroLevel: true, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter.decorator(3)).to.equal("1."); + expect(counter.decorator(4)).to.equal("01,"); + }); + + it("IndependentCounter.decorator with maxRecLevel", function () { + const counter1 = new IndependentCounter({ + maxRecLevel: 4, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter1.decorator(1)).to.equal("A"); + expect(counter1.decorator(2)).to.equal("a"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("01,"); + expect(counter1.decorator(5)).to.be.empty; + expect(counter1.decorator(6)).to.be.empty; + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("b"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("01,"); + expect(counter1.decorator(5)).to.be.empty; + expect(counter1.decorator(6)).to.be.empty; + expect(counter1.decorator(2)).to.equal("c"); + expect(counter1.decorator(6)).to.be.empty; + + const counter2 = new IndependentCounter({ + maxRecLevel: 4, + ignoreTopLevel: 2, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter2.decorator(1)).to.be.empty; + expect(counter2.decorator(2)).to.be.empty; + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(4)).to.equal("01,"); + expect(counter2.decorator(5)).to.be.empty; + expect(counter2.decorator(6)).to.be.empty; + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(3)).to.equal("2."); + expect(counter2.decorator(4)).to.equal("01,"); + expect(counter2.decorator(6)).to.be.empty; + }); + + it("IndependentCounter.decorator with orderedRecLevel", function () { + const counter1 = new IndependentCounter({ + orderedRecLevel: 3, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter1.decorator(1)).to.equal("A"); + expect(counter1.decorator(2)).to.equal("a"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("1.1."); + expect(counter1.decorator(5)).to.equal("1.1.1."); + expect(counter1.decorator(6)).to.equal("1.1.1.1."); + expect(counter1.decorator(7)).to.be.empty; + expect(counter1.decorator(2)).to.equal("b"); + expect(counter1.decorator(3)).to.equal("1."); + expect(counter1.decorator(4)).to.equal("1.1."); + expect(counter1.decorator(4)).to.equal("1.2."); + expect(counter1.decorator(4)).to.equal("1.3."); + expect(counter1.decorator(5)).to.equal("1.3.1."); + expect(counter1.decorator(6)).to.equal("1.3.1.1."); + expect(counter1.decorator(6)).to.equal("1.3.1.2."); + expect(counter1.decorator(3)).to.equal("2."); + + const counter2 = new IndependentCounter({ + orderedRecLevel: 3, + allowZeroLevel: true, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter2.decorator(1)).to.equal("A"); + expect(counter2.decorator(2)).to.equal("a"); + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(4)).to.equal("1.1."); + expect(counter2.decorator(5)).to.equal("1.1.1."); + expect(counter2.decorator(6)).to.equal("1.1.1.1."); + expect(counter2.decorator(7)).to.be.empty; + expect(counter2.decorator(2)).to.equal("b"); + expect(counter2.decorator(3)).to.equal("1."); + expect(counter2.decorator(4)).to.equal("1.1."); + expect(counter2.decorator(4)).to.equal("1.2."); + expect(counter2.decorator(4)).to.equal("1.3."); + expect(counter2.decorator(6)).to.equal("1.3.0.1."); + expect(counter2.decorator(6)).to.equal("1.3.0.2."); + expect(counter2.decorator(5)).to.equal("1.3.1."); + + const counter3 = new IndependentCounter({ + orderedRecLevel: 3, + ignoreTopLevel: 2, + h1, + h2, + h3, + h4, + h5, + h6, + }); + + expect(counter3.decorator(1)).to.be.empty; + expect(counter3.decorator(2)).to.be.empty; + expect(counter3.decorator(3)).to.equal("1."); + expect(counter3.decorator(4)).to.equal("1.1."); + expect(counter3.decorator(5)).to.equal("1.1.1."); + expect(counter3.decorator(6)).to.equal("1.1.1.1."); + expect(counter3.decorator(7)).to.be.empty; + expect(counter3.decorator(3)).to.equal("2."); + expect(counter3.decorator(6)).to.equal("2.1.1.1."); }); - expect(counter4.decorator(1)).to.be.empty; - expect(counter4.decorator(2)).to.be.empty; - expect(counter4.decorator(3)).to.equal("1."); - expect(counter4.decorator(4)).to.equal("1.1."); - expect(counter4.decorator(5)).to.be.empty; - expect(counter4.decorator(6)).to.be.empty; - expect(counter4.decorator(3)).to.equal("2."); - expect(counter4.decorator(4)).to.equal("2.1."); - expect(counter4.decorator(5)).to.be.empty; - expect(counter4.decorator(6)).to.be.empty; - expect(counter4.decorator(3)).to.equal("3."); - expect(counter4.decorator(6)).to.be.empty; }); }); diff --git a/types.d.ts b/types.d.ts index 605485e..2b057ca 100644 --- a/types.d.ts +++ b/types.d.ts @@ -10,6 +10,7 @@ type _TupleOf = R["length"] extends N type LevelTuple = TupleOf; type HeadingTuple = TupleOf; +type DecoratorMode = "orderd" | "independent" | "unordered"; type OpacityOptions = 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100; type PostionOptions = "before" | "before-inside" | "after" | "after-inside"; type RenderPolicy = "partial" | "full"; @@ -39,3 +40,8 @@ interface CSSEnabledStatus { mode: boolean | null; all: boolean | null; } + +interface Counter { + decorator(level: number): string; + handler(level: number): unknown; +}