@asciidoctor/core 4.0.0-alpha.2 → 4.0.0-alpha.4

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.
@@ -5,7 +5,7 @@ const node_fs = require('node:fs');
5
5
  const path = require('node:path');
6
6
 
7
7
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
- var version = "4.0.0-alpha.2";
8
+ var version = "4.0.0-alpha.4";
9
9
  const packageJson = {
10
10
  version: version};
11
11
 
@@ -1514,6 +1514,65 @@ function resolveSeverity(severity) {
1514
1514
  return severity ?? Severity.UNKNOWN
1515
1515
  }
1516
1516
 
1517
+ // ── Per-execution logger context ─────────────────────────────────────────────
1518
+
1519
+ // Holds an AsyncLocalStorage instance once it is lazily initialised.
1520
+ // Allows per-execution logger isolation without mutating the global singleton,
1521
+ // making concurrent test execution (e.g. Deno's node:test) safe.
1522
+ let _loggerStore = null;
1523
+
1524
+ // Promise singleton — ensures AsyncLocalStorage is initialised at most once.
1525
+ let _loggerStorePromise = null;
1526
+
1527
+ /**
1528
+ * Lazily initialise an AsyncLocalStorage for per-execution logger context.
1529
+ * Falls back to null in environments that do not support node:async_hooks (e.g. browsers).
1530
+ * @returns {Promise<import('node:async_hooks').AsyncLocalStorage|null>}
1531
+ */
1532
+ async function _ensureLoggerStore() {
1533
+ if (_loggerStorePromise === null) {
1534
+ _loggerStorePromise = import('node:async_hooks')
1535
+ .then(({ AsyncLocalStorage }) => {
1536
+ const store = new AsyncLocalStorage();
1537
+ _loggerStore = store;
1538
+ return store
1539
+ })
1540
+ .catch(() => null);
1541
+ }
1542
+ return _loggerStorePromise
1543
+ }
1544
+
1545
+ /** @internal — returns the logger bound to the current async context, or null */
1546
+ function getContextLogger() {
1547
+ return _loggerStore?.getStore() ?? null
1548
+ }
1549
+
1550
+ /**
1551
+ * Run fn() within an async-local logger context so that all log calls via
1552
+ * `this.logger` (from applyLogging) automatically route to the provided logger
1553
+ * for the duration of the async execution chain.
1554
+ *
1555
+ * Falls back to global mutation in environments without node:async_hooks (e.g. browsers).
1556
+ *
1557
+ * @param {Logger|MemoryLogger|NullLogger} logger - The logger to activate.
1558
+ * @param {() => any} fn - The function to execute within the logger context.
1559
+ * @returns {Promise<any>}
1560
+ */
1561
+ async function withLogger(logger, fn) {
1562
+ const store = await _ensureLoggerStore();
1563
+ if (store) {
1564
+ return store.run(logger, fn)
1565
+ }
1566
+ // Fallback for environments without node:async_hooks (browsers).
1567
+ const prev = LoggerManager.logger;
1568
+ if (logger !== prev) LoggerManager.logger = logger;
1569
+ try {
1570
+ return await fn()
1571
+ } finally {
1572
+ if (logger !== prev) LoggerManager.logger = prev;
1573
+ }
1574
+ }
1575
+
1517
1576
  // ── Logger ────────────────────────────────────────────────────────────────────
1518
1577
 
1519
1578
  /** Standard logger that writes formatted messages to stderr or a custom pipe. */
