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 = "";
+ return node.value.substr(0, closeTag.length) === closeTag;
+}
+
+
/**
* Return the URL of a link node or the first found 'link'-type child node.
*/
@@ -68,6 +91,15 @@ api.isHtmlComment = function isHtmlComment(node) {
&& node.value.substr(-3) === "-->";
};
+
+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.'"