asciisourcerer 0.1.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95a070a99788cf778b389f7e78810695d8461c31ba7480fc0c4d877a110a1b9a
4
- data.tar.gz: a993ba2270a205d38b39de83be2a8d9671d9b1a1224213d4935244e481638c06
3
+ metadata.gz: abee321c7941006227f85f6a006a9b6ea795f8bcfd0e5c3a5837b11400e43a23
4
+ data.tar.gz: 92dc5d0bfb4435f1d1a42a558ed1aa975d297aff3201a4cd40266da21e86f816
5
5
  SHA512:
6
- metadata.gz: f16ebd7d4f868d7864c8c17e923b817f6d54ec8b155cf4b3bdcb90ec58f1c8f6d1570610b9086008177d995619ed551931117d52f71534af7306a68ac25a4383
7
- data.tar.gz: 575747ad2af8032b928126e9294e26bb18268c4c9097cae2fd8757909450a0826079f57bbb1b96711b53db3001dfed02ddc199d48a175ee57ca467ae68bf678f
6
+ metadata.gz: 70c932c2a7875d27cec949952bc413dce9c240fe19f8fabbcd756bfa1c94d970d0d9d217538d68c2fb7325b4040dc9cae4ad71fa4c595ab89a8ffa6b650aab1d
7
+ data.tar.gz: 39b7c3e368ed5149012f4e07d6c33809d6b11e5e82e75f8562ab5edae9fde98b32928407801cdd6941951d375ac488c008b2857d3378a2115c4767b398194f1a
data/README.adoc CHANGED
@@ -1,38 +1,52 @@
1
- :page-layout: default
2
- :page-permalink: /docs
3
- :page-nav_order: 1
4
1
  = AsciiSourcerer
5
2
  // tag::ai-prompt[]
6
3
  // Collects AsciiDoc content for presenting to a generative AI prompt
7
4
  // Other AI-only prompt matter could go here
8
- // tag::globals[]
9
- :docopslab_git_www: https://github.com/DocOps
10
- :this_prod_slug: asciisourcerer
11
- :asciisourcerer_prod_repo: {docopslab_git_www}/{this_prod_slug}
12
- :asciisourcerer_prod_repo_files_path: {asciisourcerer_prod_repo}/blob/main
13
- :this_prod_repo: {asciisourcerer_prod_repo}
14
- :this_prod_vrsn_major: 0
15
- :this_prod_vrsn_minor: 1
16
- :this_prod_vrsn_major-minor: {this_prod_vrsn_major}.{this_prod_vrsn_minor}
17
- :this_prod_vrsn_patch: 0
18
- :this_prod_vrsn: {this_prod_vrsn_major-minor}.{this_prod_vrsn_patch}
19
- :next_prod_vrsn: 0.2.0
20
- // Default configuration values - single source of truth for config-def.yml
21
- :this_prod_repo_branch: {this_prod_repo}/tree/release/{this_prod_vrsn_major-minor}
5
+ // tag::global-settings[]
6
+ :this_proj_slug: asciisourcerer
7
+ :this_proj_name: AsciiSourcerer
8
+ // tag::universal-settings[]
9
+ // ALL changes within this block must be made in prime template:
10
+ // DocOps/lab/gems/docopslab-dev/templates/README.asciidoc
11
+ :docopslab_src_www_url: https://github.com/DocOps
12
+ :docopslab_domain: docopslab.org
13
+ :docopslab_www_url: https://{docopslab_domain}
14
+ :docopslab_io_www_url: https://docopslab.github.io
15
+ :docopslab_ruby_version: 3.2.7
16
+ :docopslab_src_www_url: https://raw.githubusercontent.com/DocOps
17
+ :docopslab_git_src_uri: git@github.com:DocOps
18
+ :this_proj_src_www_url: {docopslab_src_www_url}/{this_proj_slug}
19
+ :this_proj_src_raw_url: https://raw.githubusercontent.com/DocOps/{this_proj_slug}/main
20
+ :this_proj_src_main_files_url: {this_proj_src_www_url}/blob/main
21
+ :this_proj_src_git_uri: {docopslab_git_src_uri}/{this_proj_slug}.git
22
+ :this_proj_ruby_version: {docopslab_ruby_version}
23
+ // tag::env-settings[]
24
+ :docs_extn:
22
25
  ifdef::env-github[]
