eleventy-plugin-asciidoc 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.cjs ADDED
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ["xo-space", "plugin:prettier/recommended"],
4
+ plugins: ["prettier"],
5
+ rules: {
6
+ "prettier/prettier": "error",
7
+ },
8
+ env: {
9
+ browser: true,
10
+ },
11
+ };
package/README.md CHANGED
@@ -35,7 +35,7 @@ module.exports = function (eleventyConfig) {
35
35
  };
36
36
  ```
37
37
 
38
- ### Front Matter
38
+ ## Front Matter
39
39
 
40
40
  You can use either [Eleventy style front matter](https://www.11ty.dev/docs/data-frontmatter/#front-matter-formats) or AsciiDoc document attributes to write front matter.
41
41
 
@@ -68,7 +68,7 @@ Hello everyone!
68
68
  > [!WARNING]
69
69
  > Asciidoctor.js converts all attribute names to lower case letters. Example `:eleventy-aTitle:` will be made available as `atitle` in front matter data (also as `eleventy-atitle` in document attributes).
70
70
 
71
- #### Data Cascade
71
+ ### Data Cascade
72
72
 
73
73
  Data specified using AsciiDoc style front matter override YAML (or front matter in other Eleventy supported formats).
74
74
 
@@ -87,9 +87,36 @@ In the above case, front matter data will have `{ layout: layout-b.njk }`.
87
87
 
88
88
  In the case of `title`, [the AsciiDoc document title](https://docs.asciidoctor.org/asciidoc/latest/document/title/) (including `title` and `doctitle` attributes) takes precedence over front matter.
89
89
 
90
- ### Customize with Options
90
+ ## Options
91
+
92
+ You can pass options as the second argument in `addPlugin()`.
93
+
94
+ ### Options for this plugin
95
+
96
+ #### `eleventyAttributesPrefix`
97
+
98
+ Default value is `eleventy-`.
99
+
100
+ This config can be used to change the prefix string for [AsciiDoc style front matter](#front-matter).
101
+
102
+ #### `resolveDocumentTitle`
103
+
104
+ Default value is `false`.
105
+
106
+ If enabled, the title will be resolved from the heading of the first section in the document. Otherwise, the title will be the Level 0 heading.
107
+
108
+ ```adoc
109
+ == A second level heading
110
+
111
+ This text is written in AsciiDoc format.
112
+ ```
113
+
114
+ With `resolveDocumentTitle: true`, the above document will have a title (in page data). `A second level heading`.
115
+
116
+ ### Options for Asciidoctor.js
117
+
118
+ All properties other than [the ones specific to the plugin](#options-for-this-plugin) will be passed to Asciidoctor.js.
91
119
 
92
- You can pass options to `convert()` of Asciidoctor.js as second argument in `addPlugin()`.
93
120
  These are the [available options](https://docs.asciidoctor.org/asciidoctor.js/latest/processor/convert-options/).
94
121
 
95
122
  ```js