@@ -1822,8 +1881,9 @@ class MemoryLogger {
1822
1881
  // ── NullLogger ────────────────────────────────────────────────────────────────
1823
1882
 
1824
1883
  /** Logger that discards all messages but still tracks the maximum severity. */
1825
- class NullLogger {
1884
+ class NullLogger extends Logger {
1826
1885
  constructor() {
1886
+ super();
1827
1887
  this.level = Severity.UNKNOWN;
1828
1888
  this._maxSeverity = null;
1829
1889
  }
@@ -1968,12 +2028,12 @@ const LoggerManager = (() => {
1968
2028
  function applyLogging(proto) {
1969
2029
  Object.defineProperty(proto, 'logger', {
1970
2030
  get() {
1971
- return LoggerManager.logger
2031
+ return _loggerStore?.getStore() ?? LoggerManager.logger
1972
2032
  },
1973
2033
  configurable: true,
1974
2034
  });
1975
2035
 
1976
- proto.getLogger = () => LoggerManager.logger;
2036
+ proto.getLogger = () => _loggerStore?.getStore() ?? LoggerManager.logger;
1977
2037
 
1978
2038
  proto.messageWithContext = (text, context = {}) =>
1979
2039
  Logger.AutoFormattingMessage.attach({ text, ...context });
@@ -2020,7 +2080,16 @@ const rstrip = (line) => line.replace(/[ \t\r\n\f\v]+$/, '');
2020
2080
  */
2021
2081
  function prepareSourceArray(data, trimEnd = true) {
2022
2082
  if (!data.length) return []
2023
- if (data[0].startsWith(BOM)) data[0] = data[0].slice(1);
2083
+ if (data[0].startsWith(BOM)) {
2084
+ data[0] = data[0].slice(1);
2085
+ } else if (
2086
+ data[0].charCodeAt(0) === 0xef &&
2087
+ data[0].charCodeAt(1) === 0xbb &&
2088
+ data[0].charCodeAt(2) === 0xbf
2089
+ ) {
2090
+ // Strip UTF-8 BOM encoded as three raw characters ( / \xEF\xBB\xBF) if not already decoded to U+FEFF
2091
+ data[0] = data[0].slice(3);
2092
+ }
2024
2093
  // Strip trailing \r to normalize Windows CRLF line endings (lines were split on \n, leaving \r).
2025
2094
  return trimEnd
2026
2095
  ? data.map(rstrip)
@@ -2040,7 +2109,16 @@ function prepareSourceArray(data, trimEnd = true) {
2040
2109
  */
2041
2110
  function prepareSourceString(data, trimEnd = true) {
2042
2111
  if (!data) return []
2043
- if (data.startsWith(BOM)) data = data.slice(1);
2112
+ if (data.startsWith(BOM)) {
2113
+ data = data.slice(1);
2114
+ } else if (
2115
+ data.charCodeAt(0) === 0xef &&
2116
+ data.charCodeAt(1) === 0xbb &&
2117
+ data.charCodeAt(2) === 0xbf
2118
+ ) {
2119
+ // Strip UTF-8 BOM encoded as three raw characters ( / \xEF\xBB\xBF) if not already decoded to U+FEFF
2120
+ data = data.slice(3);
2121
+ }
2044
2122
  // Normalize Windows CRLF to LF so that split('\n') does not leave trailing \r on each line.
2045
2123
  if (data.includes('\r'))
2046
2124
  data = data.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
@@ -2336,6 +2414,146 @@ function nextval(current) {
2336
2414
  return current
2337
2415
  }
2338
2416
 
2417
+ // HTTP cache system for URI fetching.
2418
+ //
2419
+ // Provides a pluggable caching layer for all HTTP(S) fetches performed during
2420
+ // document conversion (includes, images, readContents). Mirrors the behaviour
2421
+ // of Ruby's open-uri/cached mechanism activated by the `cache-uri` attribute.
2422
+ //
2423
+ // When `cache-uri` is set on the document:
2424
+ // - If a cache has been registered via HttpCacheManager.setCache(), it is used.
2425
+ // - Otherwise an ephemeral MemoryHttpCache is created for the duration of the
2426
+ // conversion (keyed by Document instance via a WeakMap, GC'd with the doc).
2427
+ //
2428
+ // To implement a custom cache, extend HttpCache and override read(uri).
2429
+
2430
+ /**
2431
+ * Base HTTP cache class.
2432
+ *
2433
+ * The default implementation delegates directly to fetch() with no caching.
2434
+ * Subclasses override read() to add caching behaviour.
2435
+ */
2436
+ class HttpCache {
2437
+ /**
2438
+ * Fetch content from a URI, optionally from a cache.
2439
+ * @param {string} uri
2440
+ * @returns {Promise<Response>}
2441
+ */
2442
+ async read(uri) {
2443
+ return fetch(uri)
2444
+ }
2445
+ }
2446
+
2447
+ /**
2448
+ * In-memory HTTP cache.
2449
+ *
2450
+ * Stores successful responses as ArrayBuffers keyed by URI. On a cache hit
2451
+ * a synthetic Response is reconstructed from the stored data without touching
2452
+ * the network. Non-OK responses (4xx, 5xx) are never cached.
2453
+ *
2454
+ * Safe as an ephemeral per-conversion cache or as a longer-lived process-level
2455
+ * cache when registered via HttpCacheManager.setCache().
2456
+ */
2457
+ class MemoryHttpCache extends HttpCache {
2458
+ /** @type {Map<string, {buffer: ArrayBuffer, status: number, statusText: string, headers: Record<string,string>}>} */
2459
+ #cache = new Map()
2460
+
2461
+ async read(uri) {
2462
+ const entry = this.#cache.get(uri);
2463
+ if (entry) {
2464
+ return new Response(entry.buffer.slice(0), {
2465
+ status: entry.status,
2466
+ statusText: entry.statusText,
2467
+ headers: entry.headers,
2468
+ })
2469
+ }
2470
+ const response = await fetch(uri);
2471
+ if (response.ok) {
2472
+ const buffer = await response.arrayBuffer();
2473
+ const headers = Object.fromEntries(response.headers.entries());
2474
+ this.#cache.set(uri, {
2475
+ buffer,
2476
+ status: response.status,
2477
+ statusText: response.statusText,
2478
+ headers,
2479
+ });
2480
+ return new Response(buffer.slice(0), {
2481
+ status: response.status,
2482
+ statusText: response.statusText,
2483
+ headers,
2484
+ })
2485
+ }
2486
+ return response
2487
+ }
2488
+ }
2489
+
2490
+ /** @type {WeakMap<object, MemoryHttpCache>} */
2491
+ const _ephemeralCaches = new WeakMap();
2492
+
2493
+ /**
2494
+ * Singleton manager for the HTTP cache.
2495
+ *
2496
+ * Register a process-level cache:
2497
+ * HttpCacheManager.setCache(new MemoryHttpCache())
2498
+ * HttpCacheManager.setCache(new MyFileSystemCache('./cache'))
2499
+ * HttpCacheManager.setCache(null) // revert to default ephemeral behaviour
2500
+ *
2501
+ * When no cache is registered and `cache-uri` is set, an ephemeral
2502
+ * MemoryHttpCache is created per Document instance.
2503
+ */
2504
+ const HttpCacheManager = {
2505
+ /** @type {HttpCache|null} */
2506
+ _cache: null,
2507
+
2508
+ /**
2509
+ * Register a cache to use for all conversions.
2510
+ * Pass null to unregister and revert to the ephemeral default.
2511
+ * @param {HttpCache|null} cache
2512
+ */
2513
+ setCache(cache) {
2514
+ this._cache = cache;
2515
+ },
2516
+
2517
+ /**
2518
+ * Return the registered process-level cache, or null if none is registered.
2519
+ * @returns {HttpCache|null}
2520
+ */
2521
+ getCache() {
2522
+ return this._cache
2523
+ },
2524
+
2525
+ /**
2526
+ * Return the cache to use for a specific document conversion.
2527
+ *
2528
+ * Returns the registered cache if one exists; otherwise creates (or reuses)
2529
+ * an ephemeral MemoryHttpCache scoped to the document's lifetime via a WeakMap.
2530
+ * @param {object} doc - the current Document instance
2531
+ * @returns {HttpCache}
2532
+ */
2533
+ getCacheForDocument(doc) {
2534
+ if (this._cache) return this._cache
2535
+ let cache = _ephemeralCaches.get(doc);
2536
+ if (!cache) {
2537
+ cache = new MemoryHttpCache();
2538
+ _ephemeralCaches.set(doc, cache);
2539
+ }
2540
+ return cache
2541
+ },
2542
+ };
2543
+
2544
+ /**
2545
+ * Fetch a URI, routing through the HTTP cache when `cache-uri` is set on the document.
2546
+ * @param {string} uri
2547
+ * @param {object} doc - the current Document instance
2548
+ * @returns {Promise<Response>}
2549
+ */
2550
+ function fetchUri(uri, doc) {
2551
+ if (doc.hasAttribute('cache-uri')) {
2552
+ return HttpCacheManager.getCacheForDocument(doc).read(uri)
2553
+ }
2554
+ return fetch(uri)
2555
+ }
2556
+
2339
2557
  // ESM conversion of abstract_node.rb
2340
2558
  //
2341
2559
  // Ruby-to-JavaScript notes:
@@ -2815,10 +3033,7 @@ class AbstractNode {
2815
3033
  (targetImage = this.normalizeWebPath(targetImage, imagesBase, false)))
2816
3034
  ) {
2817
3035
  return doc.hasAttribute('allow-uri-read')
2818
- ? this.generateDataUriFromUri(
2819
- targetImage,
2820
- doc.hasAttribute('cache-uri')
2821
- )
3036
+ ? this.generateDataUriFromUri(targetImage)
2822
3037
  : targetImage
2823
3038
  }
2824
3039
  return this.generateDataUri(targetImage, assetDirKey)
@@ -2871,10 +3086,7 @@ class AbstractNode {
2871
3086
  )
2872
3087
  : this.normalizeSystemPath(targetImage);
2873
3088
  if (isUriish(imagePath)) {
2874
- return await this.generateDataUriFromUri(
2875
- imagePath,
2876
- this.document.hasAttribute('cache-uri')
2877
- )
3089
+ return await this.generateDataUriFromUri(imagePath)
2878
3090
  }
2879
3091
  if (await isReadable(imagePath)) {
2880
3092
  const data = await _fsp$1.readFile(imagePath);
@@ -2894,12 +3106,12 @@ class AbstractNode {
2894
3106
  * imageUri, the caller must await the returned Promise.
2895
3107
  *
2896
3108
  * @param {string} imageUri - The URI from which to read the image data (http/https/ftp).
2897
- * @param {boolean} [cacheUri=false] - A Boolean to control caching (not yet supported in JS).
2898
3109
  * @returns {Promise<string>} a Promise resolving to a String data URI.
2899
3110
  */
2900
- async generateDataUriFromUri(imageUri, cacheUri = false) {
3111
+ async generateDataUriFromUri(imageUri) {
2901
3112
  try {
2902
- const response = await fetch(imageUri);
3113
+ const doc = this.document;
3114
+ const response = await fetchUri(imageUri, doc);
2903
3115
  if (response.ok) {
2904
3116
  const mimetype = (
2905
3117
  response.headers.get('content-type') || 'application/octet-stream'
@@ -3070,7 +3282,7 @@ class AbstractNode {
3070
3282
  ) {
3071
3283
  if (doc.hasAttribute('allow-uri-read')) {
3072
3284
  try {
3073
- const response = await fetch(resolvedTarget);
3285
+ const response = await fetchUri(resolvedTarget, doc);
3074
3286
  const text = await response.text();
3075
3287
  contents = opts.normalize ? prepareSourceString(text).join(LF$1) : text;
3076
3288
  } catch {
@@ -3095,7 +3307,7 @@ class AbstractNode {
3095
3307
  });
3096
3308
  }
3097
3309
 
3098
- if (contents && opts.warnIfEmpty && contents.length === 0) {
3310
+ if (contents != null && opts.warnIfEmpty && contents.length === 0) {
3099
3311
  this.logger.warn(`contents of ${label} is empty: ${resolvedTarget}`);
3100
3312
  }
3101
3313
  return contents
@@ -4849,14 +5061,6 @@ class PathResolver {
4849
5061
  : path
4850
5062
  }
4851
5063
 
4852
- /**
4853
- * @param {string} path
4854
- * @returns {string}
4855
- */
4856
- posixfy(path) {
4857
- return this.posixify(path)
4858
- }
4859
-
4860
5064
  /**
4861
5065
  * Expand the path by resolving parent references (..) and removing self references (.).
4862
5066
  * @param {string} path
@@ -5157,14 +5361,27 @@ function _platformSeparator() {
5157
5361
  * @internal
5158
5362
  */
5159
5363
  function _expandPath$1(p) {
5160
- if (typeof process !== 'undefined') {
5161
- // Lazy import to avoid top-level await
5162
- try {
5163
- const path = require('node:path');
5164
- return path.resolve(p).replace(/\\/g, '/')
5165
- } catch {}
5364
+ if (typeof process === 'undefined') return p
5365
+ const cwd = process.cwd().replace(/\\/g, '/');
5366
+ const full = `${cwd}/${p.replace(/\\/g, '/')}`;
5367
+ let root, rest;
5368
+ if (full.startsWith('//')) {
5369
+ root = '//';
5370
+ rest = full.slice(2);
5371
+ } else if (full.startsWith('/')) {
5372
+ root = '/';
5373
+ rest = full.slice(1);
5374
+ } else {
5375
+ const slash = full.indexOf('/');
5376
+ root = full.slice(0, slash + 1);
5377
+ rest = full.slice(slash + 1);
5378
+ }
5379
+ const resolved = [];
5380
+ for (const seg of rest.split('/')) {
5381
+ if (seg === '..') resolved.pop();
5382
+ else if (seg && seg !== '.') resolved.push(seg);
5166
5383
  }
5167
- return p
5384
+ return root + resolved.join('/')
5168
5385
  }
5169
5386
 
5170
5387
  /**
@@ -5972,7 +6189,7 @@ const SyntaxHighlighter = new DefaultFactory();
5972
6189
  //
5973
6190
  // This logic is specific to Asciidoctor.js and has no equivalent in the upstream Ruby asciidoctor
5974
6191
  // implementation. It handles the case where the document is loaded in a browser environment
5975
- // (XMLHttpRequest / Fetch IO module) where paths can be file:// or http(s):// URIs.
6192
+ // where paths can be file:// or http(s):// URIs.
5976
6193
  //
5977
6194
  // The key behavioural differences from the standard file-system resolver:
5978
6195
  // - Relative targets are resolved by string concatenation against a URI context dir,
@@ -6021,7 +6238,7 @@ function _linkReplacement(reader, target, attrlist) {
6021
6238
  * 1. target starts with file:// → inc_path = relpath = target
6022
6239
  * 2. target is a URI → must descend from baseDir or allow-uri-read; else → link
6023
6240
  * 3. target is an absolute OS path → prepend file:// (or file:///)
6024
- * 4. baseDir == '.' → inc_path = relpath = target (resolved by XMLHttpRequest/fetch)
6241
+ * 4. baseDir == '.' → inc_path = relpath = target (resolved by fetch)
6025
6242
  * 5. baseDir starts with file:// OR baseDir is not a URI → inc_path = baseDir/target; relpath = target
6026
6243
  * 6. baseDir is an absolute URL → inc_path = baseDir/target; relpath = target
6027
6244
  *
@@ -6743,7 +6960,7 @@ class Reader {
6743
6960
  return this.source()
6744
6961
  }
6745
6962
  getLogger() {
6746
- return LoggerManager.logger
6963
+ return this._document?.logger ?? LoggerManager.logger
6747
6964
  }
6748
6965
  createLogMessage(text, context = {}) {
6749
6966
  return Logger.AutoFormattingMessage.attach({ text, ...context })
@@ -7391,7 +7608,7 @@ class PreprocessorReader extends Reader {
7391
7608
  if (targetType === 'uri') {
7392
7609
  let uriContent;
7393
7610
  try {
7394
- const response = await fetch(incPath);
7611
+ const response = await fetchUri(incPath, this._document);
7395
7612
  if (!response.ok)
7396
7613
  throw new Error(`HTTP ${response.status} ${response.statusText}`)
7397
7614
  uriContent = await response.text();
@@ -9568,6 +9785,22 @@ class AttributeList {
9568
9785
  }
9569
9786
  }
9570
9787
 
9788
+ // Symbol key used to store attribute entries on a block-attributes object without
9789
+ // polluting the public attributes (invisible to Object.keys / for-in / JSON.stringify).
9790
+ // Spread ({ ...attrs }) copies Symbol-keyed properties, so the entry survives the
9791
+ // shallow clone made in AbstractNode's constructor.
9792
+ const ATTR_ENTRIES_KEY = Symbol('attribute_entries');
9793
+
9794
+ /**
9795
+ * Return the attribute entries stored for the given block attributes object,
9796
+ * or undefined if none have been saved.
9797
+ * @param {Object} blockAttributes
9798
+ * @returns {AttributeEntry[]|undefined}
9799
+ */
9800
+ function getAttributeEntries(blockAttributes) {
9801
+ return blockAttributes[ATTR_ENTRIES_KEY]
9802
+ }
9803
+
9571
9804
  class AttributeEntry {
9572
9805
  constructor(name, value, negate = null) {
9573
9806
  this.name = name;
@@ -9576,7 +9809,7 @@ class AttributeEntry {
9576
9809
  }
9577
9810
 
9578
9811
  saveTo(blockAttributes) {
9579
- (blockAttributes.attribute_entries ??= []).push(this);
9812
+ (blockAttributes[ATTR_ENTRIES_KEY] ??= []).push(this);
9580
9813
  return this
9581
9814
  }
9582
9815
  }
@@ -11051,7 +11284,7 @@ class Parser {
11051
11284
  const Rdr = Reader;
11052
11285
  const result = await extension.processMethod(
11053
11286
  parent,
11054
- blockReader ?? new Rdr(lines),
11287
+ blockReader ?? new Rdr(lines, null, { document: parent.document }),
11055
11288
  { ...attributes }
11056
11289
  );
11057
11290
  if (!result || result === parent) return null
@@ -13173,6 +13406,94 @@ function _uniform(str, chr, len) {
13173
13406
  // references; they will be resolved when those modules implement the methods.
13174
13407
 
13175
13408
 
13409
+ // Type-only imports for JSDoc
13410
+ /**
13411
+ * @typedef {import('./document.js').Document} Document
13412
+ * @typedef {import('./abstract_block.js').AbstractBlock} AbstractBlock
13413
+ */
13414
+
13415
+ // ── DSL interface types ───────────────────────────────────────────────────────
13416
+
13417
+ /**
13418
+ * DSL interface for configuring a {@link Processor} instance.
13419
+ * Applied to a processor instance via `Object.assign(instance, DslMixin)`.
13420
+ *
13421
+ * The `process` property behaves as a setter when called with a single Function
13422
+ * argument (stores the process block), or as a passthrough caller otherwise.
13423
+ *
13424
+ * @typedef {object} ProcessorDslInterface
13425
+ * @property {(key: string, value: unknown) => void} option - Set a config option.
13426
+ * @property {(fn: (...args: unknown[]) => unknown) => void} process - Register the process function.
13427
+ * @property {() => boolean} processBlockGiven - Returns true if a process function has been registered.
13428
+ */
13429
+
13430
+ /**
13431
+ * DSL interface for document processors (Preprocessor, TreeProcessor, Postprocessor, DocinfoProcessor).
13432
+ *
13433
+ * @typedef {ProcessorDslInterface & { prefer(): void; prepend(): void }} DocumentProcessorDslInterface
13434
+ */
13435
+
13436
+ /**
13437
+ * DSL interface for syntax processors (BlockProcessor, BlockMacroProcessor, InlineMacroProcessor).
13438
+ *
13439
+ * @typedef {ProcessorDslInterface & {
13440
+ * named(value: string): void;
13441
+ * contentModel(value: string): void;
13442
+ * parseContentAs(value: string): void;
13443
+ * positionalAttributes(...value: string[]): void;
13444
+ * namePositionalAttributes(...value: string[]): void;
13445
+ * positionalAttrs(...value: string[]): void;
13446
+ * defaultAttributes(value: Record<string, string>): void;
13447
+ * defaultAttrs(value: Record<string, string>): void;
13448
+ * resolveAttributes(...args: unknown[]): void;
13449
+ * resolvesAttributes(...args: unknown[]): void;
13450
+ * }} SyntaxProcessorDslInterface
13451
+ */
13452
+
13453
+ /**
13454
+ * DSL interface for include processors.
13455
+ *
13456
+ * @typedef {DocumentProcessorDslInterface & {
13457
+ * handles(fn: (doc: Document, target: string) => boolean): void;
13458
+ * }} IncludeProcessorDslInterface
13459
+ */
13460
+
13461
+ /**
13462
+ * DSL interface for docinfo processors.
13463
+ *
13464
+ * @typedef {DocumentProcessorDslInterface & {
13465
+ * atLocation(value: string): void;
13466
+ * }} DocinfoProcessorDslInterface
13467
+ */
13468
+
13469
+ /**
13470
+ * DSL interface for block processors.
13471
+ *
13472
+ * @typedef {SyntaxProcessorDslInterface & {
13473
+ * contexts(...value: (string | string[])[]): void;
13474
+ * onContexts(...value: (string | string[])[]): void;
13475
+ * onContext(...value: (string | string[])[]): void;
13476
+ * bindTo(...value: (string | string[])[]): void;
13477
+ * }} BlockProcessorDslInterface
13478
+ */
13479
+
13480
+ /**
13481
+ * DSL interface for macro processors (block and inline macros).
13482
+ *
13483
+ * @typedef {SyntaxProcessorDslInterface} MacroProcessorDslInterface
13484
+ */
13485
+
13486
+ /**
13487
+ * DSL interface for inline macro processors.
13488
+ *
13489
+ * @typedef {MacroProcessorDslInterface & {
13490
+ * format(value: string): void;
13491
+ * matchFormat(value: string): void;
13492
+ * usingFormat(value: string): void;
13493
+ * match(value: RegExp): void;
13494
+ * }} InlineMacroProcessorDslInterface
13495
+ */
13496
+
13176
13497
  // ── DSL Mixins ────────────────────────────────────────────────────────────────
13177
13498
 
13178
13499
  /**
@@ -13768,7 +14089,12 @@ class Processor {
13768
14089
  * Extensions.register(function () { this.preprocessor(CommentStripPreprocessor) })
13769
14090
  */
13770
14091
  class Preprocessor extends Processor {
13771
- process(_document, _reader) {
14092
+ /**
14093
+ * @param {Document} document - The document being parsed.
14094
+ * @param {Reader} reader - The reader positioned at the beginning of the source.
14095
+ * @returns {Reader|undefined} The same or a substitute Reader, or undefined to use the original.
14096
+ */
14097
+ process(document, reader) {
13772
14098
  throw new Error(
13773
14099
  `${this.constructor.name} must implement the process method`
13774
14100
  )
@@ -13793,7 +14119,11 @@ Preprocessor.DSL = DocumentProcessorDsl;
13793
14119
  * Extensions.register(function () { this.treeProcessor(ShoutTreeProcessor) })
13794
14120
  */
13795
14121
  class TreeProcessor extends Processor {
13796
- process(_document) {
14122
+ /**
14123
+ * @param {Document} document - The parsed document.
14124
+ * @returns {void}
14125
+ */
14126
+ process(document) {
13797
14127
  throw new Error(
13798
14128
  `${this.constructor.name} must implement the process method`
13799
14129
  )
@@ -13819,7 +14149,12 @@ TreeProcessor.DSL = DocumentProcessorDsl;
13819
14149
  * Extensions.register(function () { this.postprocessor(FooterPostprocessor) })
13820
14150
  */
13821
14151
  class Postprocessor extends Processor {
13822
- process(_document, _output) {
14152
+ /**
14153
+ * @param {Document} document - The converted document.
14154
+ * @param {string} output - The converted output string.
14155
+ * @returns {string} The (possibly modified) output string.
14156
+ */
14157
+ process(document, output) {
13823
14158
  throw new Error(
13824
14159
  `${this.constructor.name} must implement the process method`
13825
14160
  )
@@ -13833,13 +14168,25 @@ Postprocessor.DSL = DocumentProcessorDsl;
13833
14168
  * Implementations must extend IncludeProcessor.
13834
14169
  */
13835
14170
  class IncludeProcessor extends Processor {
13836
- process(_document, _reader, _target, _attributes) {
14171
+ /**
14172
+ * @param {Document} document - The document being parsed.
14173
+ * @param {Reader} reader - The reader for the including document.
14174
+ * @param {string} target - The target of the include directive.
14175
+ * @param {Record<string, string>} attributes - The parsed include attributes.
14176
+ * @returns {void}
14177
+ */
14178
+ process(document, reader, target, attributes) {
13837
14179
  throw new Error(
13838
14180
  `${this.constructor.name} must implement the process method`
13839
14181
  )
13840
14182
  }
13841
14183
 
13842
- handles(_doc, _target) {
14184
+ /**
14185
+ * @param {Document} doc - The document being parsed.
14186
+ * @param {string} target - The target of the include directive.
14187
+ * @returns {boolean} true if this processor handles the given target.
14188
+ */
14189
+ handles(doc, target) {
13843
14190
  return true
13844
14191
  }
13845
14192
  }
@@ -13857,7 +14204,11 @@ class DocinfoProcessor extends Processor {
13857
14204
  this.config.location ??= 'head';
13858
14205
  }
13859
14206
 
13860
- process(_document) {
14207
+ /**
14208
+ * @param {Document} document - The document being converted.
14209
+ * @returns {string} The docinfo content to inject into the document.
14210
+ */
14211
+ process(document) {
13861
14212
  throw new Error(
13862
14213
  `${this.constructor.name} must implement the process method`
13863
14214
  )
@@ -13913,7 +14264,13 @@ class BlockProcessor extends Processor {
13913
14264
  this.config.content_model ??= 'compound';
13914
14265
  }
13915
14266
 
13916
- process(_parent, _reader, _attributes) {
14267
+ /**
14268
+ * @param {AbstractBlock} parent - The enclosing block.
14269
+ * @param {Reader} reader - The reader positioned at the block content.
14270
+ * @param {Record<string, unknown>} attributes - The parsed block attributes.
14271
+ * @returns {Block|void} A block node, or void to let the parser handle it.
14272
+ */
14273
+ process(parent, reader, attributes) {
13917
14274
  throw new Error(
13918
14275
  `${this.constructor.name} must implement the process method`
13919
14276
  )
@@ -13931,7 +14288,13 @@ class MacroProcessor extends Processor {
13931
14288
  this.config.content_model ??= 'attributes';
13932
14289
  }
13933
14290
 
13934
- process(_parent, _target, _attributes) {
14291
+ /**
14292
+ * @param {AbstractBlock} parent - The enclosing block.
14293
+ * @param {string} target - The macro target (text between `name:` and `[`).
14294
+ * @param {Record<string, unknown>} attributes - The parsed macro attributes.
14295
+ * @returns {Block|Inline|void}
14296
+ */
14297
+ process(parent, target, attributes) {
13935
14298
  throw new Error(
13936
14299
  `${this.constructor.name} must implement the process method`
13937
14300
  )
@@ -13977,6 +14340,16 @@ class BlockMacroProcessor extends MacroProcessor {
13977
14340
  set name(value) {
13978
14341
  this._name = value;
13979
14342
  }
14343
+
14344
+ /**
14345
+ * @param {AbstractBlock} parent - The enclosing block.
14346
+ * @param {string} target - The macro target.
14347
+ * @param {Record<string, unknown>} attributes - The parsed macro attributes.
14348
+ * @returns {Block} A block node created with one of the `createBlock` helpers.
14349
+ */
14350
+ process(parent, target, attributes) {
14351
+ return super.process(parent, target, attributes)
14352
+ }
13980
14353
  }
13981
14354
  BlockMacroProcessor.DSL = MacroProcessorDsl;
13982
14355
 
@@ -14020,6 +14393,16 @@ class InlineMacroProcessor extends MacroProcessor {
14020
14393
  ))
14021
14394
  }
14022
14395
 
14396
+ /**
14397
+ * @param {AbstractBlock} parent - The enclosing block.
14398
+ * @param {string} target - The macro target.
14399
+ * @param {Record<string, unknown>} attributes - The parsed macro attributes.
14400
+ * @returns {Inline} An Inline node created with `this.createInline(...)`.
14401
+ */
14402
+ process(parent, target, attributes) {
14403
+ return super.process(parent, target, attributes)
14404
+ }
14405
+
14023
14406
  resolveRegexp(name, format) {
14024
14407
  if (!MacroNameRx.test(name)) {
14025
14408
  throw new Error(`invalid name for inline macro: ${name}`)
@@ -14383,6 +14766,15 @@ class Registry {
14383
14766
  return !!this._block_extensions
14384
14767
  }
14385
14768
 
14769
+ /**
14770
+ * Retrieve all BlockProcessor Extension proxy objects.
14771
+ *
14772
+ * @returns {ProcessorExtension[]}
14773
+ */
14774
+ blocks() {
14775
+ return this._block_extensions ? Object.values(this._block_extensions) : []
14776
+ }
14777
+
14386
14778
  /**
14387
14779
  * Check whether a BlockProcessor is registered for the given name and context.
14388
14780
  *
@@ -14429,6 +14821,17 @@ class Registry {
14429
14821
  return !!this._block_macro_extensions
14430
14822
  }
14431
14823
 
14824
+ /**
14825
+ * Retrieve all BlockMacroProcessor Extension proxy objects.
14826
+ *
14827
+ * @returns {ProcessorExtension[]}
14828
+ */
14829
+ blockMacros() {
14830
+ return this._block_macro_extensions
14831
+ ? Object.values(this._block_macro_extensions)
14832
+ : []
14833
+ }
14834
+
14432
14835
  /**
14433
14836
  * Check whether a BlockMacroProcessor is registered for the given name.
14434
14837
  *
@@ -14534,6 +14937,85 @@ class Registry {
14534
14937
  return extension
14535
14938
  }
14536
14939
 
14940
+ // ── JavaScript-style accessors ───────────────────────────────────────────────
14941
+
14942
+ /** @returns {object} the plain Object that maps names to groups for this registry. */
14943
+ getGroups() {
14944
+ return this.groups
14945
+ }
14946
+
14947
+ /** Alias for {@link preprocessors}. */
14948
+ getPreprocessors() {
14949
+ return this.preprocessors()
14950
+ }
14951
+
14952
+ /** Alias for {@link treeProcessors}. */
14953
+ getTreeProcessors() {
14954
+ return this.treeProcessors()
14955
+ }
14956
+
14957
+ /** Alias for {@link includeProcessors}. */
14958
+ getIncludeProcessors() {
14959
+ return this.includeProcessors()
14960
+ }
14961
+
14962
+ /** Alias for {@link postprocessors}. */
14963
+ getPostprocessors() {
14964
+ return this.postprocessors()
14965
+ }
14966
+
14967
+ /**
14968
+ * Alias for {@link docinfoProcessors}.
14969
+ *
14970
+ * @param {string|null} [location=null]
14971
+ */
14972
+ getDocinfoProcessors(location = null) {
14973
+ return this.docinfoProcessors(location)
14974
+ }
14975
+
14976
+ /** Alias for {@link blocks}. */
14977
+ getBlocks() {
14978
+ return this.blocks()
14979
+ }
14980
+
14981
+ /** Alias for {@link blockMacros}. */
14982
+ getBlockMacros() {
14983
+ return this.blockMacros()
14984
+ }
14985
+
14986
+ /** Alias for {@link inlineMacros}. */
14987
+ getInlineMacros() {
14988
+ return this.inlineMacros()
14989
+ }
14990
+
14991
+ /**
14992
+ * Alias for {@link registeredForInlineMacro}.
14993
+ *
14994
+ * @param {string} name
14995
+ */
14996
+ getInlineMacroFor(name) {
14997
+ return this.registeredForInlineMacro(name)
14998
+ }
14999
+
15000
+ /**
15001
+ * Alias for {@link registeredForBlock}.
15002
+ *
15003
+ * @param {string} name
15004
+ * @param {string} context
15005
+ */
15006
+ getBlockFor(name, context) {
15007
+ return this.registeredForBlock(name, context)
15008
+ }
15009
+
15010
+ /**
15011
+ * Alias for {@link registeredForBlockMacro}.
15012
+ *
15013
+ * @param {string} name
15014
+ */
15015
+ getBlockMacroFor(name) {
15016
+ return this.registeredForBlockMacro(name)
15017
+ }
15018
+
14537
15019
  // ── Private helpers ──────────────────────────────────────────────────────────
14538
15020
 
14539
15021
  /** @internal */
@@ -14759,6 +15241,15 @@ const Extensions = {
14759
15241
  return _groups
14760
15242
  },
14761
15243
 
15244
+ /**
15245
+ * Alias for {@link groups}.
15246
+ *
15247
+ * @returns {object}
15248
+ */
15249
+ getGroups() {
15250
+ return this.groups()
15251
+ },
15252
+
14762
15253
  /**
14763
15254
  * Create a new Registry, optionally pre-populated with a named block.
14764
15255
  *
@@ -15986,8 +16477,9 @@ class Document extends AbstractBlock {
15986
16477
  * @param {Object} blockAttributes
15987
16478
  */
15988
16479
  playbackAttributes(blockAttributes) {
15989
- if (!('attribute_entries' in blockAttributes)) return
15990
- for (const entry of blockAttributes.attribute_entries) {
16480
+ const entries = getAttributeEntries(blockAttributes);
16481
+ if (!entries) return
16482
+ for (const entry of entries) {
15991
16483
  if (entry.negate) {
15992
16484
  delete this.attributes[entry.name];
15993
16485
  if (entry.name === 'compat-mode') this.compatMode = false;
@@ -16716,6 +17208,12 @@ class Document extends AbstractBlock {
16716
17208
  * Handles titles (AbstractBlock), list item text, table cell text, and reftexts.
16717
17209
  */
16718
17210
  async _resolveAllTexts(block) {
17211
+ // The header section lives outside document.blocks; pre-compute its title here so
17212
+ // that doc.doctitle() returns the fully-substituted title (with replacements applied,
17213
+ // e.g. ' → &#8217;) rather than the header-subs-only fallback.
17214
+ if (block === this && this.header) {
17215
+ await this.header.precomputeTitle?.();
17216
+ }
16719
17217
  // Skip title pre-computation for blocks with an explicit empty id ([id=]).
16720
17218
  // In Ruby, apply_title_subs is lazy: it is never called during parsing for such
16721
17219
  // blocks because section.title is never accessed. An explicit empty id is
@@ -16799,7 +17297,7 @@ class Document extends AbstractBlock {
16799
17297
  * @internal
16800
17298
  */
16801
17299
  _clearPlaybackAttributes(attributes) {
16802
- delete attributes.attribute_entries;
17300
+ delete attributes[ATTR_ENTRIES_KEY];
16803
17301
  }
16804
17302
 
16805
17303
  /**
@@ -17139,11 +17637,10 @@ class Document extends AbstractBlock {
17139
17637
  // ── Helpers ───────────────────────────────────────────────────────────────────
17140
17638
 
17141
17639
  function _expandPath(p) {
17142
- try {
17143
- return require('node:path').resolve(p)
17144
- } catch {
17145
- return p
17146
- }
17640
+ const resolver = new PathResolver();
17641
+ const posixed = p.replace(/\\/g, '/');
17642
+ if (resolver.absolutePath(posixed)) return resolver.expandPath(posixed)
17643
+ return resolver.expandPath(`${resolver.workingDir}/${posixed}`)
17147
17644
  }
17148
17645
 
17149
17646
  function _cwd() {
@@ -19527,17 +20024,23 @@ async function load$1(input, options = {}) {
19527
20024
  // Shallow-copy options so we don't mutate the caller's object.
19528
20025
  options = Object.assign({}, options);
19529
20026
 
19530
- const timings = options.timings ?? null;
19531
- if (timings) timings.start('read');
19532
-
19533
20027
  // ── Logger override ───────────────────────────────────────────────────────
20028
+ // When a logger option is supplied, run the conversion in an async-local
20029
+ // context so the logger is scoped to this call only — no global mutation,
20030
+ // which makes concurrent callers (e.g. parallel Deno tests) safe.
19534
20031
  if ('logger' in options) {
19535
- const logger = options.logger;
19536
- if (logger !== LoggerManager.logger) {
19537
- LoggerManager.logger = logger ?? new NullLogger();
19538
- }
20032
+ const newLogger = options.logger ?? new NullLogger();
20033
+ delete options.logger;
20034
+ return withLogger(newLogger, () => _doLoad(input, options, newLogger))
19539
20035
  }
19540
20036
 
20037
+ return _doLoad(input, options)
20038
+ }
20039
+
20040
+ async function _doLoad(input, options, explicitLogger = null) {
20041
+ const timings = options.timings ?? null;
20042
+ if (timings) timings.start('read');
20043
+
19541
20044
  // ── Attributes normalisation ──────────────────────────────────────────────
19542
20045
  let attrs = options.attributes;
19543
20046
  if (!attrs) {
@@ -19569,11 +20072,9 @@ async function load$1(input, options = {}) {
19569
20072
  attrs.docname = basename(inputPath, docfilesuffix);
19570
20073
  }
19571
20074
  source = await _readStream(input);
19572
- } else if (
19573
- typeof input === 'object' &&
19574
- input?.constructor?.name === 'Buffer'
19575
- ) {
19576
- source = input.toString('utf8');
20075
+ } else if (input instanceof Uint8Array) {
20076
+ // Covers both Node.js Buffer (a Uint8Array subclass) and browser Uint8Array shims.
20077
+ source = new TextDecoder('utf-8').decode(input);
19577
20078
  } else if (typeof input === 'string') {
19578
20079
  source = input;
19579
20080
  } else if (Array.isArray(input)) {
@@ -19636,6 +20137,19 @@ async function load$1(input, options = {}) {
19636
20137
  }
19637
20138
 
19638
20139
  if (timings) timings.record('parse');
20140
+
20141
+ // Persist the logger on the Document instance so that doc.convert()
20142
+ // (called by convert.js after the async-local context ends) still routes
20143
+ // logging through the caller-supplied logger.
20144
+ // ALS provides it in Node.js/Deno; the explicit parameter covers browser fallback.
20145
+ const contextLogger = getContextLogger() ?? explicitLogger;
20146
+ if (contextLogger) {
20147
+ Object.defineProperty(doc, 'logger', {
20148
+ get: () => contextLogger,
20149
+ configurable: true,
20150
+ });
20151
+ }
20152
+
19639
20153
  return doc
19640
20154
  }
19641
20155
 
@@ -19744,6 +20258,54 @@ async function _requirePath$1() {
19744
20258
  return import('node:path')
19745
20259
  }
19746
20260
 
20261
+ // Auto-generated from data/asciidoctor-default.css — run 'npm run build:data' to update
20262
+ const defaultStylesheetData = "/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\n h1{font-size:2.75em}\n h2{font-size:2.3125em}\n h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\n h4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\n body.toc2{padding-left:15em;padding-right:0}\n body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n #toc.toc2>ul{font-size:.9em;margin-bottom:0}\n #toc.toc2 ul ul{margin-left:0;padding-left:1em}\n #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\n body.toc2.toc-right{padding-left:0;padding-right:15em}\n body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n #toc.toc2{width:20em}\n #toc.toc2 #toctitle{font-size:1.375em}\n #toc.toc2>ul{font-size:.95em}\n #toc.toc2 ul ul{padding-left:1.25em}\n body.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n .sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\n html{font-size:80%}\n a{color:inherit!important;text-decoration:underline!important}\n a.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\n a[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\n abbr[title]{border-bottom:1px dotted}\n abbr[title]::after{content:\" (\" attr(title) \")\"}\n pre,blockquote,tr,img,object,svg{page-break-inside:avoid}\n thead{display:table-header-group}\n svg{max-width:100%}\n p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\n h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n #header,#content,#footnotes,#footer{max-width:none}\n #toc,.sidebarblock,.exampleblock>.content{background:none!important}\n #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\n body.book #header{text-align:center}\n body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\n body.book #header .details{border:0!important;display:block;padding:0!important}\n body.book #header .details span:first-child{margin-left:0!important}\n body.book #header .details br{display:block}\n body.book #header .details br+span::before{content:none!important}\n body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\n body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n .listingblock code[data-lang]::before{display:block}\n #footer{padding:0 .9375em}\n .hide-on-print{display:none!important}\n .print-only{display:block!important}\n .hide-for-print{display:none!important}\n .show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n .sect1{padding:0!important}\n .sect1+.sect1{border:0}\n #footer{background:none}\n #footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}";
20263
+
20264
+ // ESM port of lib/asciidoctor/stylesheets.rb
20265
+ //
20266
+ // Ruby-to-JavaScript notes:
20267
+ // - Singleton: Ruby @__instance__ = new → module-level instance exported as Stylesheets.instance
20268
+ // - primary_stylesheet_data memoisation: Ruby ||= → the CSS is a static import; no lazy load needed
20269
+ // - File.read(...).rstrip → CSS is inlined at build time in src/data/stylesheet-data.js
20270
+ // - STYLESHEETS_DIR = File.join(DATA_DIR, 'stylesheets') → not needed; CSS is a JS module
20271
+ // - coderay / pygments methods → omitted (SyntaxHighlighter.for not needed here)
20272
+
20273
+
20274
+ class StylesheetsClass {
20275
+ static DEFAULT_STYLESHEET_NAME = 'asciidoctor.css'
20276
+
20277
+ get primaryStylesheetName() {
20278
+ return StylesheetsClass.DEFAULT_STYLESHEET_NAME
20279
+ }
20280
+
20281
+ async primaryStylesheetData() {
20282
+ return defaultStylesheetData
20283
+ }
20284
+
20285
+ async embedPrimaryStylesheet() {
20286
+ return `<style>\n${defaultStylesheetData}\n</style>`
20287
+ }
20288
+
20289
+ async writePrimaryStylesheet(stylesoutdir) {
20290
+ try {
20291
+ const { writeFile } = require('node:fs/promises');
20292
+ const { join } = require('node:path');
20293
+ await writeFile(
20294
+ join(stylesoutdir, StylesheetsClass.DEFAULT_STYLESHEET_NAME),
20295
+ defaultStylesheetData,
20296
+ 'utf8'
20297
+ );
20298
+ return true
20299
+ } catch {
20300
+ return false
20301
+ }
20302
+ }
20303
+ }
20304
+
20305
+ const Stylesheets = {
20306
+ instance: new StylesheetsClass(),
20307
+ };
20308
+
19747
20309
  // ESM conversion of convert.rb
19748
20310
  //
19749
20311
  // Ruby-to-JavaScript notes:
@@ -19757,7 +20319,7 @@ async function _requirePath$1() {
19757
20319
  // - Ruby File.write → async writeFile() via node:fs/promises.
19758
20320
  // - Ruby Helpers.mkdir_p → mkdirP() from helpers.js.
19759
20321
  // - Ruby Helpers.uriish? → isUriish() from helpers.js.
19760
- // - Ruby Stylesheets.instance.write_primary_stylesheet → not yet ported to JS; skipped.
20322
+ // - Ruby Stylesheets.instance.write_primary_stylesheet → Stylesheets.instance.writePrimaryStylesheet() in stylesheets.js; returns false in browser environments.
19761
20323
  // - Ruby doc.syntax_highlighter → doc.syntaxHighlighter.
19762
20324
  // - Ruby syntax_hl.write_stylesheet? doc → syntaxHl.writeStylesheet(doc).
19763
20325
  // - Ruby syntax_hl.write_stylesheet doc, dir → syntaxHl.writeStylesheetToDisk(doc, dir).
@@ -19957,7 +20519,7 @@ async function convert(input, options = {}) {
19957
20519
  let copyAsciidoctorStylesheet = false;
19958
20520
  let copyUserStylesheet = false;
19959
20521
  const stylesheet = doc.getAttribute('stylesheet');
19960
- if (stylesheet) {
20522
+ if (stylesheet != null) {
19961
20523
  if (DEFAULT_STYLESHEET_KEYS.has(stylesheet)) {
19962
20524
  copyAsciidoctorStylesheet = true;
19963
20525
  } else if (!isUriish(stylesheet)) {
@@ -19988,7 +20550,15 @@ async function convert(input, options = {}) {
19988
20550
  }
19989
20551
  }
19990
20552
 
19991
- if (copyAsciidoctorStylesheet) ; else if (copyUserStylesheet) {
20553
+ if (copyAsciidoctorStylesheet) {
20554
+ if (
20555
+ !(await Stylesheets.instance.writePrimaryStylesheet(stylesoutdir))
20556
+ ) {
20557
+ doc.logger.info(
20558
+ 'skipping default stylesheet copy: filesystem writes are not supported in this environment'
20559
+ );
20560
+ }
20561
+ } else if (copyUserStylesheet) {
19992
20562
  let stylesheetSrc = doc.getAttribute('copycss');
19993
20563
  if (stylesheetSrc === '' || stylesheetSrc === true) {
19994
20564
  stylesheetSrc = doc.normalizeSystemPath(stylesheet);
@@ -20186,39 +20756,6 @@ class Timings {
20186
20756
  }
20187
20757
  }
20188
20758
 
20189
- // Auto-generated from data/asciidoctor-default.css — run 'npm run build:data' to update
20190
- const defaultStylesheetData = "/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\n h1{font-size:2.75em}\n h2{font-size:2.3125em}\n h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\n h4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\n body.toc2{padding-left:15em;padding-right:0}\n body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n #toc.toc2>ul{font-size:.9em;margin-bottom:0}\n #toc.toc2 ul ul{margin-left:0;padding-left:1em}\n #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\n body.toc2.toc-right{padding-left:0;padding-right:15em}\n body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n #toc.toc2{width:20em}\n #toc.toc2 #toctitle{font-size:1.375em}\n #toc.toc2>ul{font-size:.95em}\n #toc.toc2 ul ul{padding-left:1.25em}\n body.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n .sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\n html{font-size:80%}\n a{color:inherit!important;text-decoration:underline!important}\n a.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\n a[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\n abbr[title]{border-bottom:1px dotted}\n abbr[title]::after{content:\" (\" attr(title) \")\"}\n pre,blockquote,tr,img,object,svg{page-break-inside:avoid}\n thead{display:table-header-group}\n svg{max-width:100%}\n p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\n h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n #header,#content,#footnotes,#footer{max-width:none}\n #toc,.sidebarblock,.exampleblock>.content{background:none!important}\n #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\n body.book #header{text-align:center}\n body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\n body.book #header .details{border:0!important;display:block;padding:0!important}\n body.book #header .details span:first-child{margin-left:0!important}\n body.book #header .details br{display:block}\n body.book #header .details br+span::before{content:none!important}\n body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\n body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n .listingblock code[data-lang]::before{display:block}\n #footer{padding:0 .9375em}\n .hide-on-print{display:none!important}\n .print-only{display:block!important}\n .hide-for-print{display:none!important}\n .show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n .sect1{padding:0!important}\n .sect1+.sect1{border:0}\n #footer{background:none}\n #footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}";
20191
-
20192
- // ESM port of lib/asciidoctor/stylesheets.rb
20193
- //
20194
- // Ruby-to-JavaScript notes:
20195
- // - Singleton: Ruby @__instance__ = new → module-level instance exported as Stylesheets.instance
20196
- // - primary_stylesheet_data memoisation: Ruby ||= → the CSS is a static import; no lazy load needed
20197
- // - File.read(...).rstrip → CSS is inlined at build time in src/data/stylesheet-data.js
20198
- // - STYLESHEETS_DIR = File.join(DATA_DIR, 'stylesheets') → not needed; CSS is a JS module
20199
- // - coderay / pygments methods → omitted (SyntaxHighlighter.for not needed here)
20200
-
20201
-
20202
- class StylesheetsClass {
20203
- static DEFAULT_STYLESHEET_NAME = 'asciidoctor.css'
20204
-
20205
- get primaryStylesheetName() {
20206
- return StylesheetsClass.DEFAULT_STYLESHEET_NAME
20207
- }
20208
-
20209
- async primaryStylesheetData() {
20210
- return defaultStylesheetData
20211
- }
20212
-
20213
- async embedPrimaryStylesheet() {
20214
- return `<style>\n${defaultStylesheetData}\n</style>`
20215
- }
20216
- }
20217
-
20218
- const Stylesheets = {
20219
- instance: new StylesheetsClass(),
20220
- };
20221
-
20222
20759
  // ESM port of converter/html5.rb
20223
20760
  //
20224
20761
  // Ruby-to-JavaScript notes:
@@ -21973,32 +22510,13 @@ Your browser does not support the video tag.
21973
22510
 
21974
22511
  // NOTE expose readSvgContents for Bespoke converter
21975
22512
  async readSvgContents(node, target) {
21976
- const imagesdir = node.document.getAttribute('imagesdir');
21977
- let resolvedPath;
21978
- let svg;
21979
- if (isUriish(target) || (imagesdir && isUriish(imagesdir))) {
21980
- svg = await node.readContents(target, {
21981
- start: imagesdir,
21982
- normalize: true,
21983
- warnOnFailure: true,
21984
- label: 'SVG',
21985
- });
21986
- resolvedPath = target;
21987
- } else {
21988
- resolvedPath = node.normalizeSystemPath(target, imagesdir, null, {
21989
- targetName: 'image',
21990
- });
21991
- svg = await node.readAsset(resolvedPath, {
21992
- normalize: true,
21993
- warnOnFailure: true,
21994
- label: 'SVG',
21995
- });
21996
- }
21997
- if (svg == null) return null // file not found/readable; warning already emitted
21998
- if (!svg) {
21999
- node.logger.warn(`contents of SVG is empty: ${resolvedPath}`);
22000
- return null
22001
- }
22513
+ let svg = await node.readContents(target, {
22514
+ start: node.document.getAttribute('imagesdir'),
22515
+ normalize: true,
22516
+ label: 'SVG',
22517
+ warnIfEmpty: true,
22518
+ });
22519
+ if (!svg) return null
22002
22520
  if (!svg.startsWith('<svg')) svg = svg.replace(SvgPreambleRx, '');
22003
22521
  // Fix incomplete SVG start tag (missing closing >) by inserting > before the first child element.
22004
22522
  // This handles cases like: <svg width="500"\n<circle .../> where the > is missing.
@@ -22534,7 +23052,7 @@ class TemplateConverter extends ConverterBase {
22534
23052
 
22535
23053
  let entries;
22536
23054
  try {
22537
- entries = await node_fs.promises.readdir(templateDir);
23055
+ entries = (await node_fs.promises.readdir(templateDir)).sort();
22538
23056
  } catch {
22539
23057
  return result
22540
23058
  }
@@ -24705,6 +25223,8 @@ exports.DocumentTitle = DocumentTitle;
24705
25223
  exports.Extensions = Extensions;
24706
25224
  exports.Footnote = Footnote;
24707
25225
  exports.Html5Converter = Html5Converter;
25226
+ exports.HttpCache = HttpCache;
25227
+ exports.HttpCacheManager = HttpCacheManager;
24708
25228
  exports.ImageReference = ImageReference;
24709
25229
  exports.IncludeProcessor = IncludeProcessor;
24710
25230
  exports.Inline = Inline;
@@ -24713,6 +25233,7 @@ exports.List = List;
24713
25233
  exports.ListItem = ListItem;
24714
25234
  exports.Logger = Logger;
24715
25235
  exports.LoggerManager = LoggerManager;
25236
+ exports.MemoryHttpCache = MemoryHttpCache;
24716
25237
  exports.MemoryLogger = MemoryLogger;
24717
25238
  exports.NullLogger = NullLogger;
24718
25239
  exports.Postprocessor = Postprocessor;