23
26
  :docs_extn: .adoc
24
- :asciisourcerer_www: https://asciisourcerer.docopslab.org
25
- :asciisourcerer_docs_www: {asciisourcerer_www}/docs
26
- :default-config_www: {asciisourcerer_docs_www}/sample-config.html
27
- :this_prod_docs_www: {asciisourcerer_docs_www}
28
- endif::[]
29
- ifndef::env-github[]
30
- :docs_extn:
27
+ :icons: font
28
+ :caution-caption: :fire:
29
+ :important-caption: :exclamation:
30
+ :note-caption: :paperclip:
31
+ :tip-caption: :bulb:
32
+ :warning-caption: :warning:
31
33
  endif::[]
32
- // end::globals[]
34
+ // end::env-settings[]
35
+ // Settings likely to be overridden locally
36
+ :this_prod_slug: {this_proj_slug}
37
+ :this_prod_name: {this_proj_name}
38
+ // end::universal-settings[]
39
+ :this_prod_vrsn_major: 0
40
+ :this_prod_vrsn_minor: 2
41
+ :this_prod_vrsn_majmin: {this_prod_vrsn_major}.{this_prod_vrsn_minor}
42
+ :this_prod_vrsn_patch: 1
43
+ :this_prod_vrsn: {this_prod_vrsn_majmin}.{this_prod_vrsn_patch}
44
+ :next_prod_vrsn: 0.3.0
45
+ // end::global-settings[]
33
46
  :toc: macro
34
- :toclevels: 3
35
-
47
+ :toclevels: 4
48
+ :this_prod_repo_files_path: {this_proj_src_www_url}/tree/main
49
+ :imagesdir: ./specs/docs
36
50
 
37
51
  AsciiSourcerer is a Ruby library for radical single-sourcing of documentation and product data, primarily from AsciiDoc, YAML, and Liquid templating operations.
38
52
 
@@ -47,31 +61,51 @@ Its end user base is expected to be Ruby developers; for user-friendlier applica
47
61
  The core module is canonically called `Sourcerer` and is usually referred to as such in documentation.
48
62
  The module `AsciiSourcerer` serves as an alias to `Sourcerer` in case of namespace conflicts.
49
63
 
64
+ toc::[]
65
+
50
66
  [[capabilities]]
51
67
  === Capabilities
52
68
 
53
69
  The API focuses on a small set of robust primitives that downstream tools can compose.
54
70
 
71
+ [qanda]
55
72
  AsciiDoc extraction::
56
73
  Load attributes, transclude tagged snippets, extract tagged regions, and convert documents from AsciiDoc source files.
57
74
 
58
75
  Tag-aware YAML loading::
59
76
  Load YAML files while preserving custom tags and optionally resolving embedded AsciiDoc attributes and Liquid/ERB template syntax.
60
77
 
78
+ Text syncing in source files::
79
+ Synchronise canonical tagged blocks from a prime template into project-local files.
80
+ Supports one-time bootstrapping, ongoing sync, Liquid rendering within managed blocks, and dry-run diffing.
81
+ See <<sync-cast>>.
82
+
61
83
  Templating and rendering::
62
84
  Render Liquid or ERB templates against YAML data or AsciiDoc attributes.
63
85
 
64
86
  Liquid runtime integration::
65
87
  Initialize a Jekyll-routed Liquid runtime with DocOps Lab filters and tags, so Jekyll-compatible templates behave predictably.
88
+ See <<templating-liquid-runtime>>.
66
89
 
67
90
  Build-time generation::
68
91
  Generate prebuild artifacts (attributes, snippets, regions) for downstream builds and runtime access.
92
+ See <<pipelines>>.
69
93
 
70
94
  AsciiDoc-to-manpage conversion::
71
95
  Build manpages for apps from the docs.
72
96
 
73
97
  AsciiDoc-to-Markdown conversion::
74
98
  Convert AsciiDoc documents to Markdown for agentic consumption, with a focus on preserving semantic structure and document frontmatter.