@@ -144,12 +171,6 @@ module.exports = function (eleventyConfig) {
144
171
 
145
172
  Refer to [Asciidoctor.js documentation](https://docs.asciidoctor.org/asciidoctor.js/latest/extend/extensions/) to know more about extensions.
146
173
 
147
- #### `eleventyAttributesPrefix`
148
-
149
- Default value is `eleventy-`.
150
-
151
- This config can be used to change the prefix string for [AsciiDoc style front matter](#front-matter).
152
-
153
174
  ### CSS Styles
154
175
 
155
176
  The plugin does not include any CSS styles. It is up to you to style the content.
package/index.js CHANGED
@@ -1,35 +1,24 @@
1
1
  // @ts-check
2
- const eleventyAsciidoc = require("./lib/eleventy-asciidoc.js");
3
- const pkg = require("./package.json");
2
+ import eleventyAsciidoc from "./lib/eleventy-asciidoc.js";
4
3
 
5
4
  /** @typedef {import('./lib/eleventy-asciidoc.js').EleventyAsciidocOptions} EleventyAsciidocOptions} */
6
5
 
7
- module.exports = {
8
- /**
9
- * Plugin config function
10
- *
11
- * @param {object} eleventyConfig The eleventy configuration object
12
- * @param {EleventyAsciidocOptions} converterOptions Options for Asciidoctor.converter()
13
- */
14
- configFunction(eleventyConfig, converterOptions) {
15
- try {
16
- eleventyConfig.versionCheck(pkg["11ty"].compatibility);
17
- } catch (e) {
18
- console.log(
19
- `WARN: Eleventy Plugin (${pkg.name}) Compatibility: ${e.message}`,
20
- );
21
- }
22
-
23
- if (converterOptions?.extension_registry !== undefined) {
24
- console.log(
25
- `WARN: 'extension_registry' doesn't work well with Asciidoctor.js v3+. Use 'configure_extension_registry'.`,
26
- );
27
- }
28
-
29
- eleventyConfig.addTemplateFormats(["adoc", "asciidoc", "ad"]);
30
- eleventyConfig.addExtension(
31
- ["adoc", "asciidoc", "ad"],
32
- eleventyAsciidoc(converterOptions),
6
+ /**
7
+ * Plugin config function
8
+ *
9
+ * @param {object} eleventyConfig The eleventy configuration object
10
+ * @param {EleventyAsciidocOptions} converterOptions Options for Asciidoctor.converter()
11
+ */
12
+ export default function config(eleventyConfig, converterOptions) {
13
+ if (converterOptions?.extension_registry !== undefined) {
14
+ console.log(
15
+ `WARN: 'extension_registry' doesn't work well with Asciidoctor.js v3+. Use 'configure_extension_registry'.`,
33
16
  );
34
- },
35
- };
17
+ }
18
+
19
+ eleventyConfig.addTemplateFormats(["adoc", "asciidoc", "ad"]);
20
+ eleventyConfig.addExtension(
21
+ ["adoc", "asciidoc", "ad"],
22
+ eleventyAsciidoc(converterOptions),
23
+ );
24
+ }
package/lefthook.yml ADDED
@@ -0,0 +1,16 @@
1
+ pre-commit:
2
+ commands:
3
+ # Prettier for JS is included in ESlint
4
+ prettier:
5
+ glob: "*.{md,json}"
6
+ run: npx prettier --write {staged_files}
7
+ stage_fixed: true
8
+
9
+ eslint:
10
+ glob: "*.{js,mjs,cjs}"
11
+ run: npx eslint --fix {staged_files}
12
+ stage_fixed: true
13
+
14
+ tests:
15
+ glob: "*.{js,mjs,cjs}"
16
+ run: npm run test
@@ -1,35 +1,55 @@
1
1
  // @ts-check
2
2
  /* eslint camelcase: ["error", {allow: ["base_dir", "extension_registry", "configure_extension_registry"]}] */
3
3
 
4
- const asciidoctor = require("@asciidoctor/core");
5
- const debug = require("debug")("eleventy-plugin-asciidoc");
6
- const fs = require("fs");
7
- const matter = require("gray-matter");
8
- const path = require("path");
9
- const nunjucks = require("nunjucks");
10
- const { parseDocumentAttributes } = require("./utils/asciidoc.js");
11
- const { pickByKeyPrefix, mapKeys, pick } = require("./utils/object.js");
12
-
13
- // @ts-ignore
14
- const processor = asciidoctor();
4
+ import { load, Extensions, convert } from "@asciidoctor/core";
5
+ import libDebug from "debug";
6
+ import fs from "node:fs/promises";
7
+ import matter from "gray-matter";
8
+ import path from "path";
9
+ import nunjucks from "nunjucks";
10
+ import { parseDocumentAttributes } from "./utils/asciidoc.js";
11
+ import { pickByKeyPrefix, mapKeys, pick } from "./utils/object.js";
12
+
13
+ const debug = libDebug("eleventy-plugin-asciidoc");
15
14
 
16
15
  /** @typedef {import('gray-matter').GrayMatterFile} GrayMatterFile */
17
16
 
18
17
  /**
19
18
  * @typedef {Object} ExtraProcessorOptions
20
19
  * @property {string=} eleventyAttributesPrefix
20
+ * @property {Boolean} [resolveDocumentTitle=false]
21
21
  * @typedef {import('@asciidoctor/core').ProcessorOptions & ExtraProcessorOptions} EleventyAsciidocOptions
22
22
  */
23
23
 
24
24
  /**
25
- * Reads a file synchronously.
25
+ * Reads files and separates front matter and content asynchronously.
26
26
  *
27
- * @param {string} inputPath The input path
28
- * @return {GrayMatterFile}
27
+ * @param {string} inputPath Path to file
28
+ * @return {Promise<GrayMatterFile>}
29
+ */
30
+ async function readFileAsync(inputPath) {
31
+ try {
32
+ const fileContent = await fs.readFile(inputPath);
33
+ return matter(fileContent);
34
+ } catch (e) {
35
+ throw new Error(`Unable to read path. ${e.error}`);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Gets the title from ascii document document.
41
+ *
42
+ * @param {object} document The document
43
+ * @param {boolean} [resolve=false] The resolve
44
+ * @return {string | undefined} The title of the document.
29
45
  */
30
- const readFileSync = (inputPath) => {
31
- return matter(fs.readFileSync(inputPath, "utf8"));
32
- };
46
+ function getTitleFromAsciiDocDocument(document, resolve = false) {
47
+ if (resolve) {
48
+ return document.getDocumentTitle();
49
+ }
50
+
51
+ return document.getHeader()?.title;
52
+ }
33
53
 
34
54
  /** @typedef {(inputPath: string) => Object.<string, any>} GetDataFn
35
55
  * Gets front-matter data from the file synchronously
@@ -42,46 +62,54 @@ const readFileSync = (inputPath) => {
42
62
  * @return {GetDataFn}
43
63
  */
44
64
 
45
- const generateGetDataFromInputPath = (converterOptions) => (inputPath) => {
46
- const { content } = readFileSync(inputPath);
47
- const { eleventyAttributesPrefix = "eleventy-" } = converterOptions;
48
-
49
- const doc = processor.load(content, {
50
- ...converterOptions,
51
- base_dir: getBaseDir(inputPath, converterOptions.base_dir),
52
- });
53
-
54
- const title = doc.getDocumentTitle();
55
- const attributes = doc.getAttributes();
56
-
57
- let eleventyAttributes = pickByKeyPrefix(
58
- attributes,
59
- eleventyAttributesPrefix,
60
- );
61
- eleventyAttributes = mapKeys(eleventyAttributes, (k) =>
62
- k.slice(eleventyAttributesPrefix.length),
63
- );
64
-
65
- debug(`Document title ${title}`);
66
- debug(`Document attributes: ${JSON.stringify(attributes)}`);
67
- debug(`Document Eleventy attributes: ${JSON.stringify(eleventyAttributes)}`);
68
-
69
- let data = {
70
- asciidocAttributes: attributes,
71
- ...eleventyAttributes,
72
- // Pass title only if defined. Otherwise, `undefined`
73
- // will override the title in `eleventyAttributes`
74
- ...(title === undefined ? {} : { title }),
75
- };
65
+ const generateGetDataFromInputPath =
66
+ (converterOptions) => async (inputPath) => {
67
+ const { content } = await readFileAsync(inputPath);
68
+ const {
69
+ eleventyAttributesPrefix = "eleventy-",
70
+ resolveDocumentTitle = false,
71
+ ...restOfConverterOptions
72
+ } = converterOptions;
73
+
74
+ const doc = await load(content, {
75
+ ...restOfConverterOptions,
76
+ base_dir: getBaseDir(inputPath, restOfConverterOptions.base_dir),
77
+ });
78
+
79
+ const title = getTitleFromAsciiDocDocument(doc, resolveDocumentTitle);
80
+
81
+ const attributes = doc.getAttributes();
82
+
83
+ let eleventyAttributes = pickByKeyPrefix(
84
+ attributes,
85
+ eleventyAttributesPrefix,
86
+ );
87
+ eleventyAttributes = mapKeys(eleventyAttributes, (k) =>
88
+ k.slice(eleventyAttributesPrefix.length),
89
+ );
90
+
91
+ debug(`Document title ${title}`);
92
+ debug(`Document attributes: ${JSON.stringify(attributes)}`);
93
+ debug(
94
+ `Document Eleventy attributes: ${JSON.stringify(eleventyAttributes)}`,
95
+ );
96
+
97
+ let data = {
98
+ asciidocAttributes: attributes,
99
+ ...eleventyAttributes,
100
+ // Pass title only if defined. Otherwise, `undefined`
101
+ // will override the title in `eleventyAttributes`
102
+ ...(title === undefined ? {} : { title }),
103
+ };
76
104
 
77
- // Removes undefined values
78
- // that may override Eleventy page data.
79
- data = pick(data, (k, v) => v !== undefined);
105
+ // Removes undefined values
106
+ // that may override Eleventy page data.
107
+ data = pick(data, (k, v) => v !== undefined);
80
108
 
81
- return {
82
- data,
109
+ return {
110
+ data,
111
+ };
83
112
  };
84
- };
85
113
 
86
114
  /**
87
115
  * Gets the base directory if available, otherwise from input path
@@ -107,9 +135,9 @@ function eleventyAsciidoctor(convertOptions = {}) {
107
135
  ...convertOptions,
108
136
  };
109
137
 
110
- const compile = (_contents, inputPath) => (data) => {
138
+ const compile = (_contents, inputPath) => async (data) => {
111
139
  debug(`Reading ${inputPath}`);
112
- const { content } = readFileSync(inputPath);
140
+ const { content } = await readFileAsync(inputPath);
113
141
 
114
142
  let { base_dir, configure_extension_registry } = options;
115
143
  const attributes = parseDocumentAttributes(options.attributes ?? {});
@@ -145,11 +173,11 @@ function eleventyAsciidoctor(convertOptions = {}) {
145
173
  let registry;
146
174
  if (typeof configure_extension_registry === "function") {
147
175
  debug(`Creating an extension registry`);
148
- registry = processor.Extensions.create();
176
+ registry = Extensions.create();
149
177
  configure_extension_registry(registry);
150
178
  }
151
179
 
152
- return processor.convert(content, {
180
+ return convert(content, {
153
181
  ...converterOptions,
154
182
  extension_registry: registry,
155
183
  });
@@ -181,4 +209,4 @@ function eleventyAsciidoctor(convertOptions = {}) {
181
209
  };
182
210
  }
183
211
 
184
- module.exports = eleventyAsciidoctor;
212
+ export default eleventyAsciidoctor;
@@ -8,7 +8,7 @@
8
8
  * @param {Attributes | string[] | string} attrs AsciiDoc Document Attributes
9
9
  * @return {Attributes} Attributes as Object
10
10
  */
11
- function parseDocumentAttributes(attrs) {
11
+ export function parseDocumentAttributes(attrs) {
12
12
  if (Array.isArray(attrs)) {
13
13
  return Object.fromEntries(attrs.map((a) => a.split("=")));
14
14
  }
@@ -19,7 +19,3 @@ function parseDocumentAttributes(attrs) {
19
19
 
20
20
  return attrs;
21
21
  }
22
-
23
- module.exports = {
24
- parseDocumentAttributes,
25
- };
@@ -7,7 +7,7 @@
7
7
  * @param {(key: string, value: any, obj: object ) => boolean | Array<string>} keys The keys
8
8
  * @return {object} Copy of the object with filtered values
9
9
  */
10
- function pick(obj, keys = (_k, v) => Boolean(v)) {
10
+ export function pick(obj, keys = (_k, v) => Boolean(v)) {
11
11
  if (Array.isArray(keys)) {
12
12
  return pick(obj, (key) => keys.includes(key));
13
13
  }
@@ -31,7 +31,7 @@ function pick(obj, keys = (_k, v) => Boolean(v)) {
31
31
  * @param {string} prefix The key prefix
32
32
  * @return {object} Copy of the object with filtered values
33
33
  */
34
- function pickByKeyPrefix(obj, prefix) {
34
+ export function pickByKeyPrefix(obj, prefix) {
35
35
  return pick(obj, (k) => k.startsWith(prefix));
36
36
  }
37
37
 
@@ -42,7 +42,7 @@ function pickByKeyPrefix(obj, prefix) {
42
42
  * @param {(k: string, v: any)=> string} [mapKey=(k)=>k] The function to map the keys
43
43
  * @return {object} { Copy of the object with mapped keys }
44
44
  */
45
- function mapKeys(obj, mapKey = (k) => k) {
45
+ export function mapKeys(obj, mapKey = (k) => k) {
46
46
  return Object.entries(obj).reduce((acc, [k, v]) => {
47
47
  const newKey = mapKey(k, v);
48
48
  return {
@@ -51,9 +51,3 @@ function mapKeys(obj, mapKey = (k) => k) {
51
51
  };
52
52
  }, {});
53
53
  }
54
-
55
- module.exports = {
56
- pickByKeyPrefix,
57
- pick,
58
- mapKeys,
59
- };
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "eleventy-plugin-asciidoc",
3
- "version": "5.0.1",
3
+ "version": "6.0.0",
4
4
  "description": "Adds support for AsciiDoc to Eleventy",
5
5
  "main": "index.js",
6
+ "type": "module",
6
7
  "funding": "https://github.com/sponsors/saneef/",
7
8
  "repository": {
8
9
  "type": "git",
@@ -10,8 +11,7 @@
10
11
  },
11
12
  "scripts": {
12
13
  "lint": "eslint lib/**.js tests/**.js",
13
- "test": "nyc ava -v --color",
14
- "prepare": "husky install"
14
+ "test": "ava -v --color"
15
15
  },
16
16
  "keywords": [
17
17
  "asciidoc",
@@ -22,31 +22,22 @@
22
22
  ],
23
23
  "author": "Saneef Ansari <hello@saneef.com> (https://saneef.com/)",
24
24
  "license": "MIT",
25
- "11ty": {
26
- "compatibility": ">=2.0.0-canary.19"
27
- },
28
25
  "dependencies": {
29
- "@asciidoctor/core": "^3.0.4",
30
- "debug": "^4.4.0",
26
+ "@asciidoctor/core": "^4.0.0",
27
+ "debug": "^4.4.3",
31
28
  "gray-matter": "^4.0.3",
32
29
  "nunjucks": "^3.2.4"
33
30
  },
34
31
  "devDependencies": {
35
- "@11ty/eleventy": "^3.0.0",
36
- "ava": "^6.2.0",
32
+ "@11ty/eleventy": "^3.1.6",
33
+ "ava": "^8.0.1",
37
34
  "eslint": "^8.56.0",
38
- "eslint-config-prettier": "^10.0.1",
35
+ "eslint-config-prettier": "^10.1.8",
39
36
  "eslint-config-xo-space": "^0.35.0",
40
- "eslint-plugin-prettier": "^5.2.3",
41
- "husky": "^9.1.7",
42
- "lint-staged": "^15.4.3",
43
- "nyc": "^17.1.0",
44
- "prettier": "^3.5.2",
45
- "rimraf": "^6.0.1"
46
- },
47
- "lint-staged": {
48
- "*.{js,mjs,cjs}": "eslint --cache --fix",
49
- "*.{js,md,json}": "prettier --write"
37
+ "eslint-plugin-prettier": "^5.5.6",
38
+ "lefthook": "^2.1.9",
39
+ "prettier": "^3.9.4",
40
+ "rimraf": "^6.1.3"
50
41
  },
51
42
  "ava": {
52
43
  "files": [