ligarb 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/ligarb/cli.rb CHANGED
@@ -17,6 +17,10 @@ module Ligarb
17
17
  Builder.new(config_path).build
18
18
  when "init"
19
19
  Initializer.new(args.first).run
20
+ when "setup-github-review"
21
+ require_relative "github_review"
22
+ directory = args.reject { |a| a.start_with?("--") }.first
23
+ GithubReview.run(directory)
20
24
  when "serve"
21
25
  config_paths = args.reject { |a| a.start_with?("--") }
22
26
  config_paths = ["book.yml"] if config_paths.empty?
@@ -67,6 +71,8 @@ module Ligarb
67
71
 
68
72
  Usage:
69
73
  ligarb init [DIRECTORY] Create a new book project
74
+ ligarb setup-github-review [DIRECTORY]
75
+ Set up (or update) GitHub Pages + review workflows
70
76
  ligarb build [CONFIG] Build the HTML book (default CONFIG: book.yml)
71
77
  ligarb serve [CONFIG] Serve the book with live reload and review UI
72
78
  ligarb librarium Serve all */book.yml as a multi-book library
@@ -90,6 +96,7 @@ module Ligarb
90
96
  repository (optional) GitHub repository URL for "Edit on GitHub" links
91
97
  ai_generated (optional) Mark as AI-generated (badge + meta tags, default: false)
92
98
  footer (optional) Custom text at bottom of each chapter
99
+ github_review (optional) Enable the "Report as issue" reader feedback UI ({enabled: true}, needs repository)
93
100
  translations (optional) Map of lang => config path for multi-language builds
94
101
 
95
102
  Example:
@@ -98,632 +105,10 @@ module Ligarb
98
105
  USAGE
99
106
  end
100
107
 