99
+ See <<markdowngrade>>.
100
+
101
+ AsciiDoc source inspection::
102
+ Skim AsciiDoc documents to produce machine-oriented outlines of sections, code blocks, tables, and other semantic elements for tooling and agent consumption.
103
+ See <<source-skim>>.
104
+
105
+ General-purpose utilities::
106
+ Small, dependency-light primitives for list amendment and path classification/enumeration, available under `Sourcerer::Util`.
107
+ Not required internally; useful for downstream callers and scripts.
108
+ See <<utilities>>.
75
109
 
76
110
  All of these operations are meant to be available even before resources like SchemaGraphy and LiquiDoc are loaded.
77
111
  Most are best invoked via a <<integrations,downstream API or utility>>, where robust services for _input_ (file read), _output_ (file write), _configuration_, _scripting_, and contextual _enrichment_ may be available via CLI or API.
@@ -89,6 +123,7 @@ AsciiDoc attributes are key-value pairs defined in AsciiDoc documents that can b
89
123
 
90
124
  tagged regions::
91
125
  Sections of source files demarcated by `tag::` and `end::` markers, which can be extracted as content snippets for reuse in documentation or other outputs.
126
+ Tagged regions can also be used by <<sync-cast>> to identify content blocks for synchronization across _source_ files.
92
127
 
93
128
  YAML tags::
94
129
  Custom YAML tags (ex: `!liquid`, `!attribute`) that provide special processing instructions during YAML loading.
@@ -114,6 +149,10 @@ Extract attributes and tagged content from AsciiDoc into artifacts that are load
114
149
  Converter flow::
115
150
  Use a custom converter (callable or constant name) to produce specialized output without embedding converter logic into the core rendering pipeline.
116
151
 
152
+ Source inspection flow::
153
+ Skim an AsciiDoc source document to produce a structured, JSON-ready outline of its sections and key block elements for tooling and agents.
154
+ See <<source-skim>>.
155
+
117
156
  [[quickstart]]
118
157
  === Quickstart
119
158
 
@@ -122,7 +161,7 @@ Add `asciisourcerer` to your application using Bundler.
122
161
  .Gemfile addition
123
162
  [source,ruby,subs=+attributes]
124
163
  ----
125
- gem 'asciisourcerer', '~> {this_prod_vrsn_major-minor}'
164
+ gem 'asciisourcerer', '~> {this_prod_vrsn_majmin}'
126
165
  ----
127
166
 
128
167
  Then require and use it in your Ruby code.
@@ -137,6 +176,7 @@ Primary API namespaces:
137
176
  * `Sourcerer::Yaml` for YAML loading with tag preservation and optional attribute resolution.
138
177
  * `Sourcerer::Yaml::TagUtils` for tag helper methods (`detag`, `tag_of`, `tag?`).
139
178
  * `Sourcerer::Rendering` for template rendering and output orchestration.
179
+ * `Sourcerer::Sync` for canonical block synchronization (<<sync-cast>>).
140
180
 
141
181
  The top-level `Sourcerer.*` methods remain as compatibility delegators.
142
182
  This layer is actually *deprecated* and will be removed in AsciiSourcerer 1.0.
