diff --git a/README.md b/README.md index 6ba0ce52..dafd9708 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ![Tests](https://github.com/about-code/glossarify-md/workflows/Tests/badge.svg) -*glossarify-md* is a command line tool to help Markdown writers with +[glossarify-md]: https://github.com/about-code/glossarify-md + +[glossarify-md] is a command line tool to help Markdown writers with - **Cross-Linking** (prime use case): autolink terms to some definition in a glossary - **Indexes**: generate indexes from glossary terms and navigate to where they were mentioned @@ -16,16 +18,15 @@ - [Sample](#sample) - [Results](#results) - [Configuration](#configuration) - - [Via File](#via-file) - - [Via Command Line](#via-command-line) + - [Overriding via Command Line](#overriding-via-command-line) - [Additional Features](#additional-features) - [Aliases and Synonyms](#aliases-and-synonyms) - [Term Hints](#term-hints) - [Multiple Glossaries](#multiple-glossaries) - [Index of terms and where they have been used](#index-of-terms-and-where-they-have-been-used) + - [Lists](#lists) - [List of Figures](#list-of-figures) - [List of Tables](#list-of-tables) - - [Arbitrary Lists with Anchors](#arbitrary-lists-with-anchors) - [Sorting your glossaries](#sorting-your-glossaries) - [Node Support Matrix](#node-support-matrix) - [Options](#options) @@ -108,7 +109,7 @@ Your original files may just use the term *Term* anywhere in text: This is a text which uses a glossary Term to describe something. ``` -Then run *glossarify-md* with a [glossarify-md.conf.json](#configuration). +Then run [glossarify-md] with a [glossarify-md.conf.json](#configuration). ## Results @@ -167,7 +168,7 @@ Some syntactic positions of a term are **excluded** from being linked to the glo ## Configuration -### Via File +Having a configuration file is the recommended way of configuring [glossarify-md]. A minimal configuration may look like: *glossarify-md.conf.json* (minimal): @@ -176,8 +177,9 @@ Some syntactic positions of a term are **excluded** from being linked to the glo "$schema": "./node_modules/glossarify-md/conf.schema.json", "baseDir": "./src", "outDir": "../target", + "outDirDropOld": true, "glossaries": [ - { "file": "./glossary.md" } + { "file": "./glossary.md" }, ], "includeFiles": ["."], "excludeFiles": ["node_modules"], @@ -185,27 +187,24 @@ Some syntactic positions of a term are **excluded** from being linked to the glo } ``` -**Note:** All paths (except of `$schema`) must be relative to `baseDir`. `baseDir` itself is relative to the location of the config file. - -More options see [Additional Features](#additional-features) or [Options](#options) below. +**Note:** All paths (except of `$schema`) are interpreted relative to `baseDir`. `baseDir` itself is relative to the location of the config file or current working directory. More options see [Additional Features](#additional-features) or [Options](#options) below. -### Via Command Line +### Overriding via Command Line Use `--shallow` or `--deep` 1. to provide a configuration solely via command line -1. to merge a configuration via command line with - - the implicit default configuration in `./node_modules/glossarify-md/conf.json.schema` - - a configuration file (to modify it for a particular execution) +1. to merge a configuration with your config file or the implicit default config in `./node_modules/glossarify-md/conf.json.schema` -*Example: Shallow-Merge with implicit default configuration* +Use `--shallow` to *replace* simple top-level options: ``` glossarify-md + --config ./glossarify-md.conf.json --shallow "{ 'baseDir':'./src', 'outDir':'../target' }" ``` -*Example: Override glossaries array in a config file via CLI* +Use `--shallow` to *replace* complex nested options like `glossaries` alltogether: ``` glossarify-md @@ -213,7 +212,7 @@ glossarify-md --shallow "{ 'glossaries': [{'file':'./replace.md'}] }" ``` -*Example: Extend glossaries array in a config file via CLI* +Use `--deep` to *extend* complex nested options, e.g. to *add* another array item to `glossaries` in the config file write: ``` glossarify-md @@ -307,11 +306,68 @@ This option will generate a file `./book-index.md` with a list of glossary terms > **Note**: If you plan on translating markdown to HTML, e.g. with [vuepress](https://vuepress.vuejs.org), be aware that a file `index.md` will translate to `index.html` which is typically reserved for the default HTML file served under a domain. You may want to choose another name. +### Lists + +> **Since v3.5.0** + +You can generate arbitrary lists linked to particular elements in your content using HTML anchor (``) annotations and *classes*. For example, to generate a *List of People* you mentioned configure [glossarify-md] with `generateFiles.listOf`... + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "listOf": [ + { "class": "people", "file": "./people.md", "title": "List of People" } + ] +} +``` + +... and mark any position where you mention a person with an HTML anchor: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Type less** by prefixing the anchor `id` with the anchor class: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Hide anchors** using the `title` attribute as a link label in the list: + +```md +The theory of general relativity +was groundbreaking. +``` + +> **Link label extraction** +> +> The link label for list items will be inferred in this order (first-match): +> +> 1. `title` attribute value (``) +> 1. Inner text of anchor tag (`label`) +> 1. `id` attribute value, yet without list prefix (``) +> 1. Preceding section heading if `id` is just the list prefix (``) +> 1. Filename if `id` is just the list prefix and there is no preceding section heading. + +#### List Item Grouping + +By default list items will be grouped by section of occurrence using the section heading as a group title. You can generate a flat list and disable grouping (affects any list generated): + +```json +"indexing": { + "groupByHeadingDepth": 0 +} +``` + ### List of Figures > **Since v3.3.0** -> -> - Alternatively read [Arbitrary Lists with Anchors](#arbitrary-lists-with-anchors) (since 3.5.0) + +> **Since v4.1.0** `listOfFigures` annotates Markdown image references with HTML anchors as shown in [Lists](#lists). *glossarify-md.conf.json* @@ -321,23 +377,57 @@ This option will generate a file `./book-index.md` with a list of glossary terms } ``` -This option will generate an index file `./figures.md` with a list of figures grouped by sections of occurrence. You can control heading depth for grouping and e.g. generate a flat list without any grouping using +Let's say you have images referenced via Markdown syntax *and* images generated dynamically by an embedded script or some code block being sent to a rendering server (we're using [PlantUML](https://plantuml.com) as an example). `listOfFigures` can only detect Markdown references. You need to explicitely annotate dynamic graphics like in the following input... + +````md +Markdown image reference ![Foo](./figure.png) and dynamically +rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +```` + +... and `listOfFigures` will prepended a similar anchor to the markdown link: + +````md +Markdown image reference +![Foo](./figure.png) and dynamically rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +```` + +From the anchors sharing the same (default) anchor class ***figure*** a common list of figures will be generated. The previous [glossarify-md] configuration is only a shorthand for this one (since v4.1.0) ... *glossarify-md.conf.json* ```json -"indexing": { - "groupByHeadingDepth": 0 +"generateFiles": { + "listOfFigures": { "class": "figure" }, + "listOf": [ + {"class": "figure", "file": "./figures.md", "title": "Figures" } + ] } ``` +... which allows to replace the conventional anchor class ***figure*** with a shorter one, e.g. ***fig***. +**Note: this applies to Markdown tables and `listOfTables`, similarily.** + ### List of Tables > **Since v3.4.0** -> -> - Alternatively read [Arbitrary Lists with Anchors](#arbitrary-lists-with-anchors) (since 3.5.0) -Generate a file `./tables.md` with a list of tables grouped by sections of occurrence. See [`groupByHeadingDepth`](#list-of-figures) to find out how to control grouping. +> **Since v4.1.0** `listOfTables` annotates tables with HTML anchors as shown in [Lists](#lists) using information given in HTML comments as shown below. *glossarify-md.conf.json* @@ -347,9 +437,9 @@ Generate a file `./tables.md` with a list of tables grouped by sections of occur } ``` -Markdown tables have no inherent notion of a table label. *glossarify-md* scans for two patterns of user-defined table labels and attempts to infer a table label otherwise. +Generates a list of tables into `./tables.md`. Markdown tables have no inherent notion of a table caption. [glossarify-md] scans for two patterns of user-defined table labels and attempts to infer a table label otherwise: -#### Invisible table label +**1. HTML Comment (invisible):** ```md @@ -360,9 +450,9 @@ Markdown tables have no inherent notion of a table label. *glossarify-md* scans | 3 | Book | $23.45 | ``` -#### Visible table label +**2. Colon-Terminated Emphasized Paragraph Ending (visible):** -A visible table label will be inferred from an italic phrase terminated by a colon two lines prior to the table. The phrase can be a distinct paragraph... +A caption can be inferred from a distinct paragraph... ```md [...] which we can see from the average price by article category. @@ -376,10 +466,10 @@ A visible table label will be inferred from an italic phrase terminated by a col | 3 | Book | $23.45 | ``` -... or a phrase inlined into text: +... or a colon-terminated emphasized phrase at the end of the preceding paragraph: ```md -[...] which we can see from the *Average prices by article category:* +[...] which we can see from the *table of average prices by article category:* | Category | Description | Price Avg. | | -------- | ----------- | ---------- | @@ -388,71 +478,19 @@ A visible table label will be inferred from an italic phrase terminated by a col | 3 | Book | $23.45 | ``` -#### Labels for generated list items will be inferred in this order (first-match): +Otherwise labels for generated list items will be inferred in this order (first-match): 1. **HTML comment** in the line above the table 1. **emphasized text** at the end of the preceding paragraph 1. **column headers** separated by comma, e.g. *Category, Description, Price Avg.* -1. **preceding section heading** (multiple tables without column headers in the same section may be labeled ambiguously) -1. **filename** in which the table has been found. - -### Arbitrary Lists with Anchors - -> **Since v3.5.0** - -You can generate arbitrary *List of ...* lists by using HTML anchors (``) and anchor *classes*. - -> Anchors can be directly navigated to while [`listOfTables`](#list-of-tables) or [`listOfFigures`](#list-of-figures) only generate links to headings preceding a table or figure. - -For example, to generate a *List of Tables* add - -*glossarify-md.conf.json* - -```json -"generateFiles": { - "listOf": [ - { "class": "table", "file": "./tables.md", "title": "List of Tables" } - ] -} -``` - -and mark the position of a table with an HTML anchor: - -```md -Average prices by article category: - -| Category | Description | Price Avg. | -| -------- | ----------- | ---------- | -| 1 | Video Game | $35.66 | -| 2 | Film | $10.13 | -| 3 | Book | $23.45 | -``` - -Type less by passing the anchor `class` as an `id`-prefix: - -```md -Average prices by article category -``` - -Hide anchors with a `title` attribute: - -```md - -``` - -#### Labels for generated list items will be inferred in this order (first-match): - -1. `title` attribute value (``) -1. Inner text of anchor tag (`label`) -1. `id` attribute value, yet without list prefix (``) -1. Preceding section heading if `id` is just the list prefix (``) -1. Filename if `id` is just the list prefix and there is no preceding section heading, either. +1. **preceding section heading** (tables without column headers) +1. **filename** otherwise. ### Sorting your glossaries > **Since v3.6.0** -Add `sort` direction `"asc"` or `"desc"` to glossaries for which you want *glossarify-md* to sort them for you: +Add `sort` direction `"asc"` or `"desc"` to glossaries for which you want [glossarify-md] to sort them for you: *glossarify-md.conf.json* @@ -486,7 +524,7 @@ The term *support* refers to *runs on the given platform*. Compatibility is main | Node-Version | compatibility & support status | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Current | Tested. Should Node introduce breaking changes which affect *glossarify-md*, then we may choose to step back from supporting *Current* until it becomes the next LTS. | +| Current | Tested. Should Node introduce breaking changes which affect [glossarify-md], then we may choose to step back from supporting *Current* until it becomes the next LTS. | | 12.x LTS | Tested + Supported | | 10.x LTS | Tested + Supported | @@ -509,7 +547,7 @@ processing markdown files with an MD to HTML converter omitting a pre-defined - **Range:** `string` -Path to directory where to search for the glossary and markdown files. All paths in a config file will be relative to *baseDir*. *baseDir* itself is relative to the location of the config file. +Path to directory where to search for the glossary and markdown files. All paths in a config file except for `$schema` will be relative to *baseDir*. *baseDir* itself and `$schema` are relative to the location of the config file. #### \`excludeFiles @@ -535,14 +573,14 @@ If available, generates an index of glossary terms with links to files in which #### `generateFiles.listOfFigures` -- **Range:** `{file: string, [title: string]}` +- **Range:** `{file: string, [title: string, class: string]}` - **Since:** v3.3.0 If available, generates a list of figures with links to sections where the figures have been mentioned. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-figures) for a configuration example. #### `generateFiles.listOfTables` -- **Range:** `{file: string, [title: string]}` +- **Range:** `{file: string, [title: string, class: string]}` - **Since:** v3.4.0 If available, generates a list of tables. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-tables) for an example. @@ -552,7 +590,7 @@ If available, generates a list of tables. See section [Additional Features](http - **Range:** `Array<{class: string, file: string, [title: string]}>` - **Since:** v3.5.0 -If available, generates a list from HTML anchors exposing the configured `class` attribute. See section [Additional Features](https://github.com/about-code/glossarify-md#arbitrary-lists-with-anchors) for an example. +If available, generates a list from HTML anchors exposing the configured `class` attribute. See section [Additional Features](https://github.com/about-code/glossarify-md#lists) for an example. #### `glossaries` @@ -628,7 +666,7 @@ The directory where to write output files to. > **Important:** using `.` or `./` is going to overwrite your input files. Only do this on a copy of your input > files or if you are able to roll back any changes or if you know the outcome satisfies your needs. -The recommendation is to write outputs to a separate directory such as `../out` or `../tmp`. or `../target`. +The recommendation is to write outputs to a separate directory such as `../out` or `../glossarified`. or `../target`. #### `outDirDropOld` diff --git a/conf.schema.json b/conf.schema.json index 3d580720..b8cc9d2a 100644 --- a/conf.schema.json +++ b/conf.schema.json @@ -125,24 +125,10 @@ "default": {} }, "listOf": { - "description": "Generate an arbitrary 'List of {x}' from HTML anchors with css class {x}. E.g. Generate a List of Listings from every and link to those anchors.", + "description": "Generate an arbitrary list of links into your documents. For example, to generate a List of code samples configure a class 'listing' and add anchors before your sample code blocks.", "type": "array", "items": { - "type": "object", - "properties": { - "class": { - "description": "The CSS class to look for in anchor elements", - "type": "string" - }, - "file": { - "description": "Path relative to 'outDir' where to create the output file.", - "type": "string" - }, - "title": { - "description": "The page title for the index file. If missing it's being inferred from the value of 'class'.", - "type": "string" - } - } + "$ref": "#/$defs/IndexFileOpts" } }, "listOfFigures": { @@ -166,6 +152,10 @@ "description": "Path relative to 'outDir' where to create the index markdown file.", "type": "string" }, + "class": { + "description": "The class is used to compile lists of content elements. Elements with a common class will be compiled into the same list.", + "type": "string" + }, "title": { "description": "The page title for the index file. If missing the application uses a default value.", "type": "string" diff --git a/doc/templates/README.md b/doc/templates/README.md index 80488208..02cf6d11 100644 --- a/doc/templates/README.md +++ b/doc/templates/README.md @@ -2,7 +2,9 @@ ![Tests](https://github.com/about-code/glossarify-md/workflows/Tests/badge.svg) -*glossarify-md* is a command line tool to help Markdown writers with +[glossarify-md]: https://github.com/about-code/glossarify-md + +[glossarify-md] is a command line tool to help Markdown writers with - **Cross-Linking** (prime use case): autolink terms to some definition in a glossary - **Indexes**: generate indexes from glossary terms and navigate to where they were mentioned @@ -89,7 +91,7 @@ Your original files may just use the term *Term* anywhere in text: This is a text which uses a glossary Term to describe something. ``` -Then run *glossarify-md* with a [glossarify-md.conf.json](#configuration). +Then run [glossarify-md] with a [glossarify-md.conf.json](#configuration). ## Results @@ -149,7 +151,7 @@ Some syntactic positions of a term are **excluded** from being linked to the glo ## Configuration -### Via File +Having a configuration file is the recommended way of configuring [glossarify-md]. A minimal configuration may look like: *glossarify-md.conf.json* (minimal): @@ -167,34 +169,32 @@ Some syntactic positions of a term are **excluded** from being linked to the glo "linking": "relative" } ``` -**Note:** All paths (except of `$schema`) must be relative to `baseDir`. `baseDir` itself is relative to the location of the config file. - +**Note:** All paths (except of `$schema`) are interpreted relative to `baseDir`. `baseDir` itself is relative to the location of the config file or current working directory. More options see [Additional Features](#additional-features) or [Options](#options) below. -More options see [Additional Features](#additional-features) or [Options](#options) below. - -### Via Command Line +### Overriding via Command Line Use `--shallow` or `--deep` 1. to provide a configuration solely via command line -2. to merge a configuration via command line with - - the implicit default configuration in `./node_modules/glossarify-md/conf.json.schema` - - a configuration file (to modify it for a particular execution) +2. to merge a configuration with your config file or the implicit default config in `./node_modules/glossarify-md/conf.json.schema` -*Example: Shallow-Merge with implicit default configuration* +Use `--shallow` to *replace* simple top-level options: ~~~ glossarify-md + --config ./glossarify-md.conf.json --shallow "{ 'baseDir':'./src', 'outDir':'../target' }" ~~~ -*Example: Override glossaries array in a config file via CLI* +Use `--shallow` to *replace* complex nested options like `glossaries` alltogether: + ~~~ glossarify-md --config ./glossarify-md.conf.json --shallow "{ 'glossaries': [{'file':'./replace.md'}] }" ~~~ -*Example: Extend glossaries array in a config file via CLI* +Use `--deep` to *extend* complex nested options, e.g. to *add* another array item to `glossaries` in the config file write: + ~~~ glossarify-md --config ./glossarify-md.conf.json @@ -286,11 +286,68 @@ This option will generate a file `./book-index.md` with a list of glossary terms > **Note**: If you plan on translating markdown to HTML, e.g. with [vuepress](https://vuepress.vuejs.org), be aware that a file `index.md` will translate to `index.html` which is typically reserved for the default HTML file served under a domain. You may want to choose another name. +### Lists + +> **Since v3.5.0** + +You can generate arbitrary lists linked to particular elements in your content using HTML anchor (``) annotations and *classes*. For example, to generate a *List of People* you mentioned configure [glossarify-md] with `generateFiles.listOf`... + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "listOf": [ + { "class": "people", "file": "./people.md", "title": "List of People" } + ] +} +``` + +... and mark any position where you mention a person with an HTML anchor: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Type less** by prefixing the anchor `id` with the anchor class: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Hide anchors** using the `title` attribute as a link label in the list: + +```md +The theory of general relativity +was groundbreaking. +``` + +> **Link label extraction** +> +> The link label for list items will be inferred in this order (first-match): +> +> 1. `title` attribute value (``) +> 1. Inner text of anchor tag (`label`) +> 1. `id` attribute value, yet without list prefix (``) +> 1. Preceding section heading if `id` is just the list prefix (``) +> 1. Filename if `id` is just the list prefix and there is no preceding section heading. + +#### List Item Grouping + +By default list items will be grouped by section of occurrence using the section heading as a group title. You can generate a flat list and disable grouping (affects any list generated): + +```json +"indexing": { + "groupByHeadingDepth": 0 +} +``` + ### List of Figures > **Since v3.3.0** -> -> - Alternatively read [Arbitrary Lists with Anchors](#arbitrary-lists-with-anchors) (since 3.5.0) + +> **Since v4.1.0** `listOfFigures` annotates Markdown image references with HTML anchors as shown in [Lists](#lists). *glossarify-md.conf.json* ```json @@ -299,33 +356,66 @@ This option will generate a file `./book-index.md` with a list of glossary terms } ``` -This option will generate an index file `./figures.md` with a list of figures grouped by sections of occurrence. You can control heading depth for grouping and e.g. generate a flat list without any grouping using +Let's say you have images referenced via Markdown syntax *and* images generated dynamically by an embedded script or some code block being sent to a rendering server (we're using [PlantUML](https://plantuml.com) as an example). `listOfFigures` can only detect Markdown references. You need to explicitely annotate dynamic graphics like in the following input... + +~~~md +Markdown image reference ![Foo](./figure.png) and dynamically +rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +... and `listOfFigures` will prepended a similar anchor to the markdown link: + +~~~md +Markdown image reference +![Foo](./figure.png) and dynamically rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +From the anchors sharing the same (default) anchor class ***figure*** a common list of figures will be generated. The previous [glossarify-md] configuration is only a shorthand for this one (since v4.1.0) ... *glossarify-md.conf.json* ```json -"indexing": { - "groupByHeadingDepth": 0 +"generateFiles": { + "listOfFigures": { "class": "figure" }, + "listOf": [ + {"class": "figure", "file": "./figures.md", "title": "Figures" } + ] } ``` +... which allows to replace the conventional anchor class ***figure*** with a shorter one, e.g. ***fig***. +**Note: this applies to Markdown tables and `listOfTables`, similarily.** ### List of Tables > **Since v3.4.0** -> -> - Alternatively read [Arbitrary Lists with Anchors](#arbitrary-lists-with-anchors) (since 3.5.0) -Generate a file `./tables.md` with a list of tables grouped by sections of occurrence. See [`groupByHeadingDepth`](#list-of-figures) to find out how to control grouping. +> **Since v4.1.0** `listOfTables` annotates tables with HTML anchors as shown in [Lists](#lists) using information given in HTML comments as shown below. *glossarify-md.conf.json* + ```json "generateFiles": { "listOfTables": { "file": "./tables.md", "title": "Tables" } } ``` +Generates a list of tables into `./tables.md`. Markdown tables have no inherent notion of a table caption. [glossarify-md] scans for two patterns of user-defined table labels and attempts to infer a table label otherwise: -Markdown tables have no inherent notion of a table label. *glossarify-md* scans for two patterns of user-defined table labels and attempts to infer a table label otherwise. - -#### Invisible table label +**1. HTML Comment (invisible):** ```md @@ -336,9 +426,9 @@ Markdown tables have no inherent notion of a table label. *glossarify-md* scans | 3 | Book | $23.45 | ``` -#### Visible table label +**2. Colon-Terminated Emphasized Paragraph Ending (visible):** -A visible table label will be inferred from an italic phrase terminated by a colon two lines prior to the table. The phrase can be a distinct paragraph... +A caption can be inferred from a distinct paragraph... ```md [...] which we can see from the average price by article category. @@ -352,10 +442,10 @@ A visible table label will be inferred from an italic phrase terminated by a col | 3 | Book | $23.45 | ``` -... or a phrase inlined into text: +... or a colon-terminated emphasized phrase at the end of the preceding paragraph: ```md -[...] which we can see from the *Average prices by article category:* +[...] which we can see from the *table of average prices by article category:* | Category | Description | Price Avg. | | -------- | ----------- | ---------- | @@ -364,71 +454,20 @@ A visible table label will be inferred from an italic phrase terminated by a col | 3 | Book | $23.45 | ``` -#### Labels for generated list items will be inferred in this order (first-match): +Otherwise labels for generated list items will be inferred in this order (first-match): 1. **HTML comment** in the line above the table 1. **emphasized text** at the end of the preceding paragraph 1. **column headers** separated by comma, e.g. *Category, Description, Price Avg.* -1. **preceding section heading** (multiple tables without column headers in the same section may be labeled ambiguously) -1. **filename** in which the table has been found. - -### Arbitrary Lists with Anchors - -> **Since v3.5.0** - -You can generate arbitrary *List of ...* lists by using HTML anchors (``) and anchor *classes*. - -> Anchors can be directly navigated to while [`listOfTables`](#list-of-tables) or [`listOfFigures`](#list-of-figures) only generate links to headings preceding a table or figure. - -For example, to generate a *List of Tables* add - -*glossarify-md.conf.json* -```json -"generateFiles": { - "listOf": [ - { "class": "table", "file": "./tables.md", "title": "List of Tables" } - ] -} -``` - -and mark the position of a table with an HTML anchor: - -```md -Average prices by article category: - -| Category | Description | Price Avg. | -| -------- | ----------- | ---------- | -| 1 | Video Game | $35.66 | -| 2 | Film | $10.13 | -| 3 | Book | $23.45 | -``` - -Type less by passing the anchor `class` as an `id`-prefix: - -```md -Average prices by article category -``` - -Hide anchors with a `title` attribute: - -```md - -``` - -#### Labels for generated list items will be inferred in this order (first-match): - -1. `title` attribute value (``) -1. Inner text of anchor tag (`label`) -1. `id` attribute value, yet without list prefix (``) -1. Preceding section heading if `id` is just the list prefix (``) -1. Filename if `id` is just the list prefix and there is no preceding section heading, either. +1. **preceding section heading** (tables without column headers) +1. **filename** otherwise. ### Sorting your glossaries > **Since v3.6.0** -Add `sort` direction `"asc"` or `"desc"` to glossaries for which you want *glossarify-md* to sort them for you: +Add `sort` direction `"asc"` or `"desc"` to glossaries for which you want [glossarify-md] to sort them for you: *glossarify-md.conf.json* ```json @@ -460,7 +499,7 @@ The term *support* refers to *runs on the given platform*. Compatibility is main | Node-Version | compatibility & support status | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Current | Tested. Should Node introduce breaking changes which affect *glossarify-md*, then we may choose to step back from supporting *Current* until it becomes the next LTS. | +| Current | Tested. Should Node introduce breaking changes which affect [glossarify-md], then we may choose to step back from supporting *Current* until it becomes the next LTS. | | 12.x LTS | Tested + Supported | | 10.x LTS | Tested + Supported | @@ -509,14 +548,14 @@ If available, generates an index of glossary terms with links to files in which #### `generateFiles.listOfFigures` -- **Range:** `{file: string, [title: string]}` +- **Range:** `{file: string, [title: string, class: string]}` - **Since:** v3.3.0 If available, generates a list of figures with links to sections where the figures have been mentioned. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-figures) for a configuration example. #### `generateFiles.listOfTables` -- **Range:** `{file: string, [title: string]}` +- **Range:** `{file: string, [title: string, class: string]}` - **Since:** v3.4.0 If available, generates a list of tables. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-tables) for an example. @@ -526,7 +565,7 @@ If available, generates a list of tables. See section [Additional Features](http - **Range:** `Array<{class: string, file: string, [title: string]}>` - **Since:** v3.5.0 -If available, generates a list from HTML anchors exposing the configured `class` attribute. See section [Additional Features](https://github.com/about-code/glossarify-md#arbitrary-lists-with-anchors) for an example. +If available, generates a list from HTML anchors exposing the configured `class` attribute. See section [Additional Features](https://github.com/about-code/glossarify-md#lists) for an example. #### `glossaries` diff --git a/doc/templates/README.md.orig b/doc/templates/README.md.orig new file mode 100644 index 00000000..19a6f593 --- /dev/null +++ b/doc/templates/README.md.orig @@ -0,0 +1,761 @@ +# glossarify-md + +![Tests](https://github.com/about-code/glossarify-md/workflows/Tests/badge.svg) + +[glossarify-md]: https://github.com/about-code/glossarify-md + +[glossarify-md] is a command line tool to help Markdown writers with + +- **Cross-Linking** (prime use case): autolink terms to some definition in a glossary +- **Indexes**: generate indexes from glossary terms and navigate to where they were mentioned +- **Lists**: generate arbitrary lists such as *List of Tables*, *List of Figures*, *List of Listings*, *List of Definitions*, *List of Formulas*, and so forth... + +[vuepress](https://vuepress.vuejs.org) users might be interested in learning [how to use the tool with vuepress](https://github.com/about-code/glossarify-md/blob/master/doc/vuepress.md). + + +## Table of Contents + +## Install + +#### Option 1: Run in any directory: +``` +npm i -g glossarify-md +``` + +``` +glossarify-md --config ./glossarify-md.conf.json +``` + +#### Option 2: Install locally to your project: + +``` +npm i glossarify-md +``` + +``` +npx glossarify-md --config ./glossarify-md.conf.json +``` + +or add as an npm-script to your `package.json`: + +*package.json* +```json +scripts: { + "glossarify": "glossarify-md --config ./glossarify-md.conf.json" +} +``` + +``` +npm run glossarify +``` + + +## Sample + +We assume a sample project with the following structure: + +``` +${root} + +- src/ + | +- pages/ + | | |- page1.md + | | `- page2.md + | | + | |- README.md + | |- requirements.md + | `- glossary.md + | + +- target/ (Generated output directory) + `- glossarify-md.conf.json +``` + +Your original glossary is a file + +*src/glossary.md* + +```md +# Glossary + +## Term + +A glossary term has a short description. The full description contains both sentences. +``` + +Your original files may just use the term *Term* anywhere in text: + +*src/pages/page1.md* + +```md +# Demo + +This is a text which uses a glossary Term to describe something. +``` + +Then run [glossarify-md] with a [glossarify-md.conf.json](#configuration). + + +## Results + +Augmented versions of the source files have been written to the output directory. Headings in glossary files have been made linkable... + +*./target/glossary.md*: + +```md +# [Glossary](#glossary) + +## [Term](#term) + +A glossary term has a short description. The full description contains both sentences. +``` + +> ## [Glossary](#glossary) +> +> ### [Term](#term) +> +> A glossary term has a short description. The full description contains both sentences. + +... and occurrences of the term in markdown files have been linked to the term definition in the glossary: + +*./target/pages/page1.md* + +```md +# [Demo](#demo) + +This is a text which uses a glossary [Term ↴][1] to describe something. + +[1]: ../glossary.md#term "A glossary term has a short description." +``` + +> ## [Demo](#demo) +> +> This is a text which uses a glossary [Term ↴][1] to describe something. +> +> [1]: #term "A glossary term has a short description." + +Some syntactic positions of a term are **excluded** from being linked to the glossary. These are + +- Headlines +- Blockquotes +- Preformatted blocks +- (Markdown) links + +> **Important:** As of now, we can't prevent text between the opening and closing angle brackets of an HTML link to be linkified. In a markdown syntax tree something like `term` is represented as distinct HTML nodes with arbitrary complex markdown nodes in between. Therefore a term found between those HTML tags currently results in +> +> ``` +> [term][1] +> +> [1] ./glossary.md#term +> ``` + +> **Note:** Terms found in blockquotes are not automatically linked to a glossary definition since a quoted source entity may not share the same definition of a term as the entity who quotes it. It may use a term in a completely different semantic context. + +## Configuration + +Having a configuration file is the recommended way of configuring [glossarify-md]. A minimal configuration may look like: + +*glossarify-md.conf.json* (minimal): + +```json +{ + "$schema": "./node_modules/glossarify-md/conf.schema.json", + "baseDir": "./src", + "outDir": "../target", + "outDirDropOld": true, + "glossaries": [ + { "file": "./glossary.md" }, + ], + "includeFiles": ["."], + "excludeFiles": ["node_modules"], + "linking": "relative" +} +``` +**Note:** All paths (except of `$schema`) are interpreted relative to `baseDir`. `baseDir` itself is relative to the location of the config file or current working directory. More options see [Additional Features](#additional-features) or [Options](#options) below. + +### Overriding via Command Line + +Use `--shallow` or `--deep` + +1. to provide a configuration solely via command line +2. to merge a configuration with your config file or the implicit default config in `./node_modules/glossarify-md/conf.json.schema` + +Use `--shallow` to *replace* simple top-level options: +~~~ +glossarify-md + --config ./glossarify-md.conf.json + --shallow "{ 'baseDir':'./src', 'outDir':'../target' }" +~~~ + +Use `--shallow` to *replace* complex nested options like `glossaries` alltogether: + +~~~ +glossarify-md + --config ./glossarify-md.conf.json + --shallow "{ 'glossaries': [{'file':'./replace.md'}] }" +~~~ + +Use `--deep` to *extend* complex nested options, e.g. to *add* another array item to `glossaries` in the config file write: + +~~~ +glossarify-md + --config ./glossarify-md.conf.json + --deep "{'glossaries': [{'file':'./extend.md'}] }" +~~~ + + +## Additional Features + +### Aliases and Synonyms + +Aliases can be defined in an HTML comment with the keyword `Aliases:` followed by a comma-separated list of alternative terms. + +*glossary.md* + +```md +# Glossary + +## Cat + +Cats are cute, ...dogs are loyal. +``` + +In the output files aliases will be linked to their related term: + +*./target/pages/page2.md* + +```md +# About Cats + +[Cats](./glossary.md#cat) and kitten almost hidden spotting mouses in their houses. [The Author] +``` + +### Term Hints + +*glossarify-md.conf.json* +```json +"glossaries": [ + { "file": "./glossary.md", "termHint": "↴"}, +] +``` + +Glossaries can be associated with *term hints*. Term hints may be used to indicate that a link refers to a glossary term and in case of [multiple glossaries](#multiple-glossaries) to which one. + +> **Since v2.0.0**: +Use `"${term}"` to control placement of a `termHint`. For example, `"☛ ${term}"` puts the symbol `☛` in front of the link. + +### Multiple Glossaries +Sometimes you might whish to have multiple glossaries. For example as a Requirements Engineer you may not just have a glossary of business terms but also a requirements catalogue: + +*glossarify-md.conf.json* + +```json +"glossaries": [ + { "file": "./glossary.md", "termHint": "↴" }, + { "file": "./requirements.md", "termHint": "★" } +] +``` + +*requirements.md* + +```md +## REQ-1: The system MUST provide service X + +... +## REQ-2: The system MAY provide service Y + +... +``` + +By adding *requirements.md* to the list of glossaries every use of *REQ-1* or *REQ-2* gets linked to the requirements catalogue. Read on to find out how to generate an index in order to answer the question in which particular sections those requirements got mentioned. + +### Index of terms and where they have been used + +> **Since v3.0.0** + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "indexFile": { + "file": "./book-index.md", + "title": "Book Index" + } +} +``` + +This option will generate a file `./book-index.md` with a list of glossary terms and links to book sections in which they have been mentioned. The `title` argument is optional. If missing the value given in the example will be the default. + +> **Note**: If you plan on translating markdown to HTML, e.g. with [vuepress](https://vuepress.vuejs.org), be aware that a file `index.md` will translate to `index.html` which is typically reserved for the default HTML file served under a domain. You may want to choose another name. + +<<<<<<< Updated upstream +### Lists + +> **Since v3.5.0** + +You can generate arbitrary lists linked to particular elements in your content using HTML anchor (``) annotations and *classes*. For example, to generate a *List of People* you mentioned configure [glossarify-md] with `generateFiles.listOf`... + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "listOf": [ + { "class": "people", "file": "./people.md", "title": "List of People" } + ] +} +``` + +... and mark any position where you mention a person with an HTML anchor: + +```md +The general theory of relativity by Albert Einstein +was ground-breaking. +``` + +**Type less** by prefixing the anchor `id` with the anchor class: + +```md +The general theory of relativity by Albert Einstein +was ground-breaking. +``` + +**Hide anchors** using the `title` attribute as a link label in the list: + +```md +The general theory of relativity +was ground-breaking. +``` + +> **Link label extraction** +> +> The link label for list items will be inferred in this order (first-match): +> +> 1. `title` attribute value (``) +> 1. Inner text of anchor tag (`label`) +> 1. `id` attribute value, yet without list prefix (``) +> 1. Preceding section heading if `id` is just the list prefix (``) +> 1. Filename if `id` is just the list prefix and there is no preceding section heading. + +#### List Item Grouping + +By default list items will be grouped by section of occurrence using the section heading as a group title. You can generate a flat list and disable grouping (affects any list generated): + +```json +"indexing": { + "groupByHeadingDepth": 0 +} +``` + +||||||| merged common ancestors +======= +### Lists + +> **Since v3.5.0** + +You can generate arbitrary lists linked to particular elements in your content using HTML anchor (``) annotations and *classes*. For example, to generate a *List of People* you mentioned configure [glossarify-md] with `generateFiles.listOf`... + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "listOf": [ + { "class": "people", "file": "./people.md", "title": "List of People" } + ] +} +``` + +... and mark any position where you mention a person with an HTML anchor: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Type less** by prefixing the anchor `id` with the anchor class: + +```md +The theory of general relativity by Albert Einstein +was groundbreaking. +``` + +**Hide anchors** using the `title` attribute as a link label in the list: + +```md +The theory of general relativity +was groundbreaking. +``` + +> **Link label extraction** +> +> The link label for list items will be inferred in this order (first-match): +> +> 1. `title` attribute value (``) +> 1. Inner text of anchor tag (`label`) +> 1. `id` attribute value, yet without list prefix (``) +> 1. Preceding section heading if `id` is just the list prefix (``) +> 1. Filename if `id` is just the list prefix and there is no preceding section heading. + +#### List Item Grouping + +By default list items will be grouped by section of occurrence using the section heading as a group title. You can generate a flat list and disable grouping (affects any list generated): + +```json +"indexing": { + "groupByHeadingDepth": 0 +} +``` + +>>>>>>> Stashed changes +### List of Figures + +> **Since v3.3.0** + +> **Since v4.1.0** `listOfFigures` annotates Markdown image references with HTML anchors as shown in [Lists](#lists). + +*glossarify-md.conf.json* +```json +"generateFiles": { + "listOfFigures": { "file": "./figures.md", "title": "Figures" } +} +``` + +<<<<<<< Updated upstream +Let's say you have images referenced via Markdown syntax *and* images generated dynamically by an embedded script or some code block being sent to a rendering server (we're using [PlantUML](https://plantuml.com) as an example). `listOfFigures` can only detect Markdown references. You need to explicitely annotate dynamic graphics like in the following input... + +~~~md +Markdown image reference ![Foo](./figure.png) and dynamically +rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +... which will be translated to: + +~~~md +Markdown image reference +![Foo](./figure.png) and dynamically rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +From the anchors sharing the (default) anchor class ***figure*** a common list of figures will be generated. The previous configuration is only a shorthand for this one (since v4.1.0) ... +||||||| merged common ancestors +This option will generate an index file `./figures.md` with a list of figures grouped by sections of occurrence. You can control heading depth for grouping and e.g. generate a flat list without any grouping using +======= +Let's say you have images referenced via Markdown syntax *and* images generated dynamically by an embedded script or some code block being sent to a rendering server (we're using [PlantUML](https://plantuml.com) as an example). `listOfFigures` can only detect Markdown references. You need to explicitely annotate dynamic graphics like in the following input... + +~~~md +Markdown image reference ![Foo](./figure.png) and dynamically +rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +... and `listOfFigures` will prepended a similar anchor to the markdown link: + +~~~md +Markdown image reference +![Foo](./figure.png) and dynamically rendered diagramm annotated explicitely: + +Generated Diagramm + +```plantuml +@startuml +... your PlantUML diagram code ... +@enduml +``` +~~~ + +From the anchors sharing the same (default) anchor class ***figure*** a common list of figures will be generated. The previous [glossarify-md] configuration is only a shorthand for this one (since v4.1.0) ... +>>>>>>> Stashed changes + +*glossarify-md.conf.json* +```json +"generateFiles": { + "listOfFigures": { "class": "figure" }, + "listOf": [ + {"class": "figure", "file": "./figures.md", "title": "Figures" } + ] +} +``` +... which allows to replace the conventional anchor class ***figure*** with a shorter one, e.g. ***fig***. +**Note: this applies to Markdown tables and `listOfTables`, similarily.** + +### List of Tables + +> **Since v3.4.0** + +> **Since v4.1.0** `listOfTables` annotates tables with HTML anchors as shown in [Lists](#lists) using information given in HTML comments as shown below. + +*glossarify-md.conf.json* + +```json +"generateFiles": { + "listOfTables": { "file": "./tables.md", "title": "Tables" } +} +``` +Generates a list of tables into `./tables.md`. Markdown tables have no inherent notion of a table caption. [glossarify-md] scans for two patterns of user-defined table labels and attempts to infer a table label otherwise: + +**1. HTML Comment (invisible):** + +```md + +| Category | Description | Price Avg. | +| -------- | ----------- | ---------- | +| 1 | Video Game | $35.66 | +| 2 | Film | $10.13 | +| 3 | Book | $23.45 | +``` + +**2. Colon-Terminated Emphasized Paragraph Ending (visible):** + +A caption can be inferred from a distinct paragraph... + +```md +[...] which we can see from the average price by article category. + +*Average prices by article category:* + +| Category | Description | Price Avg. | +| -------- | ----------- | ---------- | +| 1 | Video Game | $35.66 | +| 2 | Film | $10.13 | +| 3 | Book | $23.45 | +``` + +... or a colon-terminated emphasized phrase at the end of the preceding paragraph: + +```md +[...] which we can see from the *table of average prices by article category:* + +| Category | Description | Price Avg. | +| -------- | ----------- | ---------- | +| 1 | Video Game | $35.66 | +| 2 | Film | $10.13 | +| 3 | Book | $23.45 | +``` + +Otherwise labels for generated list items will be inferred in this order (first-match): + +1. **HTML comment** in the line above the table +1. **emphasized text** at the end of the preceding paragraph +1. **column headers** separated by comma, e.g. *Category, Description, Price Avg.* +1. **preceding section heading** (tables without column headers) +1. **filename** otherwise. + + +### Sorting your glossaries + +> **Since v3.6.0** + +Add `sort` direction `"asc"` or `"desc"` to glossaries for which you want [glossarify-md] to sort them for you: + +*glossarify-md.conf.json* +```json +"glossaries": [ + { "file":"./glossary.md", "termHint": "", "sort": "asc" } +] +``` + +Internally sorting uses `Intl.Collator` and falls back to `String.localeCompare` if the `Intl` API is missing. You can tweak collation by adding `i18n` options: + +*glossarify-md.conf.json* +```json +"i18n": { + "locale": "de", + "ignorePunctuation": true +}, +"glossaries": [ + ... +] +``` + +The i18n-object is passed *as is* to the collator function. Thus you can use additional options documented on [Mozilla Developer Portal](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Collator): + +### Node Support Matrix + +> **Since v3.0.0** + +The term *support* refers to *runs on the given platform*. Compatibility is maintained with *best effort* and under the terms and conditions of [LICENSE](#license). + +| Node-Version | compatibility & support status | +| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Current | Tested. Should Node introduce breaking changes which affect [glossarify-md], then we may choose to step back from supporting *Current* until it becomes the next LTS. | +| 12.x LTS | Tested + Supported | +| 10.x LTS | Tested + Supported | + +## Options + +#### `help` + +Show all options and default values. + +#### `baseUrl` + +- **Range:** `string` + +URL to prepend to links. Only effective with `linking: "absolute"`. +In most situations, e.g. when hosting markdown files in a repository or +processing markdown files with an MD to HTML converter omitting a pre-defined +`baseUrl` and using `linking: "relative"` is likely to work better. + +#### `baseDir`` + +- **Range:** `string` + +Path to directory where to search for the glossary and markdown files. All paths in a config file except for `$schema` will be relative to *baseDir*. *baseDir* itself and `$schema` are relative to the location of the config file. + +#### `excludeFiles + +- **Range:** `string[]` + +Paths or Glob-Patterns of files to exclude. Use `keepRawFiles` if you just +want to ignore certain markdown files from being modified. + +#### `experimentalFootnotes` + +- **Range:** `boolean` + +Enable support for markdown footnote syntax as defined at . Footnotes will be considered an *experimental* feature until they become official part of the CommonMark Specification at . + +#### `generateFiles.indexFile` + +- **Range:** `{file: string, [title: string]}` +- **Since:** v3.0.0 + +If available, generates an index of glossary terms with links to files in which they have been mentioned. See section [Additional Features](https://github.com/about-code/glossarify-md#index-of-terms-and-where-they-have-been-used) for a configuration example. + +> **Important:** The `string` value range is *deprecated*. It will be kept throughout all versions of v3.x but is eventually going to be removed. Please use the object value range as shown in the example. + +#### `generateFiles.listOfFigures` + +- **Range:** `{file: string, [title: string, class: string]}` +- **Since:** v3.3.0 + +If available, generates a list of figures with links to sections where the figures have been mentioned. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-figures) for a configuration example. + +#### `generateFiles.listOfTables` + +- **Range:** `{file: string, [title: string, class: string]}` +- **Since:** v3.4.0 + +If available, generates a list of tables. See section [Additional Features](https://github.com/about-code/glossarify-md#list-of-tables) for an example. + +#### `generateFiles.listOf` + +- **Range:** `Array<{class: string, file: string, [title: string]}>` +- **Since:** v3.5.0 + +If available, generates a list from HTML anchors exposing the configured `class` attribute. See section [Additional Features](https://github.com/about-code/glossarify-md#lists) for an example. + +#### `glossaries` + +- **Range:** `Array<{file: string, [termHint: string], [sort: string]}>` + +A list of glossary configuations, each with a path to the glossary file. Every +glossary may have an optional *termHint*. A *termHint* is a symbol character +being appended to term occurrences in order to indicate which glossary or +category a term belongs to. A term hint may be any UTF-8 character or character +sequence. If you would like to have the glossary sorted provide a *sort* direction +`"asc"` or `"desc"`. + +#### `ignoreCase` + +- **Range:** `boolean` + +When true any occurrence of a term will be linked no matter how it was spelled. + +#### `includeFiles` + +- **Range:** `string[]` + +Paths or Glob-Patterns for files to include. + +#### `indexing.groupByHeadingDepth` + +- **Range:** `number` in [1-6] +- **Since:** v3.4.0 + +This option affects outputs generated with `generateFiles`. By default when +indexing terms and markdown elements they are being grouped by the heading of +the section they've been found in. In larger books with a lot of sections and +subsections this can lead to *Index* files or *Tables of X* to be generated with +lots of low-level sections and much detail. Yet sometimes it may be preferable +to only list the book chapter or high-level sections which some element has been +found in. This option allows to set the depth by which indexed elements shall be +grouped where `1` refers to chapters (`#` headings). Note that grouping by +high-level sections doesn't mean that only links to the high-level sections are +generated. Where it makes sense links to low-level sections of occurrence are +just being shortened. + +#### `i18n` + +- **Range**:` { locale: string, [localeMatcher: string], + [caseFirst: string], [ignorePunctuation: boolean], + [numeric: boolean], [sensitivity: string], [usage: string] }` + +Locale options to control [sorting](#sorting-your-glossaries). See [`Intl.Collator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator/Collator). + +#### `keepRawFiles` + +- **Range:** `string[]` + +Paths or Glob-Patterns for (markdown) files to copy to `outDir` but ignore in +glossarification and linking. Non-markdown files will always be kept as is so no +need to add those. + +#### `linking` + +- **Range:** `"relative" | "absolute"` + +Whether to create absolute or relative link-urls to the glossary. +The use of `"absolute"` may require a `baseUrl`. + +> **Important:** Using `"absolute"` without a `"baseUrl"` will produce an absolute file system path which you might not want to publish. + +#### `outDir` + +- **Range:** `string` + +The directory where to write output files to. + +> **Important:** using `.` or `./` is going to overwrite your input files. Only do this on a copy of your input +> files or if you are able to roll back any changes or if you know the outcome satisfies your needs. + +The recommendation is to write outputs to a separate directory such as `../out` or `../glossarified`. or `../target`. + +#### `outDirDropOld` + +- **Range:** `boolean` + +If `true` remove old `outDir` before writing a new one, otherwise overwrite files. Drops orphan files that have intentionally been removed from `baseDir`. + +#### `reportNotMentioned` + +- **Range:** `boolean` + +Report on terms which exist in a glossary but have neither been mentioned directly nor with any of its aliases. + +#### Special Thanks go to + +- [John Gruber](https://daringfireball.net/projects/markdown/), author of the Markdown syntax +- [Titus Wormer](https://github.com/wooorm), author of [unifiedjs](https://unifiedjs.com/), [remarkjs](https://github.com/remarkjs) and many more +- and all the other great people publishing modules of value to the tool - directly or transitively. + +## License diff --git a/lib/anchorizer.js b/lib/anchorizer.js new file mode 100644 index 00000000..e5f5b9e5 --- /dev/null +++ b/lib/anchorizer.js @@ -0,0 +1,100 @@ +const GitHubSlugger = require("github-slugger"); +const uVisit = require("unist-util-visit"); +const {html} = require("mdast-builder"); +const {getNodeText, getTableHeaders, getLastChildByType, isHtmlComment} = require("./ast/tools"); +const api = {}; +/** + * Linker operates on the abstract syntax tree for a markdown file + * and searches for occurrences of a glossary term. + * + * @private + * @param {{context: Context}} opts + */ +api.anchorizer = function(args) { + const {context} = args; + const {listOf, listOfFigures, listOfTables} = context.opts.generateFiles; + if (listOf.length > 0) { + // assumes that listOfFigures and listOfTables configs have been + // pushed to listOf configs during context initialization. + const figuresClass = listOfFigures ? listOfFigures.class : "figure"; + const tablesClass = listOfTables ? listOfTables.class : "table"; + return (tree, vFile) => { + const slugger = new GitHubSlugger(); + uVisit(tree, getNodeVisitor(context, vFile, slugger, figuresClass, tablesClass)); + return tree; + }; + } else { + return (tree) => tree; + } +}; + +function getNodeVisitor(context, file, slugger, figuresClass, tablesClass) { + return function(node, index, parent) { + const t = node.type; + if (t === "image" || t === "imageReference") { + return anchorizeImage(node, index, parent, slugger, figuresClass); + } else if (t === "table") { + return anchorizeTable(node, index, parent, slugger, tablesClass); + } + }; +} + +function anchorizeImage(node, index, parent, slugger, classifier) { + // Note: The file-specific slugger internally counts figures with id "figure". + const t = node.type; + const id = slugger.slug(node.title || node.alt || "figure"); + let title = ""; + if (t === "image") { + title = node.alt || node.title || node.url; + } else if (t === "imageReference") { + title = node.alt || node.label; + } + parent.children.splice(index, 0, + html(``), + html("\n") + ); + return index + 3; +} + +function anchorizeTable(node, index, parent, slugger, classifier) { + const label = getTableLabel(node, index, parent); + const id = label ? slugger.slug(label) : ""; + parent.children.splice(index, 0, + html(``) + ); + return index + 2; +} + +const TABLE_LABEL_REGEXP = //; +const TABLE_LABEL_REGEXP2 = /(.*):(\s|\n|$)/; +function getTableLabel(node, index, parent) { + let label = ""; + let predecessor = parent.children[index - 1]; + const fromHtmlComment = isHtmlComment(predecessor); + const fromParagraph = getLastChildByType("emphasis", predecessor); + + if (fromHtmlComment) { + // Try infer label from html annotation comment + const matches = predecessor.value.match(TABLE_LABEL_REGEXP); + if (matches && matches.length > 1) { + label = matches[1]; + } + } else if (fromParagraph) { + // Try infer label from preceding paragraph (must end with an *emphasis*) + const matches = getNodeText(fromParagraph).match(TABLE_LABEL_REGEXP2); + if (matches && matches.length > 1) { + label = matches[1]; + } + } + + if (! label) { + // Try constructing a table label from table headings + label = getTableHeaders(node) + .filter(text => !!text) + .join(", "); + } + return label; +} + + +module.exports = api; diff --git a/lib/ast/tools.js b/lib/ast/tools.js index e944d627..6480980e 100644 --- a/lib/ast/tools.js +++ b/lib/ast/tools.js @@ -21,9 +21,9 @@ api.getHtmlNodeInnerText = function getHtmlNodeInnerText(htmlNode, parent) { const children = parent.children; let isHtml = false; return children.reduce((prev, currNode) => { - if (currNode === htmlNode) { + if (isHtmlOpenTag(currNode) && !isHtmlClosedTag(currNode)) { isHtml = true; - } else if (isHtml && currNode.type === "html") { + } else if (isHtmlClosingTag(currNode)) { isHtml = false; } else if (isHtml && currNode.type !== "html") { return prev + api.getNodeText(currNode); @@ -33,6 +33,29 @@ api.getHtmlNodeInnerText = function getHtmlNodeInnerText(htmlNode, parent) { } }; +function isHtmlOpenTag(node) { + if (node.type !== "html") { return false; } + const openTag = "<"; + return node.value[0] === openTag; +} + +function isHtmlClosedTag(node) { + if (node.type !== "html") { return false; } + const closedComment = "-->"; + const closedTag = "/>"; + const value = node.value; + return ( + value.substr(-closedComment.length) === closedComment || + value.substr(-closedTag.length) === closedTag + ); +} +function isHtmlClosingTag(node) { + if (node.type !== "html") { return false; } + const closeTag = ""; }; + +api.getLastChildByType = function getLastChildByType(type, node) { + if (type && node && node.children) { + const c = node.children; + const last = c[c.length - 1]; + return last.type === type ? last : null; + } +}; + /** * Helper function for debugging purposes. */ diff --git a/lib/index/figures.js b/lib/index/figures.js deleted file mode 100644 index 60f47e2d..00000000 --- a/lib/index/figures.js +++ /dev/null @@ -1,149 +0,0 @@ -const {root, paragraph, text, heading, brk, link, list, listItem } = require("mdast-builder"); - -const {getFileLinkUrl} = require("../path/tools"); -const {getLinkUrl, getNodeText} = require("../ast/tools"); -const {getIndex, getIndexValues: getValues, group, byGroupHeading} = require("../indexer"); - -const api = {}; - -/** - * @typedef { import('./model/context') } Context - * @typedef { import('./indexer').IndexEntry } IndexEntry - * @typedef { import('./indexer').Index } Index - */ - -api.indices = [ - { - id: "index/figures/nodeType/image" - ,filterFn: (indexEntry) => { - const t = indexEntry.node.type; - return t === "image" || t === "imageReference"; - } - ,keyFn: (indexEntry) => indexEntry.node.type - } - ,{ - id: "index/figures/nodeType/definition" - ,filterFn: (indexEntry) => indexEntry.node.type === "definition" - ,keyFn: (indexEntry) => `${indexEntry.file}#${indexEntry.node.identifier}` - } -]; - -/** - * Returns the markdown abstract syntax tree that is to be written to the file - * configured via 'generateFiles.indexFile' config. - * - * @param {Context} context - * @returns {Node} mdast tree - */ -api.getAST = function(context) { - const {generateFiles, indexing} = context.opts; - const {groupByHeadingDepth} = indexing; - const {title} = generateFiles.listOfFigures; - const figures = selectFiguresFromIndex(context); - - let tree = [ - heading(1, text(title || "Figures")) - ]; - if (! groupByHeadingDepth || groupByHeadingDepth < 0) { - tree.push(getListOfFiguresAst(context, figures)); - } else { - tree.push(getFiguresBySectionAst(context, figures)); - } - return root(tree); -}; - -/** - * @param {Context} context - * @param {IndexEntry[]} figures - */ -function getFiguresBySectionAst(context, figures) { - return paragraph( - group(figures, byGroupHeading).map((figures) => { - const groupHeadingNode = figures[0].groupHeadingNode; - if (! groupHeadingNode) { - return paragraph([ - getListOfFiguresAst(context, figures) - ,brk - ]); - } else { - return paragraph([ - brk - ,heading(groupHeadingNode.depth + 1, // [1] - text(getNodeText(groupHeadingNode)) - ) - ,brk - ,brk - ,getListOfFiguresAst(context, figures) - ,brk - ]); - } - }) - ); - /** - * Implementation Notes: - * - * [1] add +1 to depth of headings referred to in order to keep - * the title of the generated file the only depth-1 heading - */ -} - -/** - * @param {Context} context - * @param {IndexEntry[]} figures - * @returns {Node} mdast tree - */ -function getListOfFiguresAst(context, figures) { - return list( - "ordered" - ,figures - .sort((entry1, entry2) => entry1.id - entry2.id) - .map((indexEntry) => getListOfFiguresItemAst(context, indexEntry)) - ); -} - -/** - * @param {Context} context - * @param {IndexEntry} indexEntry - * @returns {Node} mdast tree - */ -function getListOfFiguresItemAst(context, indexEntry) { - const {listOfFigures} = context.opts.generateFiles; - const {file: listOfFiguresFile} = listOfFigures; - - return listItem([ - link( - getFileLinkUrl(context, listOfFiguresFile, indexEntry.file, getLinkUrl(indexEntry.headingNode)) - ,indexEntry.node.title - ,text(indexEntry.node.alt) - ) - ]); -} - -/** - * @returns {IndexEntry[]} index entries for node types "image" and "imageReference" - */ -function selectFiguresFromIndex() { - const images = getValues("index/figures/nodeType/image", "image"); - const imageRefs = getValues("index/figures/nodeType/image", "imageReference"); - const defIndex = getIndex("index/figures/nodeType/definition"); - let figures = [ - ...images - ,...imageRefs.map((indexEntry) => { - // dereference - const refFile = indexEntry.file; - const refNode = indexEntry.node; - const defId = `${refFile}#${refNode.identifier}`; - const defNode = defIndex[defId][0].node; - indexEntry.node = { - ...indexEntry.node - , type: "image" - , url: defNode.url - , title : defNode.title - }; - return indexEntry; - }) - ]; - return figures; -} - -module.exports = api; diff --git a/lib/index/tables.js b/lib/index/tables.js deleted file mode 100644 index 8069f57c..00000000 --- a/lib/index/tables.js +++ /dev/null @@ -1,224 +0,0 @@ -const {root, paragraph, text, heading, brk, link, list, listItem } = require("mdast-builder"); -const {getFileLinkUrl} = require("../path/tools"); -const {getLinkUrl, getNodeText, getTableHeaders} = require("../ast/tools"); -const {getIndex, group, byGroupHeading} = require("../indexer"); - -const api = {}; -const TABLE_LABEL_REGEXP = //; -const TABLE_LABEL_REGEXP2 = /(.*):(\s|\n|$)/; - -/** - * @typedef { import('./model/context') } Context - * @typedef { import('./indexer').IndexEntry } IndexEntry - * @typedef { import('./indexer').Index } Index - */ - -api.indices = [ - { - id: "index/tables" - ,filterFn: (indexEntry) => { - const node = indexEntry.node; - if (node.type === "table") { - return true; - } else if (node.type === "html" && node.value.match(TABLE_LABEL_REGEXP)) { - return true; - } else if (node.type === "emphasis" && getNodeText(node.children[0]).match(TABLE_LABEL_REGEXP2)) { - return true; - } - } - ,keyFn: (indexEntry) => { - const file = indexEntry.file; - const node = indexEntry.node; - if (node.type === "table") { - return `${file}#${node.position.start.line}`; - } else if (node.type === "html") { - return `${file}#${node.position.start.line + 1}`; - } else if (node.type === "emphasis") { - return `${file}#${node.position.start.line + 2}`; - } - // Implementation Note: - // In order to identify a descriptive label for a markdown table, we - // attempt to group the table node with descriptive nodes by projecting - // the line numbers of descriptive nodes onto the line number where - // we *assume* the actual table node to be (+1 line or +2 lines below) - // - // However, this is not guaranteed to always produce groups with a - // table. For example we might find an emphasis node not followed by - // a table at all. Then we have a group without a table. Those groups - // must be filtered and ignored when processing the index. - } - } -]; - -/** - * Returns the markdown abstract syntax tree that is to be written to the file - * configured via 'generateFiles.listOfTables' config. - * - * Given, documents satisfy a particular syntax, then descriptive labels for - * (syntactically) anonymous tables will be inferred as follows: - * - * #### Syntax 1: Using a descriptive html comment invisible in rendered output - * - * ``` - * - * | Article ID | Description | Price | - * | ---------- | ----------- | ------ | - * | 12345678 | Football | $44.50 | - * ``` - * - * #### Syntax 2: Using colon-terminated, emphasized paragraph visible in rendered output - * - * ``` - * This is a preceding paragraph just being there to highlight that the actual - * table label must be surrounded by newlines and be a distinct paragraph. - * - * *Articles:* - * - * | Article ID | Description | Price | - * | ---------- | ----------- | ------ | - * | 12345678 | Football | $44.50 | - * ``` - * - * @param {Context} context - * @returns {Node} mdast tree - */ -api.getAST = function(context) { - const {generateFiles, indexing} = context.opts; - const {groupByHeadingDepth} = indexing; - const {title} = generateFiles.listOfTables; - const tables = selectTablesFromIndex(context); - - let tree = [ - heading(1, text(title || "Tables")) - ]; - if (! groupByHeadingDepth || groupByHeadingDepth < 0) { - tree.push(getListOfTablesAst(context, tables)); - } else { - tree.push(getTablesBySectionAst(context, tables)); - } - return root(tree); -}; - -/** - * @param {Context} context - * @param {IndexEntry[]} tables - */ -function getTablesBySectionAst(context, tables) { - return paragraph( - group(tables, byGroupHeading).map((tables) => { - const groupHeadingNode = tables[0].groupHeadingNode; - if (! groupHeadingNode) { - return paragraph([ - getListOfTablesAst(context, tables) - ,brk - ]); - } else { - return paragraph([ - brk - ,heading(groupHeadingNode.depth + 1, // [1] - text(getNodeText(groupHeadingNode)) - ) - ,brk - ,brk - ,getListOfTablesAst(context, tables) - ,brk - ]); - } - }) - ); - /** - * Implementation Notes: - * - * [1] add +1 to depth of headings referred to in order to keep - * the title of the generated file the only depth-1 heading - */ -} - -/** - * @param {Context} context - * @param {IndexEntry[]} tables - * @returns {Node} mdast tree - */ -function getListOfTablesAst(context, tables) { - return list( - "ordered" - ,tables - .sort((entry1, entry2) => entry1.id - entry2.id) - .map((indexEntry) => getListOfTablesItemAst(context, indexEntry)) - ); -} - -/** - * @param {Context} context - * @param {IndexEntry} indexEntry - * @returns {Node} mdast tree - */ -function getListOfTablesItemAst(context, indexEntry) { - const {listOfTables} = context.opts.generateFiles; - const {file: listOfTablesFile} = listOfTables; - - return listItem([ - link( - getFileLinkUrl(context, listOfTablesFile, indexEntry.file, getLinkUrl(indexEntry.headingNode)) - ,indexEntry.description - ,text(indexEntry.description) - ) - ]); -} - -/** - * @returns {IndexEntry[]} index entries for node types "table" - */ -function selectTablesFromIndex() { - const tableEntries = getIndex("index/tables"); - let tables = [ - ...Object - .keys(tableEntries) - .filter(key => tableEntries[key].find(entry => entry.node.type === "table")) // [1] - .map(key => mergeTableWithLabel(tableEntries[key])) - ]; - return tables; - - // Implementation Notes: - // [1] See implementation note for the index key function, above. -} - -function mergeTableWithLabel(indexEntries) { - const htmlEntry = indexEntries.filter(x => x.node.type === "html")[0]; - const textEntry = indexEntries.filter(x => x.node.type === "emphasis")[0]; - const tableEntry = indexEntries.filter(x => x.node.type === "table")[0]; - let label = ""; - if (htmlEntry) { - // Take table label from html annotation comment - const matches = htmlEntry.node.value.match(TABLE_LABEL_REGEXP); - if (matches.length > 1) { - label = matches[1]; - } - } else if (textEntry) { - // Take table label from preceding paragraph - const matches = getNodeText(textEntry.node).match(TABLE_LABEL_REGEXP2); - if (matches.length > 1) { - label = matches[1]; - } - } - if (! label) { - // Try constructing a table label from table headings - label = getTableHeaders(tableEntry.node) - .filter(text => !!text) - .join(", "); - } - if (! label) { - // Use section heading to label the table - label = getNodeText(tableEntry.headingNode); - } - if (! label) { - // Use file name if none of previous attempts succeeded - label = `${tableEntry.file}`; - } - return { - ...tableEntry - , description: label - }; -} - -module.exports = api; diff --git a/lib/main.js b/lib/main.js index dadbaece..9d218b4d 100644 --- a/lib/main.js +++ b/lib/main.js @@ -19,8 +19,6 @@ function run(opts) { .all([ writer.writeOutput(context) ,writer.writeIndex(context) - ,writer.writeListOfFigures(context) - ,writer.writeListOfTables(context) ,writer.writeListsOfAny(context) ]) .then(() => context) @@ -76,6 +74,17 @@ function prepare(context) { if (! opts.generateFiles ) { opts.generateFiles = {}; } + if (! opts.generateFiles.listOf) { + opts.generateFiles.listOf = []; + } + if (opts.generateFiles.listOfFigures) { + opts.generateFiles.listOfFigures = Object.assign({ class: "figure", title: "Figures"}, opts.generateFiles.listOfFigures); + opts.generateFiles.listOf.push(opts.generateFiles.listOfFigures); + } + if (opts.generateFiles.listOfTables) { + opts.generateFiles.listOfTables = Object.assign({ class: "table", title: "Tables"}, opts.generateFiles.listOfTables); + opts.generateFiles.listOf.push(opts.generateFiles.listOfTables); + } if (! opts.glossaries ) { opts.glossaries = {}; } diff --git a/lib/reader.js b/lib/reader.js index 37da3fea..89d8efde 100644 --- a/lib/reader.js +++ b/lib/reader.js @@ -12,10 +12,9 @@ const remark_footnotes = require("remark-footnotes"); // Our plugins const {withTocInstruction} = require("./ast/with/toc-instruction"); const {counter} = require("./counter"); +const {anchorizer} = require("./anchorizer"); const {indexer} = require("./indexer"); const {indices: termIndices} = require("./index/terms"); -const {indices: imgIndices} = require("./index/figures"); -const {indices: tableIndices} = require("./index/tables"); const {indices: anyCssClassIndices} = require("./index/any"); const {linker} = require("./linker"); const {sorter} = require("./sorter"); @@ -118,6 +117,7 @@ api.readDocumentFiles = function(context) { processor: unified() .use(remark_parse) // parser .use(remark_stringify) // compiler + .use(anchorizer, { context }) .use(withTocInstruction) .use(printAst, { match: dev.printInputAst }) // Might be regex. /.*\/table\.md/g; .use(sorter, { context }) @@ -130,8 +130,6 @@ api.readDocumentFiles = function(context) { context: context ,indices: [ ...termIndices - ,...imgIndices - ,...tableIndices ,...anyCssClassIndices ] }) diff --git a/lib/writer.js b/lib/writer.js index 5f728717..d18948d9 100644 --- a/lib/writer.js +++ b/lib/writer.js @@ -11,8 +11,6 @@ const remark_stringify = require("remark-stringify"); const {toSystemSlash} = require("./path/tools"); const {getAST: getIndexerAST} = require("./index/terms"); -const {getAST: getListOfFiguresAST} = require("./index/figures"); -const {getAST: getListOfTablesAST} = require("./index/tables"); const {getAST: getListOfAnyAST} = require("./index/any"); /** * @typedef {import("./model/context")} Context @@ -97,34 +95,17 @@ api.writeIndex = function(context) { } }; -api.writeListOfFigures = function(context) { - const {generateFiles} = context.opts; - const {listOfFigures} = generateFiles; - if (! listOfFigures) { - return Promise.resolve(context); - } else if (typeof listOfFigures === "object") { - return this.writeMarkdownFile(context, getListOfFiguresAST(context), listOfFigures.file); - } -}; - -api.writeListOfTables = function(context) { - const {generateFiles} = context.opts; - const {listOfTables} = generateFiles; - if (! listOfTables) { - return Promise.resolve(context); - } else if (typeof listOfTables === "object") { - return this.writeMarkdownFile(context, getListOfTablesAST(context), listOfTables.file); - } -}; - api.writeListsOfAny = function(context) { const {listOf} = context.opts.generateFiles; if (Array.isArray(listOf)) { return Promise - .all(listOf.map((opts) => { - const mdAst = getListOfAnyAST(context, opts); - return this.writeMarkdownFile(context, mdAst, opts.file); - })) + .all(listOf + .filter(opts => opts.file) + .map((opts) => { + const mdAst = getListOfAnyAST(context, opts); + return this.writeMarkdownFile(context, mdAst, opts.file); + }) + ) .then(() => context); } else { return Promise.resolve(context); diff --git a/test/input/config-listOfFigures/image-reference/document.md b/test/input/config-listOfFigures/image-reference/document.md new file mode 100644 index 00000000..81d49f82 --- /dev/null +++ b/test/input/config-listOfFigures/image-reference/document.md @@ -0,0 +1,35 @@ +# Testing option generateFiles.listOfFigures + +## Image Reference Without Caption + +![ref1] + +GIVEN a config option `generateFiles.listOfFigures` +AND a document with + +- a section *Image Reference* +- AND a reference `![ref1]` +- AND a definition `[ref1]: ../figure1.png` + +THEN the reference MUST be correctly detected as an image +AND in the generated list of figures there MUST be a link *ref1* +AND the link must refer to section `./document.md#image-reference-without-caption` + +[ref1]: ./figure.png + +## Image Reference With Caption + +![Test Figure][ref2] + +GIVEN a config option `generateFiles.listOfFigures` +AND a document with + +- a section *Image Reference* +- AND a reference `![Test Figure][ref2]` +- AND a definition `[ref2]: ../figure1.png` + +THEN the reference MUST be correctly detected as an image +AND in the generated list of figures there MUST be a link *Test Figure* +AND the link must refer to section `./document.md#image-reference-with-caption` + +[ref2]: ./figure.png diff --git a/test/input/config-listOfFigures/image-reference/figure.png b/test/input/config-listOfFigures/image-reference/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/input/config-listOfFigures/image-reference/figure.png differ diff --git a/test/input/config-listOfFigures/image-reference/glossarify-md.conf.json b/test/input/config-listOfFigures/image-reference/glossarify-md.conf.json new file mode 100644 index 00000000..37cb1e36 --- /dev/null +++ b/test/input/config-listOfFigures/image-reference/glossarify-md.conf.json @@ -0,0 +1,20 @@ +{ + "$schema": "../../../../conf.schema.json", + "baseDir": ".", + "linking": "relative", + "includeFiles": ["."], + "excludeFiles": [], + "generateFiles": { + "listOfFigures": { "file": "./figures.md" } + }, + "glossaries": [ + { "file": "./glossary.md"} + ], + "ignoreCase": false, + "outDir": "../../../output-actual/config-listOfFigures/image-reference", + "dev": { + "printInputAst": false, + "reproducablePaths": true, + "printOutputAst": false + } +} diff --git a/test/input/config-listOfFigures/image-reference/glossary.md b/test/input/config-listOfFigures/image-reference/glossary.md new file mode 100644 index 00000000..ca3c8276 --- /dev/null +++ b/test/input/config-listOfFigures/image-reference/glossary.md @@ -0,0 +1 @@ +# Glossary diff --git a/test/input/config-listOfFigures/option-title-missing/document.md b/test/input/config-listOfFigures/option-title-missing/document.md index be9e494b..8897f2ac 100644 --- a/test/input/config-listOfFigures/option-title-missing/document.md +++ b/test/input/config-listOfFigures/option-title-missing/document.md @@ -5,4 +5,4 @@ AND config `generateFiles.listOfFigures.title` is `undefined` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the default title MUST be "Figures". -![Figure 1 depth 1](./figure1.png) +![Figure 1 depth 1](./figure.png) diff --git a/test/input/config-listOfFigures/option-title-missing/figure.png b/test/input/config-listOfFigures/option-title-missing/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/input/config-listOfFigures/option-title-missing/figure.png differ diff --git a/test/input/config-listOfFigures/with-listof-combined/document.md b/test/input/config-listOfFigures/with-listof-combined/document.md new file mode 100644 index 00000000..02ef5e04 --- /dev/null +++ b/test/input/config-listOfFigures/with-listof-combined/document.md @@ -0,0 +1,14 @@ +# Testing option generateFiles.listOfFigures + +## Section with image detected by listOfFigures + +![Test image](./figure.png) + +## Section with image anchor detected by listOf + + +~~~ +@startuml +Assume some generated PlantUML graphic here. +@enduml +~~~ diff --git a/test/input/config-listOfFigures/with-listof-combined/figure.png b/test/input/config-listOfFigures/with-listof-combined/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/input/config-listOfFigures/with-listof-combined/figure.png differ diff --git a/test/input/config-listOfFigures/with-listof-combined/glossarify-md.conf.json b/test/input/config-listOfFigures/with-listof-combined/glossarify-md.conf.json new file mode 100644 index 00000000..03474cab --- /dev/null +++ b/test/input/config-listOfFigures/with-listof-combined/glossarify-md.conf.json @@ -0,0 +1,23 @@ +{ + "$schema": "../../../../conf.schema.json", + "baseDir": ".", + "linking": "relative", + "includeFiles": ["."], + "excludeFiles": [], + "generateFiles": { + "listOfFigures": { "class": "my-figures" }, + "listOf":[ + { "class": "my-figures", "file": "./figures-combined.md", "title": "Combined List of Figures" } + ] + }, + "glossaries": [ + { "file": "./glossary.md"} + ], + "ignoreCase": false, + "outDir": "../../../output-actual/config-listOfFigures/with-listof-combined", + "dev": { + "printInputAst": false, + "reproducablePaths": true, + "printOutputAst": false + } +} diff --git a/test/input/config-listOfFigures/with-listof-combined/glossary.md b/test/input/config-listOfFigures/with-listof-combined/glossary.md new file mode 100644 index 00000000..ca3c8276 --- /dev/null +++ b/test/input/config-listOfFigures/with-listof-combined/glossary.md @@ -0,0 +1 @@ +# Glossary diff --git a/test/input/config-listOfTables/table-anchor-ids/table-anchor-ids.md b/test/input/config-listOfTables/table-anchor-ids/table-anchor-ids.md new file mode 100644 index 00000000..ee0a6db4 --- /dev/null +++ b/test/input/config-listOfTables/table-anchor-ids/table-anchor-ids.md @@ -0,0 +1,40 @@ +# Unique Anchor IDs + +### Test Case: Unique anchor ids when generated + +GIVEN two tables without a caption AND same columns +THEN unique anchor ids must be generated. + +Table 1: + +| Column1_Ambiguous | Column2_Ambiguous | +| ----------------- | ----------------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + + +Table 2: + +| Column1_Ambiguous | Column2_Ambiguous | +| ----------------- | ----------------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + + +### Test Case: Unique anchor ids when labels are ambiguous + +GIVEN two tables with identical captions +THEN unique anchor ids must be generated. + + +| Column1 | Column2 | +| -------- | -------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + + + +| Column1 | Column2 | +| -------- | -------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | diff --git a/test/input/config-listOfTables/table-label-text/table-label-text.md b/test/input/config-listOfTables/table-label-text/table-label-text.md index e4949144..6af616bd 100644 --- a/test/input/config-listOfTables/table-label-text/table-label-text.md +++ b/test/input/config-listOfTables/table-label-text/table-label-text.md @@ -56,7 +56,7 @@ THEN in the generated output file the table label MUST equal 'Column 1, Column 2 Paragraph with *invalid inline label missing the terminating colon* -| Column 1 | Column 2 | Column 3 | +| Column A | Column B | Column C | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | | Col1Row4 | Col2Row4 | Col3Row4 | diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-0/document-figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-0/document-figures.md index e4b3efff..fb555e8c 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-0/document-figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-0/document-figures.md @@ -5,38 +5,47 @@ AND config `indexing.groupByHeadingDepth === 0` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the generated file MUST be a flat list of figures. + ![Figure 1 depth 1][1] ## [Heading 2 Depth 2](#heading-2-depth-2) + ![Figure 2 depth 2][2] ### [Heading 3 Depth 3](#heading-3-depth-3) + ![Figure 3 depth 3][3] #### [Heading 4 Depth 4](#heading-4-depth-4) + ![Figure 4 depth 4][4] ### [Heading 5 Depth 3](#heading-5-depth-3) + ![Figure 5 depth 3][5] ## [Heading 6 Depth 2](#heading-6-depth-2) + ![Figure 6 depth 2][6] ### [Heading 7 Depth 3](#heading-7-depth-3) + ![Figure 7 depth 3][7] ###### [Heading 8 Depth 6](#heading-8-depth-6) + ![Figure 8 depth 6][8] ###### [Heading 9 Depth 2](#heading-9-depth-2) + ![Figure 9 depth 2][9] [1]: ./figure1.png diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-0/figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-0/figures.md index b6ed5121..f26412e6 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-0/figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-0/figures.md @@ -10,20 +10,20 @@ 8. [Figure 8 depth 6][8] 9. [Figure 9 depth 2][9] -[1]: ./document-figures.md#testing-option-generatefileslistoffigures +[1]: ./document-figures.md#figure-1-depth-1 "Figure 1 depth 1" -[2]: ./document-figures.md#heading-2-depth-2 +[2]: ./document-figures.md#figure-2-depth-2 "Figure 2 depth 2" -[3]: ./document-figures.md#heading-3-depth-3 +[3]: ./document-figures.md#figure-3-depth-3 "Figure 3 depth 3" -[4]: ./document-figures.md#heading-4-depth-4 +[4]: ./document-figures.md#figure-4-depth-4 "Figure 4 depth 4" -[5]: ./document-figures.md#heading-5-depth-3 +[5]: ./document-figures.md#figure-5-depth-3 "Figure 5 depth 3" -[6]: ./document-figures.md#heading-6-depth-2 +[6]: ./document-figures.md#figure-6-depth-2 "Figure 6 depth 2" -[7]: ./document-figures.md#heading-7-depth-3 +[7]: ./document-figures.md#figure-7-depth-3 "Figure 7 depth 3" -[8]: ./document-figures.md#heading-8-depth-6 +[8]: ./document-figures.md#figure-8-depth-6 "Figure 8 depth 6" -[9]: ./document-figures.md#heading-9-depth-2 +[9]: ./document-figures.md#figure-9-depth-2 "Figure 9 depth 2" diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-1/document-figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-1/document-figures.md index c1c4d894..56e9fecc 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-1/document-figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-1/document-figures.md @@ -5,38 +5,47 @@ AND config `indexing.groupByHeadingDepth === 1` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the generated file MUST be a flat list of figures. + ![Figure 1 depth 1][1] ## [Heading 2 Depth 2](#heading-2-depth-2) + ![Figure 2 depth 2][2] ### [Heading 3 Depth 3](#heading-3-depth-3) + ![Figure 3 depth 3][3] #### [Heading 4 Depth 4](#heading-4-depth-4) + ![Figure 4 depth 4][4] ### [Heading 5 Depth 3](#heading-5-depth-3) + ![Figure 5 depth 3][5] ## [Heading 6 Depth 2](#heading-6-depth-2) + ![Figure 6 depth 2][6] ### [Heading 7 Depth 3](#heading-7-depth-3) + ![Figure 7 depth 3][7] ###### [Heading 8 Depth 6](#heading-8-depth-6) + ![Figure 8 depth 6][8] ###### [Heading 9 Depth 2](#heading-9-depth-2) + ![Figure 9 depth 2][9] [1]: ./figure1.png diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-1/figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-1/figures.md index 4341a8be..6efdf0e3 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-1/figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-1/figures.md @@ -14,20 +14,20 @@ 9. [Figure 9 depth 2][9] -[1]: ./document-figures.md#testing-option-generatefileslistoffigures +[1]: ./document-figures.md#figure-1-depth-1 "Figure 1 depth 1" -[2]: ./document-figures.md#heading-2-depth-2 +[2]: ./document-figures.md#figure-2-depth-2 "Figure 2 depth 2" -[3]: ./document-figures.md#heading-3-depth-3 +[3]: ./document-figures.md#figure-3-depth-3 "Figure 3 depth 3" -[4]: ./document-figures.md#heading-4-depth-4 +[4]: ./document-figures.md#figure-4-depth-4 "Figure 4 depth 4" -[5]: ./document-figures.md#heading-5-depth-3 +[5]: ./document-figures.md#figure-5-depth-3 "Figure 5 depth 3" -[6]: ./document-figures.md#heading-6-depth-2 +[6]: ./document-figures.md#figure-6-depth-2 "Figure 6 depth 2" -[7]: ./document-figures.md#heading-7-depth-3 +[7]: ./document-figures.md#figure-7-depth-3 "Figure 7 depth 3" -[8]: ./document-figures.md#heading-8-depth-6 +[8]: ./document-figures.md#figure-8-depth-6 "Figure 8 depth 6" -[9]: ./document-figures.md#heading-9-depth-2 +[9]: ./document-figures.md#figure-9-depth-2 "Figure 9 depth 2" diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-2/document-figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-2/document-figures.md index 1fdf5828..b4713403 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-2/document-figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-2/document-figures.md @@ -5,38 +5,47 @@ AND config `indexing.groupByHeadingDepth === 2` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the generated file MUST be a flat list of figures. + ![Figure 1 depth 1][1] ## [Heading 2 Depth 2](#heading-2-depth-2) + ![Figure 2 depth 2][2] ### [Heading 3 Depth 3](#heading-3-depth-3) + ![Figure 3 depth 3][3] #### [Heading 4 Depth 4](#heading-4-depth-4) + ![Figure 4 depth 4][4] ### [Heading 5 Depth 3](#heading-5-depth-3) + ![Figure 5 depth 3][5] ## [Heading 6 Depth 2](#heading-6-depth-2) + ![Figure 6 depth 2][6] ### [Heading 7 Depth 3](#heading-7-depth-3) + ![Figure 7 depth 3][7] ###### [Heading 8 Depth 6](#heading-8-depth-6) + ![Figure 8 depth 6][8] ###### [Heading 9 Depth 2](#heading-9-depth-2) + ![Figure 9 depth 2][9] [1]: ./figure1.png diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-2/figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-2/figures.md index 123fde57..73b6f319 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-2/figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-2/figures.md @@ -20,20 +20,20 @@ 4. [Figure 9 depth 2][9] -[1]: ./document-figures.md#testing-option-generatefileslistoffigures +[1]: ./document-figures.md#figure-1-depth-1 "Figure 1 depth 1" -[2]: ./document-figures.md#heading-2-depth-2 +[2]: ./document-figures.md#figure-2-depth-2 "Figure 2 depth 2" -[3]: ./document-figures.md#heading-3-depth-3 +[3]: ./document-figures.md#figure-3-depth-3 "Figure 3 depth 3" -[4]: ./document-figures.md#heading-4-depth-4 +[4]: ./document-figures.md#figure-4-depth-4 "Figure 4 depth 4" -[5]: ./document-figures.md#heading-5-depth-3 +[5]: ./document-figures.md#figure-5-depth-3 "Figure 5 depth 3" -[6]: ./document-figures.md#heading-6-depth-2 +[6]: ./document-figures.md#figure-6-depth-2 "Figure 6 depth 2" -[7]: ./document-figures.md#heading-7-depth-3 +[7]: ./document-figures.md#figure-7-depth-3 "Figure 7 depth 3" -[8]: ./document-figures.md#heading-8-depth-6 +[8]: ./document-figures.md#figure-8-depth-6 "Figure 8 depth 6" -[9]: ./document-figures.md#heading-9-depth-2 +[9]: ./document-figures.md#figure-9-depth-2 "Figure 9 depth 2" diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-missing/document-figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-missing/document-figures.md index 00376c32..02368137 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-missing/document-figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-missing/document-figures.md @@ -5,38 +5,47 @@ AND config `indexing === undefined` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the generated file MUST be a flat list of figures. + ![Figure 1 depth 1][1] ## [Heading 2 Depth 2](#heading-2-depth-2) + ![Figure 2 depth 2][2] ### [Heading 3 Depth 3](#heading-3-depth-3) + ![Figure 3 depth 3][3] #### [Heading 4 Depth 4](#heading-4-depth-4) + ![Figure 4 depth 4][4] ### [Heading 5 Depth 3](#heading-5-depth-3) + ![Figure 5 depth 3][5] ## [Heading 6 Depth 2](#heading-6-depth-2) + ![Figure 6 depth 2][6] ### [Heading 7 Depth 3](#heading-7-depth-3) + ![Figure 7 depth 3][7] ###### [Heading 8 Depth 6](#heading-8-depth-6) + ![Figure 8 depth 6][8] ###### [Heading 9 Depth 2](#heading-9-depth-2) + ![Figure 9 depth 2][9] [1]: ./figure1.png diff --git a/test/output-expected/config-indexing/groupByHeadingDepth-missing/figures.md b/test/output-expected/config-indexing/groupByHeadingDepth-missing/figures.md index b039490f..d135aa55 100644 --- a/test/output-expected/config-indexing/groupByHeadingDepth-missing/figures.md +++ b/test/output-expected/config-indexing/groupByHeadingDepth-missing/figures.md @@ -38,20 +38,20 @@ 1. [Figure 9 depth 2][9] -[1]: ./document-figures.md#document-with-figure +[1]: ./document-figures.md#figure-1-depth-1 "Figure 1 depth 1" -[2]: ./document-figures.md#heading-2-depth-2 +[2]: ./document-figures.md#figure-2-depth-2 "Figure 2 depth 2" -[3]: ./document-figures.md#heading-3-depth-3 +[3]: ./document-figures.md#figure-3-depth-3 "Figure 3 depth 3" -[4]: ./document-figures.md#heading-4-depth-4 +[4]: ./document-figures.md#figure-4-depth-4 "Figure 4 depth 4" -[5]: ./document-figures.md#heading-5-depth-3 +[5]: ./document-figures.md#figure-5-depth-3 "Figure 5 depth 3" -[6]: ./document-figures.md#heading-6-depth-2 +[6]: ./document-figures.md#figure-6-depth-2 "Figure 6 depth 2" -[7]: ./document-figures.md#heading-7-depth-3 +[7]: ./document-figures.md#figure-7-depth-3 "Figure 7 depth 3" -[8]: ./document-figures.md#heading-8-depth-6 +[8]: ./document-figures.md#figure-8-depth-6 "Figure 8 depth 6" -[9]: ./document-figures.md#heading-9-depth-2 +[9]: ./document-figures.md#figure-9-depth-2 "Figure 9 depth 2" diff --git a/test/output-expected/config-listOfFigures/image-reference/document.md b/test/output-expected/config-listOfFigures/image-reference/document.md new file mode 100644 index 00000000..30266752 --- /dev/null +++ b/test/output-expected/config-listOfFigures/image-reference/document.md @@ -0,0 +1,37 @@ +# [Testing option generateFiles.listOfFigures](#testing-option-generatefileslistoffigures) + +## [Image Reference Without Caption](#image-reference-without-caption) + + +![ref1] + +GIVEN a config option `generateFiles.listOfFigures` +AND a document with + +- a section _Image Reference_ +- AND a reference `![ref1]` +- AND a definition `[ref1]: ../figure1.png` + +THEN the reference MUST be correctly detected as an image +AND in the generated list of figures there MUST be a link _ref1_ +AND the link must refer to section `./document.md#image-reference-without-caption` + +[ref1]: ./figure.png + +## [Image Reference With Caption](#image-reference-with-caption) + + +![Test Figure][ref2] + +GIVEN a config option `generateFiles.listOfFigures` +AND a document with + +- a section _Image Reference_ +- AND a reference `![Test Figure][ref2]` +- AND a definition `[ref2]: ../figure1.png` + +THEN the reference MUST be correctly detected as an image +AND in the generated list of figures there MUST be a link _Test Figure_ +AND the link must refer to section `./document.md#image-reference-with-caption` + +[ref2]: ./figure.png diff --git a/test/output-expected/config-listOfFigures/image-reference/figure.png b/test/output-expected/config-listOfFigures/image-reference/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/output-expected/config-listOfFigures/image-reference/figure.png differ diff --git a/test/output-expected/config-listOfFigures/image-reference/figures.md b/test/output-expected/config-listOfFigures/image-reference/figures.md new file mode 100644 index 00000000..7edd60c6 --- /dev/null +++ b/test/output-expected/config-listOfFigures/image-reference/figures.md @@ -0,0 +1,15 @@ +# [Figures](#figures) + + +### [Image Reference With Caption](#image-reference-with-caption) + +1. [Test Figure][1] + +### [Image Reference Without Caption](#image-reference-without-caption) + +1. [ref1][2] + + +[1]: ./document.md#test-figure "Test Figure" + +[2]: ./document.md#ref1 "ref1" diff --git a/test/output-expected/config-listOfFigures/image-reference/glossarify-md.conf.json b/test/output-expected/config-listOfFigures/image-reference/glossarify-md.conf.json new file mode 100644 index 00000000..37cb1e36 --- /dev/null +++ b/test/output-expected/config-listOfFigures/image-reference/glossarify-md.conf.json @@ -0,0 +1,20 @@ +{ + "$schema": "../../../../conf.schema.json", + "baseDir": ".", + "linking": "relative", + "includeFiles": ["."], + "excludeFiles": [], + "generateFiles": { + "listOfFigures": { "file": "./figures.md" } + }, + "glossaries": [ + { "file": "./glossary.md"} + ], + "ignoreCase": false, + "outDir": "../../../output-actual/config-listOfFigures/image-reference", + "dev": { + "printInputAst": false, + "reproducablePaths": true, + "printOutputAst": false + } +} diff --git a/test/output-expected/config-listOfFigures/image-reference/glossary.md b/test/output-expected/config-listOfFigures/image-reference/glossary.md new file mode 100644 index 00000000..44b53ccf --- /dev/null +++ b/test/output-expected/config-listOfFigures/image-reference/glossary.md @@ -0,0 +1 @@ +# [Glossary](#glossary) diff --git a/test/output-expected/config-listOfFigures/option-title-missing/document.md b/test/output-expected/config-listOfFigures/option-title-missing/document.md index 54f51b26..1ac3b3cc 100644 --- a/test/output-expected/config-listOfFigures/option-title-missing/document.md +++ b/test/output-expected/config-listOfFigures/option-title-missing/document.md @@ -5,6 +5,7 @@ AND config `generateFiles.listOfFigures.title` is `undefined` THEN a file `generateFiles.listOfFigures.file` MUST be generated successfully AND the default title MUST be "Figures". + ![Figure 1 depth 1][1] -[1]: ./figure1.png +[1]: ./figure.png diff --git a/test/output-expected/config-listOfFigures/option-title-missing/figure.png b/test/output-expected/config-listOfFigures/option-title-missing/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/output-expected/config-listOfFigures/option-title-missing/figure.png differ diff --git a/test/output-expected/config-listOfFigures/option-title-missing/figures.md b/test/output-expected/config-listOfFigures/option-title-missing/figures.md index 9090d953..80ed58d8 100644 --- a/test/output-expected/config-listOfFigures/option-title-missing/figures.md +++ b/test/output-expected/config-listOfFigures/option-title-missing/figures.md @@ -6,4 +6,4 @@ 1. [Figure 1 depth 1][1] -[1]: ./document.md#testing-option-generatefileslistoffigures +[1]: ./document.md#figure-1-depth-1 "Figure 1 depth 1" diff --git a/test/output-expected/config-listOfFigures/with-listof-combined/document.md b/test/output-expected/config-listOfFigures/with-listof-combined/document.md new file mode 100644 index 00000000..7cd2b048 --- /dev/null +++ b/test/output-expected/config-listOfFigures/with-listof-combined/document.md @@ -0,0 +1,16 @@ +# [Testing option generateFiles.listOfFigures](#testing-option-generatefileslistoffigures) + +## [Section with image detected by listOfFigures](#section-with-image-detected-by-listoffigures) + + +![Test image][1] + +## [Section with image anchor detected by listOf](#section-with-image-anchor-detected-by-listof) + + + + @startuml + Assume some generated PlantUML graphic here. + @enduml + +[1]: ./figure.png diff --git a/test/output-expected/config-listOfFigures/with-listof-combined/figure.png b/test/output-expected/config-listOfFigures/with-listof-combined/figure.png new file mode 100644 index 00000000..42c24da1 Binary files /dev/null and b/test/output-expected/config-listOfFigures/with-listof-combined/figure.png differ diff --git a/test/output-expected/config-listOfFigures/with-listof-combined/figures-combined.md b/test/output-expected/config-listOfFigures/with-listof-combined/figures-combined.md new file mode 100644 index 00000000..6ab31aa4 --- /dev/null +++ b/test/output-expected/config-listOfFigures/with-listof-combined/figures-combined.md @@ -0,0 +1,15 @@ +# [Combined List of Figures](#combined-list-of-figures) + + +### [Section with image detected by listOfFigures](#section-with-image-detected-by-listoffigures) + +1. [Test image][1] + +### [Section with image anchor detected by listOf](#section-with-image-anchor-detected-by-listof) + +1. [Invisible image of foo][2] + + +[1]: ./document.md#test-image "Test image" + +[2]: ./document.md#foo "Invisible image of foo" diff --git a/test/output-expected/config-listOfFigures/with-listof-combined/glossarify-md.conf.json b/test/output-expected/config-listOfFigures/with-listof-combined/glossarify-md.conf.json new file mode 100644 index 00000000..03474cab --- /dev/null +++ b/test/output-expected/config-listOfFigures/with-listof-combined/glossarify-md.conf.json @@ -0,0 +1,23 @@ +{ + "$schema": "../../../../conf.schema.json", + "baseDir": ".", + "linking": "relative", + "includeFiles": ["."], + "excludeFiles": [], + "generateFiles": { + "listOfFigures": { "class": "my-figures" }, + "listOf":[ + { "class": "my-figures", "file": "./figures-combined.md", "title": "Combined List of Figures" } + ] + }, + "glossaries": [ + { "file": "./glossary.md"} + ], + "ignoreCase": false, + "outDir": "../../../output-actual/config-listOfFigures/with-listof-combined", + "dev": { + "printInputAst": false, + "reproducablePaths": true, + "printOutputAst": false + } +} diff --git a/test/output-expected/config-listOfFigures/with-listof-combined/glossary.md b/test/output-expected/config-listOfFigures/with-listof-combined/glossary.md new file mode 100644 index 00000000..44b53ccf --- /dev/null +++ b/test/output-expected/config-listOfFigures/with-listof-combined/glossary.md @@ -0,0 +1 @@ +# [Glossary](#glossary) diff --git a/test/output-expected/config-listOfTables/table-anchor-ids/table-anchor-ids.md b/test/output-expected/config-listOfTables/table-anchor-ids/table-anchor-ids.md new file mode 100644 index 00000000..81c6f509 --- /dev/null +++ b/test/output-expected/config-listOfTables/table-anchor-ids/table-anchor-ids.md @@ -0,0 +1,47 @@ +# [Unique Anchor IDs](#unique-anchor-ids) + +### [Test Case: Unique anchor ids when generated](#test-case-unique-anchor-ids-when-generated) + +GIVEN two tables without a caption AND same columns +THEN unique anchor ids must be generated. + +Table 1: + + + +| Column1_Ambiguous | Column2_Ambiguous | +| ----------------- | ----------------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + +Table 2: + + + +| Column1_Ambiguous | Column2_Ambiguous | +| ----------------- | ----------------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + +### [Test Case: Unique anchor ids when labels are ambiguous](#test-case-unique-anchor-ids-when-labels-are-ambiguous) + +GIVEN two tables with identical captions +THEN unique anchor ids must be generated. + + + + + +| Column1 | Column2 | +| -------- | -------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | + + + + + +| Column1 | Column2 | +| -------- | -------- | +| Col1Row1 | Col2Row1 | +| Col1Row2 | Col2Row2 | diff --git a/test/output-expected/config-listOfTables/table-label-comment/table-label-comment.md b/test/output-expected/config-listOfTables/table-label-comment/table-label-comment.md index 1c5fa8b0..0605a184 100644 --- a/test/output-expected/config-listOfTables/table-label-comment/table-label-comment.md +++ b/test/output-expected/config-listOfTables/table-label-comment/table-label-comment.md @@ -10,6 +10,8 @@ AND the link text MUST be "Label from Comment". + + | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | @@ -26,6 +28,8 @@ AND the link text MUST equal 'Column 1, Column 2, Column 3'. + + | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | diff --git a/test/output-expected/config-listOfTables/table-label-file/table-label-file.md b/test/output-expected/config-listOfTables/table-label-file/table-label-file.md index ded58a0d..04d42428 100644 --- a/test/output-expected/config-listOfTables/table-label-file/table-label-file.md +++ b/test/output-expected/config-listOfTables/table-label-file/table-label-file.md @@ -8,11 +8,15 @@ AND no section heading exists THEN in the generated output file the table MUST be linked to this section AND the link text MUST equal './table-label-file/table-label-file.md' + + | | | | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | | Col1Row4 | Col2Row4 | Col3Row4 | + + | | | | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | diff --git a/test/output-expected/config-listOfTables/table-label-heading/table-label-heading.md b/test/output-expected/config-listOfTables/table-label-heading/table-label-heading.md index 077d4a5b..13507bf2 100644 --- a/test/output-expected/config-listOfTables/table-label-heading/table-label-heading.md +++ b/test/output-expected/config-listOfTables/table-label-heading/table-label-heading.md @@ -8,6 +8,8 @@ WHEN the table's first row is all empty AND no user-defined label exists THEN in the generated output file the table MUST be linked to this section AND the link text MUST equal its preceding heading 'Label from Section Heading'. + + | | | | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | diff --git a/test/output-expected/config-listOfTables/table-label-text/table-label-text.md b/test/output-expected/config-listOfTables/table-label-text/table-label-text.md index 666cab3f..6f3e23a6 100644 --- a/test/output-expected/config-listOfTables/table-label-text/table-label-text.md +++ b/test/output-expected/config-listOfTables/table-label-text/table-label-text.md @@ -10,6 +10,8 @@ AND not terminated by a colon. _Label from paragraph:_ + + | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | @@ -24,6 +26,8 @@ THEN in the generated output file the table label MUST equal 'Column 1, Column 2 _Label from paragraph_ + + | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | @@ -39,6 +43,8 @@ AND not terminated by a colon. Paragraph with _Label from inlined text:_ + + | Column 1 | Column 2 | Column 3 | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | @@ -54,7 +60,9 @@ THEN in the generated output file the table label MUST equal 'Column 1, Column 2 Paragraph with _invalid inline label missing the terminating colon_ -| Column 1 | Column 2 | Column 3 | + + +| Column A | Column B | Column C | | -------- | -------- | -------- | | Col1Row3 | Col2Row3 | Col3Row3 | | Col1Row4 | Col2Row4 | Col3Row4 | diff --git a/test/output-expected/config-listOfTables/tables.md b/test/output-expected/config-listOfTables/tables.md index f8bb49bd..35c4924c 100644 --- a/test/output-expected/config-listOfTables/tables.md +++ b/test/output-expected/config-listOfTables/tables.md @@ -1,37 +1,52 @@ # [List of Tables](#list-of-tables) +## [Unique Anchor IDs](#unique-anchor-ids) + +1. [Column1_Ambiguous, Column2_Ambiguous][1] +2. [Column1_Ambiguous, Column2_Ambiguous][2] +3. [Ambiguous][3] +4. [Ambiguous][4] + ## [User-Defined Invisible Table Label Comments](#user-defined-invisible-table-label-comments) -1. [Label from Comment][1] -2. [Column 1, Column 2, Column 3][2] -1. [table-label-file/table-label-file.md][3] -2. [table-label-file/table-label-file.md][3] +1. [Label from Comment][5] +2. [Column 1, Column 2, Column 3][6] +1. [table-label-file/table-label-file.md][7] +2. [table-label-file/table-label-file.md][7] ## [Inferred Table Label from Section Heading](#inferred-table-label-from-section-heading) -1. [Label from Section Heading][4] +1. [Label from Section Heading][8] ## [User-Defined Visible Table Labels](#user-defined-visible-table-labels) -1. [Label from paragraph][5] -2. [Column 1, Column 2, Column 3][6] -3. [Label from inlined text][7] -4. [Column 1, Column 2, Column 3][8] +1. [Label from paragraph][9] +2. [Column 1, Column 2, Column 3][10] +3. [Label from inlined text][11] +4. [Column A, Column B, Column C][12] + + +[1]: ./table-anchor-ids/table-anchor-ids.md#column1_ambiguous-column2_ambiguous "Column1_Ambiguous, Column2_Ambiguous" + +[2]: ./table-anchor-ids/table-anchor-ids.md#column1_ambiguous-column2_ambiguous-1 "Column1_Ambiguous, Column2_Ambiguous" + +[3]: ./table-anchor-ids/table-anchor-ids.md#ambiguous "Ambiguous" +[4]: ./table-anchor-ids/table-anchor-ids.md#ambiguous-1 "Ambiguous" -[1]: ./table-label-comment/table-label-comment.md#test-case-comment-pattern-matches "Label from Comment" +[5]: ./table-label-comment/table-label-comment.md#label-from-comment "Label from Comment" -[2]: ./table-label-comment/table-label-comment.md#test-case-comment-pattern-misses-table "Column 1, Column 2, Column 3" +[6]: ./table-label-comment/table-label-comment.md#column-1-column-2-column-3 "Column 1, Column 2, Column 3" -[3]: ./table-label-file/table-label-file.md "table-label-file/table-label-file.md" +[7]: ./table-label-file/table-label-file.md "table-label-file/table-label-file.md" -[4]: ./table-label-heading/table-label-heading.md#label-from-section-heading "Label from Section Heading" +[8]: ./table-label-heading/table-label-heading.md#label-from-section-heading "Label from Section Heading" -[5]: ./table-label-text/table-label-text.md#test-case-separate-paragraph-match "Label from paragraph" +[9]: ./table-label-text/table-label-text.md#label-from-paragraph "Label from paragraph" -[6]: ./table-label-text/table-label-text.md#test-case-separate-paragraph-colon-missing "Column 1, Column 2, Column 3" +[10]: ./table-label-text/table-label-text.md#column-1-column-2-column-3 "Column 1, Column 2, Column 3" -[7]: ./table-label-text/table-label-text.md#test-case-inline-match "Label from inlined text" +[11]: ./table-label-text/table-label-text.md#label-from-inlined-text "Label from inlined text" -[8]: ./table-label-text/table-label-text.md#test-case-inline-colon-is-missing "Column 1, Column 2, Column 3" +[12]: ./table-label-text/table-label-text.md#column-a-column-b-column-c "Column A, Column B, Column C" diff --git a/test/package.json b/test/package.json index 7d61e605..4ba689f7 100644 --- a/test/package.json +++ b/test/package.json @@ -16,6 +16,7 @@ "test-win": "npm run suite", "test": "npm run suite", "suite": "npm-run-all test_*", + "at": "npm-run-all", "test_00": "node ./conf.spec.js", "test_01": "node ./path-tools.spec.js", "test_02": "npx . --config ./input/markdown/glossarify-md.conf.json", @@ -51,10 +52,13 @@ "test_32": "npx . --config ./input/config-indexing/groupByHeadingDepth-1/glossarify-md.conf.json", "test_33": "npx . --config ./input/config-indexing/groupByHeadingDepth-2/glossarify-md.conf.json", "test_34": "npx . --config ./input/config-listOfFigures/option-title-missing/glossarify-md.conf.json", - "test_35": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json", - "test_36": "npx . --config ./input/config-listOf/glossarify-md.conf.json", - "test_37": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json", + "test_35": "npx . --config ./input/config-listOfFigures/image-reference/glossarify-md.conf.json", + "test_36": "npx . --config ./input/config-listOfFigures/with-listof-combined/glossarify-md.conf.json", + "test_37": "npx . --config ./input/config-listOfTables/glossarify-md.conf.json", + "test_38": "npx . --config ./input/config-listOf/glossarify-md.conf.json", + "test_39": "npx . --config ./input/config-indexFile/issue-75-formatted-headings/glossarify-md.conf.json", "postsuite": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js", + "postat": "git diff --minimal --color --no-index --ignore-cr-at-eol ./output-expected ./output-actual | node ../bin/test.js", "new-baseline": "rm -r ./output-expected && mv ./output-actual ./output-expected", "new-baseline-win": "del /Q .\\output-expected && rename .\\output-actual .\\output-expected", "commit-baseline": "npm test && git reset && git add './package.json' './input' './output-expected' && git commit -m 'test: New baseline.'"