101
- def spec_text
102
- <<~SPEC
103
- ligarb - Generate a single-page HTML book from Markdown files
104
-
105
- Version: #{VERSION}
106
-
107
- == Overview ==
108
-
109
- ligarb converts multiple Markdown files into a self-contained index.html.
110
- The generated HTML includes:
111
- - A left sidebar with a searchable table of contents (h1-h3)
112
- - Chapter-based content switching in the main area
113
- - Permalink support via URL hash (#chapter-slug)
114
- - Responsive design with print-friendly styles
115
- - Syntax-highlighted code blocks
116
- - Search with content highlighting
117
- - Chapter and section numbering (configurable)
118
- - Previous/Next chapter navigation
119
- - Dark mode toggle (saved to localStorage)
120
- - Custom CSS support
121
- - "Edit on GitHub" links (optional)
122
- - Footnotes (kramdown syntax)
123
-
124
- == Commands ==
125
-
126
- ligarb init [DIRECTORY] Create a new book project with scaffolding.
127
- If DIRECTORY is given, creates and populates that directory.
128
- If omitted, populates the current directory.
129
- Generates book.yml, 01-introduction.md, and images/.
130
- If .md files already exist, registers them as chapters.
131
- Aborts if book.yml already exists.
132
-
133
- ligarb build [CONFIG] Build the HTML book.
134
- CONFIG defaults to 'book.yml' in the current directory.
135
-
136
- ligarb serve [CONFIG...]
137
- Start a local web server with live reload and review UI.
138
- CONFIG defaults to 'book.yml' in the current directory.
139
- Multiple CONFIG paths can be given to serve multiple books.
140
- Options:
141
- --port PORT Server port (default: 3000)
142
- --multi Force multi-book mode (even with 1 CONFIG)
143
- Single book mode (1 CONFIG, without --multi):
144
- - Serves the built HTML book at http://localhost:PORT
145
- Multi-book mode (2+ CONFIGs, or --multi):
146
- - Top page (/) shows a book index with links
147
- - Each book is served at /<directory-name>/
148
- - "Write a new book" button on the index page to generate
149
- a new book via AI (posts a brief, runs Writer in background)
150
- - Example: ligarb serve */book.yml
151
- Features:
152
- - Injects a reload button that pulses when build output changes
153
- - Injects a review UI for commenting on book text
154
- - Review comments are saved to .ligarb/reviews/*.json
155
- (in each book's directory)
156
- - If 'claude' CLI is installed, comments are sent to Claude
157
- for review suggestions, and approved changes are applied
158
- to the source Markdown files and the book is rebuilt
159
- - Review patches can span multiple chapters and the
160
- bibliography file (Claude reads book.yml to find all files)
161
-
162
- ligarb librarium Start a multi-book library server.
163
- Automatically discovers */book.yml in the current directory.
164
- Equivalent to: ligarb serve --multi */book.yml
165
- Options:
166
- --port PORT Server port (default: 3000)
167
-
168
- ligarb help Show this detailed specification.
169
-
170
- ligarb --help Show short usage summary.
171
-
172
- ligarb version Show the version number.
173
-
174
- == Configuration: book.yml ==
175
-
176
- The configuration file is a YAML file with the following fields:
177
-
178
- title: (required) The book title displayed in the header and <title> tag.
179
- author: (optional) Author name displayed in the header. Default: empty.
180
- language: (optional) HTML lang attribute value. Default: "en".
181
- output_dir: (optional) Output directory relative to book.yml. Default: "build".
182
- chapter_numbers: (optional) Show chapter/section numbers (e.g. "1.", "1.1", "1.1.1").
183
- Default: true.
184
- style: (optional) Path to a custom CSS file relative to book.yml.
185
- Loaded after the default styles, so it can override any rule.
186
- repository: (optional) GitHub repository URL (e.g. "https://github.com/user/repo").
187
- When set, each chapter shows a "View on GitHub" link.
188
- The link points to {repository}/blob/HEAD/{path-from-git-root}.
189
- The chapter path is resolved relative to the Git repository root.
190
- ai_generated: (optional) Mark the book as AI-generated content. Default: false.
191
- When true: adds an "AI Generated" badge in the sidebar header,
192
- adds a default disclaimer footer to each chapter, and adds
193
- noindex/noai meta tags to prevent search indexing and AI training.
194
- The footer text can be overridden with the 'footer' field.
195
- footer: (optional) Custom text displayed at the bottom of each chapter.
196
- Overrides the default ai_generated disclaimer if both are set.
197
- Useful for copyright notices, disclaimers, or other per-chapter text.
198
- translations: (optional) A mapping of language codes to config file paths.
199
- Enables multi-language support. See "Translations" section below.
200
- chapters: (required) Book structure. An array that can contain:
201
- - A cover: the landing page shown when the book is opened
202
- - A string: a chapter Markdown file path (relative to book.yml)
203
- - A part: groups chapters under a titled section
204
- - An appendix: groups chapters with alphabetic numbering (A, B, C, ...)
205
-
206
- The chapters array supports four element types:
207
-
208
- 1. Cover (object with 'cover' key):
209
- chapters:
210
- - cover: cover.md # Markdown file: landing page shown when the book is opened
211
- # Not shown in the TOC sidebar.
212
-
213
- 2. Plain chapter (string):
214
- chapters:
215
- - 01-introduction.md
216
-
217
- 3. Part (object with 'part' and 'chapters' keys):
218
- chapters:
219
- - part: part1.md # Markdown file: h1 = part title, body = opening text
220
- chapters:
221
- - 01-introduction.md
222
- - 02-getting-started.md
223
-
224
- 4. Appendix (object with 'appendix' key, value is array of chapter files):
225
- chapters:
226
- - appendix:
227
- - a1-references.md
228
- - a2-glossary.md
229
-
230
- These can be combined freely:
231
-
232
- chapters:
233
- - cover: cover.md
234
- - part: part1.md
235
- chapters:
236
- - 01-introduction.md
237
- - 02-getting-started.md
238
- - part: part2.md
239
- chapters:
240
- - 03-advanced.md
241
- - appendix:
242
- - a1-references.md
243
-
244
- Part numbering is sequential across parts (1, 2, 3, ...).
245
- Appendix numbering uses letters (A, B, C, ...).
246
-
247
- Example book.yml (simple):
248
-
249
- title: "My Software Guide"
250
- author: "Author Name"
251
- language: "ja"
252
- chapters:
253
- - 01-introduction.md
254
- - 02-getting-started.md
255
- - 03-advanced.md
256
-
257
- Example book.yml (with parts and appendix):
258
-
259
- title: "My Software Guide"
260
- author: "Author Name"
261
- language: "ja"
262
- chapters:
263
- - part: part1.md
264
- chapters:
265
- - 01-introduction.md
266
- - 02-getting-started.md
267
- - part: part2.md
268
- chapters:
269
- - 03-advanced.md
270
- - 04-deployment.md
271
- - appendix:
272
- - a1-config-reference.md
273
-
274
- == Directory Structure ==
275
-
276
- A typical book project has this structure:
277
-
278
- my-book/
279
- ├── book.yml # Configuration file
280
- ├── part1.md # Part opening page (optional)
281
- ├── 01-introduction.md # Markdown source files
282
- ├── 02-getting-started.md
283
- ├── 03-advanced.md
284
- └── images/ # Image files (optional)
285
- ├── screenshot.png
286
- └── diagram.svg
287
-
288
- After running 'ligarb build', the output is:
289
-
290
- my-book/
291
- └── build/
292
- ├── index.html # Single-page HTML book
293
- ├── js/ # Auto-downloaded (only if needed)
294
- ├── css/ # Auto-downloaded (only if needed)
295
- └── images/ # Copied image files
296
-
297
- == Markdown Files ==
298
-
299
- Each Markdown file represents one chapter. ligarb uses GitHub Flavored
300
- Markdown (GFM) via kramdown. Supported syntax includes:
301
-
302
- - Headings (# h1, ## h2, ### h3) — used for TOC generation
303
- - Code blocks with language-specific syntax highlighting (``` fenced blocks)
304
- - Tables, task lists, strikethrough, and other GFM extensions
305
- - Inline HTML
306
-
307
- The first heading (h1) in each file becomes the chapter title in the TOC.
308
-
309
- == Fenced Code Blocks ==
310
-
311
- The following fenced code block types are automatically detected and
312
- rendered. Required JS/CSS is auto-downloaded on first build to build/js/
313
- and build/css/.
314
-
315
- ```ruby, ```python, etc. Syntax highlighting (highlight.js, BSD-3-Clause)
316
- ```mermaid Diagrams: flowcharts, sequence, bar/line/pie charts,
317
- gantt, mindmap, etc.
318
- (mermaid, MIT)
319
- ```math LaTeX math equations (KaTeX, MIT)
320
- ```functionplot Function graphs (function-plot + d3, MIT)
321
-
322
- These are rendered visually in the output HTML — use them freely.
323
-
324
- Mermaid example (flowchart):
325
-
326
- ```mermaid
327
- graph TD
328
- A[Start] --> B{Check}
329
- B -->|Yes| C[OK]
330
- B -->|No| D[Retry]
331
- ```
332
-
333
- Mermaid example (sequence diagram):
334
-
335
- ```mermaid
336
- sequenceDiagram
337
- Client->>Server: Request
338
- Server-->>Client: Response
339
- ```
340
-
341
- Mermaid example (bar chart):
342
-
343
- ```mermaid
344
- xychart
345
- title "Monthly Sales"
346
- x-axis ["Jan", "Feb", "Mar", "Apr", "May"]
347
- y-axis "Revenue" 0 --> 500
348
- bar [120, 230, 180, 350, 410]
349
- line [120, 230, 180, 350, 410]
350
- ```
351
-
352
- Mermaid example (line chart, line only):
353
-
354
- ```mermaid
355
- xychart
356
- title "Temperature"
357
- x-axis ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
358
- y-axis "°C" -5 --> 30
359
- line [2, 4, 10, 16, 22, 26]
360
- ```
361
-
362
- Mermaid example (pie chart):
363
-
364
- ```mermaid
365
- pie title Browser Share
366
- "Chrome" : 65
367
- "Safari" : 19
368
- "Firefox" : 4
369
- "Other" : 12
370
- ```
371
-
372
- Mermaid example (gantt chart):
373
-
374
- ```mermaid
375
- gantt
376
- title Project Plan
377
- dateFormat YYYY-MM-DD
378
- section Design
379
- Requirements :a1, 2025-01-01, 14d
380
- Architecture :a2, after a1, 10d
381
- section Dev
382
- Implementation :b1, after a2, 21d
383
- Testing :b2, after b1, 14d
384
- ```
385
-
386
- Mermaid example (mindmap):
387
-
388
- ```mermaid
389
- mindmap
390
- root((Project))
391
- Frontend
392
- React
393
- CSS
394
- Backend
395
- API
396
- Database
397
- ```
398
-
399
- Math example (KaTeX, LaTeX syntax):
400
-
401
- ```math
402
- E = mc^2
403
- ```
404
-
405
- Inline math uses $...$ syntax within text:
406
-
407
- The equation $E = mc^2$ is well-known.
408
-
409
- Rules for inline math:
410
- - $$ is not matched (use ```math for display math)
411
- - $ followed by a space is not matched (e.g. $10)
412
- - $ preceded by a space is not matched
413
- - Content inside <code> and <pre> is not affected
414
- - The content is rendered with KaTeX (displayMode: false)
415
-
416
- Function plot example:
417
-
418
- ```functionplot
419
- y = sin(x)
420
- y = x^2 - 1
421
- range: [-2pi, 2pi]
422
- yrange: [-3, 3]
423
- ```
424
-
425
- Function plot syntax:
426
- - y = <expr> Standard function (e.g. y = sin(x))
427
- - r = <expr> Polar function (e.g. r = cos(2*theta))
428
- - parametric: <x>, <y> Parametric curve (e.g. parametric: cos(t), sin(t))
429
- - Bare expression Treated as y = <expr>
430
- Options (one per line):
431
- - range / xrange: [min, max] X-axis range (supports pi, e.g. [-2pi, 2pi])
432
- - yrange: [min, max] Y-axis range
433
- - width: <pixels> Plot width (default: 600)
434
- - height: <pixels> Plot height (default: 400)
435
- - title: <text> Plot title
436
- - grid: true Show grid lines
437
-
438
- == Images ==
439
-
440
- Place image files in the 'images/' directory next to book.yml.
441
- Reference them from Markdown with relative paths:
442
-
443
- ![Screenshot](images/screenshot.png)
444
-
445
- ligarb rewrites image paths to 'images/filename' in the output and copies
446
- all files from the images/ directory to the output.
447
-
448
- == Build ==
449
-
450
- Run from the directory containing book.yml:
451
-
452
- ligarb build
453
-
454
- Or specify a path to book.yml:
455
-
456
- ligarb build path/to/book.yml
457
-
458
- The generated index.html is a fully self-contained HTML file (CSS and JS
459
- are embedded). Open it directly in a browser — no web server needed.
460
-
461
- == Footnotes ==
462
-
463
- Footnotes use kramdown syntax:
464
-
465
- This is a sentence with a footnote[^1].
466
-
467
- [^1]: This is the footnote content.
108
+ HELP_PATH = File.expand_path("../../../docs/help.md", __FILE__)
468
109
 
469
- Footnote IDs are scoped per chapter to avoid collisions in the single-page
470
- output.
471
-
472
- == Index ==
473
-
474
- Mark terms for the book index using Markdown link syntax with #index:
475
-
476
- [Ruby](#index) Index the link text as-is
477
- [dynamic typing](#index:動的型付け) Index under a specific term
478
- [Ruby](#index:Ruby,Languages/Ruby) Multiple index entries (comma-separated)
479
- [Ruby](#index:Languages/Ruby) Hierarchical: Languages > Ruby
480
-
481
- The link is rendered as plain text in the output (no link styling).
482
- An "Index" section is automatically appended at the end of the book,
483
- with terms sorted alphabetically and grouped by first character.
484
-
485
- Clicking an index entry navigates to the exact location in the chapter.
486
-
487
- == Bibliography ==
488
-
489
- Cite references in the text using Markdown link syntax with #cite:
490
-
491
- [Ruby](#cite:matz1995) Cite by key; rendered as Ruby[Matsumoto, 1995]
492
-
493
- Define a bibliography data file in book.yml:
494
-
495
- bibliography: references.yml # YAML format
496
- bibliography: references.bib # BibTeX format
497
-
498
- The format is auto-detected by file extension (.bib = BibTeX, otherwise YAML).
499
-
500
- YAML format maps keys to reference data:
501
-
502
- matz1995:
503
- author: "Yukihiro Matsumoto"
504
- title: "The Ruby Programming Language"
505
- year: 1995
506
- url: "https://www.ruby-lang.org"
507
- publisher: "O'Reilly"
508
- doi: "10.1234/example"
509
-
510
- BibTeX format (.bib) is also supported:
511
-
512
- @book{matz1995,
513
- author = {Yukihiro Matsumoto},
514
- title = {The Ruby Programming Language},
515
- year = {1995},
516
- publisher = {O'Reilly},
517
- url = {https://www.ruby-lang.org}
518
- }
519
-
520
- BibTeX notes:
521
- - Entry types (@book, @article, etc.) are preserved for formatting
522
- - Field values can use {braces} or "quotes"
523
- - Nested braces are supported one level deep ({The {Ruby} Language})
524
- - Lines starting with % are comments
525
-
526
- Supported fields (YAML and BibTeX):
527
- author, title, year, url, publisher, journal, booktitle, volume,
528
- number, pages, edition, doi, editor, note.
529
-
530
- The bibliography section formats entries by type:
531
- - book: Author. Title. Edition. Publisher, Year.
532
- - article: Author. "Title". Journal, Volume(Number), Pages, Year.
533
- - inproceedings: Author. "Title". In Booktitle, Pages, Year.
534
- - other/YAML: Author. Title. Publisher/Journal, Volume, Pages, Year.
535
-
536
- If url is present, the title becomes a link. If doi is present, a DOI link
537
- is appended.
538
-
539
- The citation is rendered as a superscript [author, year] link that navigates
540
- to the "Bibliography" section at the end of the book. Hovering the link shows
541
- the full reference. The bibliography section lists all cited entries sorted by
542
- author and year.
543
-
544
- A warning is printed and the citation is rendered as [key?] (highlighted in
545
- red) if a cite key is not found in the bibliography file.
546
- If no bibliography file is configured, cite markers are left as-is.
547
-
548
- == Custom CSS ==
549
-
550
- Add a 'style' field to book.yml to inject custom CSS:
551
-
552
- style: "custom.css"
553
-
554
- The custom CSS is loaded after the default styles. You can override any
555
- CSS custom property (e.g. colors, fonts, sidebar width) or add new rules.
556
-
557
- Example custom.css:
558
-
559
- :root {
560
- --color-accent: #e63946;
561
- --sidebar-width: 320px;
562
- }
563
-
564
- == Dark Mode ==
565
-
566
- The generated HTML includes a dark mode toggle button (moon icon) in the
567
- sidebar header. The user's preference is saved to localStorage and persists
568
- across page reloads.
569
-
570
- Custom CSS can override dark mode colors using the [data-theme="dark"]
571
- selector.
572
-
573
- == Edit on GitHub ==
574
-
575
- Add a 'repository' field to book.yml:
576
-
577
- repository: "https://github.com/user/repo"
578
-
579
- Each chapter will show a "View on GitHub" link pointing to:
580
- {repository}/blob/HEAD/{path-from-git-root}
581
-
582
- == Admonitions ==
583
-
584
- GFM-style blockquote alerts are converted to styled admonition boxes.
585
- Five types are supported: NOTE, TIP, WARNING, CAUTION, IMPORTANT.
586
-
587
- Syntax:
588
-
589
- > [!NOTE]
590
- > This is a note.
591
-
592
- > [!TIP]
593
- > Helpful advice here.
594
-
595
- > [!WARNING]
596
- > Be careful about this.
597
-
598
- > [!CAUTION]
599
- > Dangerous operation.
600
-
601
- > [!IMPORTANT]
602
- > Critical information.
603
-
604
- Each type renders with a distinct color and icon:
605
- - NOTE: blue (info)
606
- - TIP: green (lightbulb)
607
- - WARNING: yellow (warning)
608
- - CAUTION: red (stop)
609
- - IMPORTANT: purple (exclamation)
610
-
611
- == Cross-References ==
612
-
613
- Link to other chapters or headings using standard Markdown relative links.
614
- ligarb resolves .md file references to internal anchors in the single-page
615
- output.
616
-
617
- Syntax:
618
-
619
- [link text](other-chapter.md) Link to a chapter
620
- [link text](other-chapter.md#Heading) Link to a specific heading
621
- [](other-chapter.md) Auto-fill with chapter title
622
- [](other-chapter.md#Heading) Auto-fill with heading text
623
-
624
- The .md path is resolved relative to the current Markdown file's directory.
625
- The heading fragment is matched against heading IDs (case-insensitive,
626
- normalized the same way heading slugs are generated).
627
-
628
- When the link text is empty, ligarb fills it with the target's display text:
629
- - Chapter link: the chapter's display title (e.g. "3. Config Guide")
630
- - Heading link: the heading's display text (e.g. "3.2 Setup")
631
-
632
- If a referenced chapter or heading does not exist, the build fails with an
633
- error message indicating the broken reference and its source file.
634
-
635
- External URLs ending in .md (e.g. https://example.com/README.md) are not
636
- affected — only relative paths are resolved.
637
-
638
- == Previous/Next Navigation ==
639
-
640
- Each chapter displays Previous and Next navigation links at the bottom.
641
- These follow the flat chapter order (including across parts and appendix).
642
- Cover pages do not show navigation.
643
-
644
- == Write Command ==
645
-
646
- ligarb write [BRIEF] Generate a complete book using AI (Claude).
647
- BRIEF defaults to 'brief.yml' in the current directory.
648
- Reads the brief, sends a prompt to Claude, and builds
649
- the generated book. Files are created in the same
650
- directory as brief.yml.
651
-
652
- ligarb write --init [DIR] Create a brief.yml template.
653
- If DIR is given, creates DIR/brief.yml (mkdir as needed).
654
- If omitted, creates brief.yml in the current directory.
655
-
656
- ligarb write --no-build Generate files only, skip the build step.
657
-
658
- brief.yml fields:
659
-
660
- title: (required) The book title.
661
- language: (optional) Language. Default: "ja".
662
- audience: (optional) Target audience (used in the prompt).
663
- notes: (optional) Additional instructions for Claude (free text).
664
- sources: (optional) Reference files for AI context. Array of strings
665
- or {path:, label:} objects. Paths relative to brief.yml.
666
- author: (optional) Passed through to book.yml.
667
- output_dir: (optional) Passed through to book.yml.
668
- chapter_numbers: (optional) Passed through to book.yml.
669
- style: (optional) Passed through to book.yml.
670
- repository: (optional) Passed through to book.yml.
671
-
672
- The book is generated in the directory containing brief.yml.
673
- Example: 'ligarb write ruby_book/brief.yml' creates files in ruby_book/.
674
-
675
- Requires the 'claude' CLI to be installed.
676
-
677
- == Translations (Multi-Language) ==
678
-
679
- ligarb supports building the same book in multiple languages. A parent
680
- config file (hub) defines shared settings and points to per-language
681
- config files.
682
-
683
- Hub config (book.yml):
684
-
685
- repository: "https://github.com/user/repo"
686
- ai_generated: true
687
- translations:
688
- ja: book.ja.yml
689
- en: book.en.yml
690
-
691
- Per-language config (book.ja.yml):
692
-
693
- title: "マニュアル"
694
- language: "ja"
695
- chapters:
696
- - chapters/ja/01-intro.md
697
-
698
- Per-language config (book.en.yml):
699
-
700
- title: "Manual"
701
- language: "en"
702
- chapters:
703
- - chapters/en/01-intro.md
704
-
705
- Building the hub builds all translations:
706
-
707
- ligarb build book.yml # Builds all languages
708
- ligarb build book.ja.yml # Builds only Japanese (standalone)
709
-
710
- Inheritance rules:
711
- - The hub's settings (repository, style, ai_generated, etc.) are
712
- inherited by each per-language config as defaults.
713
- - Per-language configs can override any inherited setting.
714
- - title, language, and chapters are always per-language (required in
715
- each per-language config).
716
-
717
- The hub config does not need 'title' or 'chapters' fields — it only
718
- needs 'translations'. If the hub has no 'chapters', it is treated
719
- purely as a translations hub.
720
-
721
- Language switcher:
722
- - When built via the hub, each output HTML includes a language switcher
723
- in the sidebar header (e.g. [JA | EN]).
724
- - Links use relative paths between output directories.
725
- - The current language is highlighted; others are clickable links.
726
- SPEC
110
+ def spec_text
111
+ "ligarb #{VERSION}\n\n#{File.read(HELP_PATH)}"
727
112
  end
728
113
 
729
114
  def print_spec