@@ -169,7 +209,7 @@ Sourcerer::AsciiDoc.generate_html(
169
209
 
170
210
  If `asciidoctor-html5s` is unavailable at runtime, Sourcerer falls back to the standard `html5` backend.
171
211
 
172
- [[markdown-grade]]
212
+ [[markdowngrade]]
173
213
  === MarkDownGrade (AsciiDoc -> Markdown)
174
214
 
175
215
  `Sourcerer::MarkDownGrade` handles HTML-to-Markdown adaptation.
@@ -217,8 +257,8 @@ markdown = Sourcerer::MarkDownGrade.convert_html(
217
257
  puts(markdown)
218
258
  ----
219
259
 
220
- [[markdown-grade-migration]]
221
- === Migration Mini-Guide (DocOps Lab)
260
+ [[markdowngrade-migration]]
261
+ ==== Migration Mini-Guide (DocOps Lab)
222
262
 
223
263
  For consumers currently using `DocOps/lab/scripts/mark_down_grade.rb`, migrate to Sourcerer in two steps.
224
264
 
@@ -235,7 +275,99 @@ Step 2: Verify parity, then remove duplicate script::
235
275
  Recommended follow-through::
236
276
  * Redirect or retire `lab/scripts/README-mark_down_grade.adoc` so AsciiSourcerer remains source-of-truth.
237
277
 
238
- [[templating-and-liquid-runtime]]
278
+ [[sync-cast]]
279
+ === Sync/Cast: Canonical Block Synchronization
280
+
281
+ Sync/Cast keeps a set of _canonical blocks_ consistent across multiple files.
282
+ Here are some feature-specific terms.
283
+
284
+ prime template::
285
+ A source file containing canonical blocks intended to be synchronised into one or more project-local target files.
286
+
287
+ target file::
288
+ A project-local file that receives synchronised content from a prime template.
289
+ All content outside canonical blocks is preserved verbatim.
290
+
291
+ canonical block::
292
+ A tagged region whose content is owned by the synchronization system.
293
+ Identified by a configurable prefix; the default is `universal-`.
294
+ Override it per call with the `canonical_prefix:` keyword argument.
295
+
296
+ [[sync-cast-tag-syntax]]
297
+ ==== Tag syntax
298
+
299
+ Canonical blocks use AsciiDoc-style `tag::`/`end::` markers embedded inside comments.
300
+ Three comment styles are recognized so the same prime can manage files of any type:
301
+
302
+ [cols="3m,5m",options="header"]
303
+ |===
304
+ | Style | Example
305
+ | HTML / Markdown comment
306
+ | <!-- tag::universal-intro[] -->
307
+ | AsciiDoc line comment
308
+ | // tag::universal-intro[]
309
+ | Shell / Ruby / YAML comment
310
+ | # tag::universal-intro[]
311
+ |===
312
+
313
+ The trailing `[]` is optional in all three styles.
314
+
315
+ A tag whose name begins with the configured prefix (default `universal-`) is treated as canonical and managed by Sync/Cast.
316
+ All other tagged regions in a target file are left entirely alone, and their presence beside a canonical block never triggers a warning.
317
+
318
+ [[sync-cast-operations]]
319
+ ==== Operations
320
+
321
+ init::
322
+ One-time operation that renders the prime template (the whole file, not just canonical blocks) through Liquid and writes the result as a new target file.
323
+ Use this to bootstrap a repo-local copy of a project template.
324
+
325
+ sync::
326
+ Ongoing operation that scans for canonical blocks, replaces their content with the prime version (after optional Liquid rendering), and leaves everything else verbatim.
327
+
328
+ dry_run: true::
329
+ Pass `dry_run: true` to either operation to compute the result without writing any file.
330
+ The `result.diff` file contains the rendered content (`init`) or a unified diff (`sync`).
331
+
332
+ [NOTE]
333
+ ====
334
+ If a canonical block is absent from a target file, `sync` emits a warning.
335
+ That warning is suppressed when the target contains a non-canonical tag sharing the same suffix — for example, `local-intro` alongside canonical `universal-intro` — indicating a deliberate project-local override.
336
+ ====
337
+
338
+ [[sync-cast-liquid]]
339
+ ==== Liquid variables in blocks
340
+
341
+ Pass a plain Ruby `Hash` as `data:` and its top-level keys become Liquid variables inside every canonical block.
342
+ Nested values follow Liquid dot notation.
343
+
344
+ During `sync`, only canonical block content is rendered.
345
+ During `init`, the entire prime template is rendered.
346
+ Local content in target files is never rendered.
347
+
348
+ [source,markdown]
349
+ ----
350
+ <!-- tag::universal-intro[] -->
351
+ This is {{ data.variables.name }} version {{ data.variables.version }}.
352
+ <!-- end::universal-intro[] -->
353
+ ----
354
+
355
+ [[sync-cast-bootstrap]]
356
+ ==== Bootstrap example
357
+
358
+ [source,ruby]
359
+ ----
360
+ Sourcerer::Sync.init(
361
+ 'templates/AGENTS.markdown',
362
+ 'AGENTS.md',
363
+ data: { 'project' => 'my-gem', 'org' => 'DocOps' }
364
+ )
365
+ ----
366
+
367
+ Parent directories are created automatically.
368
+ Pass `dry_run: true` to return the rendered content in `result.diff` without writing any file.
369
+
370
+ [[templating-liquid-runtime]]
239
371
  === Templating and Liquid Runtime
240
372
 
241
373
  Sourcerer supports Liquid and ERB, but its Liquid support is intentionally aligned with Jekyll’s runtime.
@@ -284,6 +416,169 @@ Downstream filter responsibility::
284
416
  Sourcerer ships generic Liquid utility filters only.
285
417
  Schema-aware filters (including SGYML-specific classification filters) should be provided by downstream tooling such as SchemaGraphy and/or ReleaseHx.
286
418
 
419
+ [[source-skim]]
420
+ === SourceSkim
421
+
422
+ `Sourcerer::SourceSkim` generates machine-oriented _skims_ of AsciiDoc source documents.
423
+
424
+ A skim is a structured, JSON/YAML-ready outline of selected source elements:
425
+ sections, code blocks, definition lists, tables, images, and more.
426
+ Skims are intended to help tooling and agents inspect documentation source without ingesting full file contents.
427
+
428
+ .Example: Skim a file for sections and code blocks
429
+ [source,ruby]
430
+ ----
431
+ # Tree sections by default
432
+ skim = Sourcerer::SourceSkim.skim_file('docs/install.adoc')
433
+
434
+ # Both tree and flat section shapes
435
+ skim = Sourcerer::SourceSkim.skim_file('docs/install.adoc', forms: [:tree, :flat])
436
+
437
+ # Restrict to specific categories
438
+ skim = Sourcerer::SourceSkim.skim_file('docs/install.adoc', categories: [:code_blocks, :tables])
439
+
440
+ # Skim inline content
441
+ skim = Sourcerer::SourceSkim.skim_string(raw_adoc_content)
442
+ ----
443
+
444
+ Section shapes::
445
+ Pass `forms: [:tree]` (default), `forms: [:flat]`, or both.
446
+ Tree shape preserves nesting; flat shape adds `parent_id` and expresses child section IDs as an array.
447
+
448
+ Categories::
449
+ Default output includes `attributes_custom`, `definition_lists`, `code_blocks`, `literal_blocks`, `examples`, `sidebars`, `tables`, and `images`.
450
+ Opt-in only (excluded by default): `attributes_builtin`, `admonitions`, `quotes`.
451
+ Pass `categories:` with an explicit array of symbols to restrict or expand output.
452
+
453
+ Output reference::
454
+ The skim output schema is at `specs/data/asciidoc-source-skim.schema.json` and a YAML model reference at `specs/data/asciidoc-source-skim-model.yaml`.
455
+
456
+ [[skim-asciidoctor-extension]]
457
+ ==== Asciidoctor extension
458
+ `Sourcerer::SourceSkim::TreeProcessorExtension` integrates SourceSkim into Asciidoctor parsing pipelines.
459
+ It stores the result as the `source-skim-result` document attribute and reads `source-skim-forms` and `source-skim-categories` document attributes for per-document configuration.
460
+
461
+ .Register the extension
462
+ [source,ruby]
463
+ ----
464
+ require 'asciidoctor/extensions/source-skim-tree-processor/extension'
465
+ Asciidoctor::Extensions.register Sourcerer::SourceSkim::TreeProcessorExtension
466
+ ----
467
+
468
+
469
+ [[utilities]]
470
+ === Utilities
471
+
472
+ `Sourcerer::Util` hosts small, dependency-light primitives intended for use by downstream callers and scripts.
473
+ They are not required internally; require the appropriate file explicitly when you need it.
474
+
475
+ Neither utility carries any new runtime dependencies beyond the standard library.
476
+
477
+ [[util-list-amend]]
478
+ ==== `Sourcerer::Util::ListAmend`
479
+
480
+ Merges a user-supplied list into a default list using `+`/`-` amendment tokens.
481
+
482
+ .Require
483
+ [source,ruby]
484
+ ----
485
+ require 'sourcerer/util/list_amend'
486
+ ----
487
+
488
+ .API
489
+ [source,ruby]
490
+ ----
491
+ Sourcerer::Util::ListAmend.apply(default_list, custom_list, normalize: nil) -> Array<String>
492
+ ----
493
+
494
+ Behavior::
495
+ `nil` / empty custom:::
496
+ Returns `default_list` (stringified) unchanged.
497
+ Fixed-list mode:::
498
+ If `custom_list` contains *no* tokens starting with `+` or `-`, it fully replaces `default_list`.
499
+ Amendment mode:::
500
+ If `custom_list` contains *any* `+`/`-` token:
501
+ `-slug` removes `slug` from the working set (or no-op if absent). +
502
+ `+slug` adds `slug` if not already present. +
503
+ bare `slug` is treated as `+slug`.
504
+
505
+ `normalize` (optional)::
506
+ A callable used to compare items during deduplication and removal, for example `->(s) { s.downcase }`.
507
+
508
+ .Examples
509
+ [source,ruby]
510
+ ----
511
+ defaults = %w[a b c]
512
+
513
+ # nil → unchanged
514
+ Sourcerer::Util::ListAmend.apply(defaults, nil) # => ["a", "b", "c"]
515
+
516
+ # fixed list
517
+ Sourcerer::Util::ListAmend.apply(defaults, "b c") # => ["b", "c"]
518
+
519
+ # amendment: remove b, add d
520
+ Sourcerer::Util::ListAmend.apply(defaults, "-b +d") # => ["a", "c", "d"]
521
+
522
+ # amendment: bare token treated as addition
523
+ Sourcerer::Util::ListAmend.apply(defaults, "-b d") # => ["a", "c", "d"]
524
+ ----
525
+
526
+ [[util-pathifier]]
527
+ ==== `Sourcerer::Util::Pathifier`
528
+
529
+ Classifies an input string as `:file`, `:dir`, `:glob`, or `:missing` and provides a lazy enumerator of matching paths.
530
+ Directory traversal is enumerator-based to avoid materializing large path arrays.
531
+
532
+ .Require
533
+ [source,ruby]
534
+ ----
535
+ require 'sourcerer/util/path_matcher'
536
+ ----
537
+
538
+ .API
539
+ [source,ruby]
540
+ ----
541
+ result = Sourcerer::Util::Pathifier.match(input, recursive: true, include_dirs: false, follow_symlinks: false)
542
+ # result.type -> :file | :dir | :glob | :missing
543
+ # result.input -> original input string
544
+ # result.enum -> Enumerator<String> of matching paths
545
+ ----
546
+
547
+ Classification rules::
548
+ `:file`::: `File.file?(input)` is true.
549
+ `:dir`::: `File.directory?(input)` is true.
550
+ `:glob`::: Input contains glob metacharacters (`* ? [ ] { }`).
551
+ `:missing`::: None of the above.
552
+
553
+ Options::
554
+ `recursive`::: Traverse directories recursively via `Find.find` (default: `true`).
555
+ `include_dirs`::: Also yield directory paths during traversal (default: `false`).
556
+ `follow_symlinks`::: Follow symlink directories during recursion (default: `false`).
557
+
558
+ .Examples
559
+ [source,ruby]
560
+ ----
561
+ # File
562
+ r = Sourcerer::Util::Pathifier.match('docs/install.adoc')
563
+ r.type # => :file
564
+ r.enum.to_a # => ["/absolute/path/docs/install.adoc"]
565
+
566
+ # Directory (lazy recursive)
567
+ r = Sourcerer::Util::Pathifier.match('docs/')
568
+ r.type # => :dir
569
+ r.enum.select { |p| p.end_with?('.adoc') } # lazy filter
570
+
571
+ # Glob
572
+ r = Sourcerer::Util::Pathifier.match('docs/**/*.adoc')
573
+ r.type # => :glob
574
+ r.enum.to_a # => all matching files
575
+
576
+ # Missing
577
+ r = Sourcerer::Util::Pathifier.match('no/such/path')
578
+ r.type # => :missing
579
+ r.enum.to_a # => []
580
+ ----
581
+
287
582
 
288
583
  [[integrations]]
289
584
  == Integrations (Implemented and Planned)
@@ -291,6 +586,9 @@ Schema-aware filters (including SGYML-specific classification filters) should be
291
586
  These notes describe how AsciiSourcerer relates to existing and future downstream tools.
292
587
  For most users, these tools are the recommended way to access AsciiSourcerer’s capabilities, since they provide a richer context for configuration, input/output management, and workflow orchestration.
293
588
 
589
+ https://github.com/DocOps/lab/tree/main/gems/docopslab-dev[docopslab-dev]::
590
+ A harness for DocOps Lab developer tasks and operations.
591
+
294
592
  SchemaGraphy::
295
593
  SchemaGraphy's API is the schema-aware layer in the DocOps Lab ecosystem.
296
594
  Sourcerer provides it with primitives such as YAML loading, templating, and Liquid runtime setup, while SchemaGraphy handles schema validation and templated-field interpretation.
@@ -306,6 +604,28 @@ Jekyll Extensions::
306
604
  DocOps Labs maintains plugins, themes, and even a utility for generating technical documentation with the Jekyll static-site generator.
307
605
  All the benefits of extended YAML ingest and Liquid processing are available via these extensions, along with and usually through SchemaGraphy.
308
606
 
607
+ [[alpha-scripts]]
608
+ === Alpha Scripts/CLIs
609
+
610
+ The AsciiSourcerer repo does host some CLI utilities and scripts that make direct usage of APIs hosted in the `asciisourcerer` gem.
611
+ These are largely prototype utilities that will eventually make it into official DocOps Lab applications with proper I/O surfaces.
612
+
613
+ [WARNING]
614
+ These scripts are *neither* rigorously tested *nor* officially supported.
615
+ They may be altered, deprecated, or dropped in backward-incompatible ways.
616
+ Use them as examples but do not rely on them in production.
617
+
618
+ To use such a script, copy it from the repo's `scripts/` directory into your project, then run it with `ruby` or `bundle exec ruby` as appropriate.
619
+
620
+ Current scripts include::
621
+ `skim_asciidoc.rb`:::
622
+ For AsciiDoc source inspection.
623
+ Generates YAML or JSON versions of `Sourcerer::SourceSkim` output for a given AsciiDoc document or collection of documents.
624
+
625
+ `mark_down_grade.rb`:::
626
+ For AsciiDoc-to-Markdown conversion.
627
+ This script orchestrates `Sourcerer::AsciiDoc.mark_down_grade` and is a recommended starting point for users needing this functionality without building their own Ruby integration.
628
+
309
629
 
310
630
  [[development]]
311
631
  == Development
@@ -343,7 +663,7 @@ Special developer Rake tasks and libraries are available via the `docopslab-dev`
343
663
  [.prompt]
344
664
  bundle exec rake --tasks | grep labdev:
345
665
 
346
- The link:{docopslab_git_www}/lab/tree/main/gems/docopslab-dev/README.adoc[DocOps Lab Devtool] or see `.agent/docs/topics/docpslab-devtool.md`.
666
+ The link:{docopslab_src_www_url}/lab/tree/main/gems/docopslab-dev/README.adoc[DocOps Lab Devtool] or see `.agent/docs/topics/docpslab-devtool.md`.
347
667
 
348
668
  [[api]]
349
669
  === API Design
@@ -354,13 +674,19 @@ The top-level `Sourcerer.*` methods are deprecated in favor of direct namespace
354
674
  Do not add new public methods directly to the `Sourcerer` namespace;
355
675
  instead, add them to the appropriate submodule.
356
676
 
357
- Ruby API shape policy::
677
+ [[api-shape-policy]]
678
+ ==== Ruby API shape policy
679
+
358
680
  Use singleton methods (`def self.*`) on namespace modules for stateless primitives.
681
+
359
682
  Use classes when behavior is naturally stateful or lifecycle-driven.
683
+
360
684
  Use mixin modules for host-integration surfaces (for example, Liquid filters/tags) where the host expects instance methods.
361
- For mixin modules, keep public entrypoints as thin wrappers and place transformation logic in an internal helper module/object.
685
+ Keep public entrypoints as thin wrappers and place transformation logic in an internal helper module/object.
686
+
687
+ [[visibility-policy]]
688
+ ==== Visibility policy
362
689
 
363
- Visibility policy::
364
690
  Use `private_class_method` for singleton helper methods defined with `def self.*`.
365
691
  Use `private` for instance helper methods in classes or mixins.
366
692
  Avoid exporting helper methods as accidental public API.
@@ -368,7 +694,7 @@ Avoid exporting helper methods as accidental public API.
368
694
  [[tests]]
369
695
  === Tests
370
696
 
371
- See the full testing documentation at link:{asciisourcerer_prod_repo_files_path}[`specs/tests/README.adoc`]
697
+ See the full testing documentation at link:{this_prod_repo_files_url}/specs/tests/README.adoc[`specs/tests/README.adoc`]
372
698
 
373
699
  Run the RSpec suite:
374
700
 
@@ -385,6 +711,36 @@ Run the PR/CI test suite:
385
711
  [.prompt]
386
712
  bundle exec rake pr_test
387
713
 
714
+ [[release-process]]
715
+ === Release Process and History
716
+
717
+ AsciiSourcerer is intended to be the most primal gem in the DocOps Lab pool.
718
+ As such, its development is less formal.
719
+
720
+ Each release is tested against all downstream gems and tools, but we are somewhat less formal about issue tracking and development branch management, at least in early stages.
721
+
722
+ Standard release flow:
723
+
724
+ . Update version in `lib/sourcerer/version.rb` and `README.adoc` attributes.
725
+
726
+ . Commit to Git.
727
+
728
+ . Push to GitHub.
729
+
730
+ . Run `./scripts/build.sh` to validate the environment, run tests, and build the gem file to `pkg/`.
731
+
732
+ . Publish to RubyGems.
733
+ +
734
+ RUBYGEMS_API_KEY=<rubygems.org key> ./scripts/publish.sh
735
+
736
+ . Tag the release in Git:
737
+ +
738
+ [.prompt,subs=+attributes]
739
+ git tag v{this_prod_vrsn} && git push origin v{this_prod_vrsn}`.
740
+
741
+ [NOTE]
742
+ AsciiSourcerer does not yet publish a release history document.
743
+
388
744
 
389
745
  [[legal]]
390
746
  == Legal
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'asciidoctor/extensions'
4
+ require_relative '../../../sourcerer/source_skim'
5
+
6
+ module Sourcerer
7
+ module SourceSkim
8
+ # Asciidoctor TreeProcessor extension that runs a SourceSkim pass on the
9
+ # document immediately after parsing and stores the result as the document
10
+ # attribute +source-skim-result+.
11
+ #
12
+ # The skim is keyed by symbol (+:title+, +:sections_tree+, etc.) so it is
13
+ # ready for direct use in Ruby without a JSON round-trip.
14
+ #
15
+ # == Configuration via document attributes
16
+ #
17
+ # +source-skim-forms+:: Comma-separated list of section shapes to emit.
18
+ # Recognized values: +tree+, +flat+. Default: +tree+.
19
+ # +source-skim-categories+:: Comma-separated list of element categories to
20
+ # include. Omit to use the default set (everything except
21
+ # +attributes_builtin+).
22
+ #
23
+ # == Usage
24
+ #
25
+ # === API
26
+ #
27
+ # require 'asciidoctor/extensions/source-skim-tree-processor/extension'
28
+ #
29
+ # Asciidoctor::Extensions.register Sourcerer::SourceSkim::TreeProcessorExtension
30
+ #
31
+ # doc = Asciidoctor.load_file('my.adoc', safe: :safe, sourcemap: true)
32
+ # skim = doc.attr('source-skim-result')
33
+ #
34
+ # === With asciidoctor CLI
35
+ #
36
+ # asciidoctor -r ./lib/asciidoctor/extensions/source-skim-tree-processor/extension.rb \
37
+ # -a source-skim-forms=tree,flat \
38
+ # -a source-skim-categories=sections,code_blocks,admonitions \
39
+ # my.adoc
40
+ class TreeProcessorExtension < Asciidoctor::Extensions::TreeProcessor
41
+ def process document
42
+ raw_forms = document.attr('source-skim-forms', 'tree')
43
+ forms = raw_forms.split(',').map { |f| f.strip.to_sym }
44
+
45
+ raw_cats = document.attr('source-skim-categories')
46
+ categories = raw_cats&.split(',')&.map { |c| c.strip.to_sym }
47
+
48
+ config = Config.new(forms: forms, categories: categories)
49
+ skim = Skimmer.new.process(document, config: config)
50
+ document.set_attr('source-skim-result', skim)
51
+ nil
52
+ end
53
+ end
54
+ end
55
+ end
@@ -30,3 +30,4 @@ AsciiSourcerer::Rendering = Sourcerer::Rendering
30
30
  AsciiSourcerer::Builder = Sourcerer::Builder
31
31
  AsciiSourcerer::MarkDownGrade = Sourcerer::MarkDownGrade
32
32
  AsciiSourcerer::Jekyll = Sourcerer::Jekyll
33
+ AsciiSourcerer::Sync = Sourcerer::Sync