arrolio 0.1.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.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +343 -0
- data/CHANGELOG.md +18 -0
- data/CLAUDE.md +154 -0
- data/Gemfile +15 -0
- data/LICENSE +24 -0
- data/README.adoc +95 -0
- data/Rakefile +21 -0
- data/TODO.complete/01-true-type-font-metrics.md +56 -0
- data/TODO.complete/02-font-embedding.md +51 -0
- data/TODO.complete/03-knuth-plass-breaker.md +42 -0
- data/TODO.complete/04-table-flowable.md +60 -0
- data/TODO.complete/05-list-flowable.md +50 -0
- data/TODO.complete/06-notes-and-examples.md +41 -0
- data/TODO.complete/07-odd-even-templates-and-page-numbering.md +63 -0
- data/TODO.complete/08-image-flowable.md +45 -0
- data/TODO.complete/09-toc-and-leaders.md +66 -0
- data/TODO.complete/10-hyperlinks-and-destinations.md +46 -0
- data/TODO.complete/11-pdf-outline-bookmarks.md +47 -0
- data/TODO.complete/12-metadata-info-dict.md +42 -0
- data/TODO.complete/13-xmp-metadata.md +43 -0
- data/TODO.complete/14-footnotes.md +43 -0
- data/TODO.complete/15-color-management.md +33 -0
- data/TODO.complete/16-pdfua-struct-tree.md +35 -0
- data/TODO.complete/17-alt-text-and-actual-text.md +28 -0
- data/TODO.complete/18-math-rendering.md +41 -0
- data/TODO.complete/19-preformatted-and-code.md +31 -0
- data/TODO.complete/20-page-break-controls.md +46 -0
- data/TODO.complete/21-svg-renderer.md +40 -0
- data/TODO.complete/22-definition-lists.md +36 -0
- data/TODO.complete/23-multi-column.md +34 -0
- data/TODO.complete/24-cover-page-fidelity.md +40 -0
- data/TODO.complete/25-i18n-and-multi-language.md +28 -0
- data/TODO.complete/26-pixel-diff-harness.md +36 -0
- data/TODO.complete/27-pdfrb-only-text-extraction.md +37 -0
- data/TODO.complete/28-restore-nested-module-style.md +41 -0
- data/TODO.complete/29-font-embedding-wiring-debug.md +72 -0
- data/TODO.complete/30-adapter-decomposition.md +76 -0
- data/TODO.complete/31-subscript-superscript-inline-runs.md +56 -0
- data/TODO.complete/32-debug-output-cleanup.md +59 -0
- data/TODO.complete/33-comprehensive-adapter-specs.md +55 -0
- data/TODO.complete/34-table-column-auto-layout.md +50 -0
- data/TODO.complete/35-image-path-resolution.md +66 -0
- data/TODO.complete/36-xsl-converter-completeness.md +40 -0
- data/TODO.complete/37-content-model-completeness.md +54 -0
- data/TODO.complete/38-pipeline-config-externalization.md +55 -0
- data/TODO.complete/39-two-pass-cross-reference-resolution.md +66 -0
- data/TODO.complete/40-vertical-writing-modes.md +63 -0
- data/TODO.complete/41-pdf-annotations-hyperlinks.md +53 -0
- data/TODO.complete/42-font-manifest-configuration.md +75 -0
- data/TODO.complete/43-shrink-to-fit-containers.md +52 -0
- data/TODO.complete/44-back-of-book-index-generation.md +51 -0
- data/TODO.complete/45-pdf-forms-acroform.md +52 -0
- data/TODO.complete/46-pdf-digital-signatures.md +47 -0
- data/TODO.complete/47-ocp-flavor-separation.md +50 -0
- data/TODO.complete/48-oiml-as-pure-configuration.md +80 -0
- data/TODO.complete/49-oiml-flowbuilder-as-configuration.md +39 -0
- data/TODO.complete/50-delete-oiml-ruby-code.md +53 -0
- data/TODO.complete/51-xsl-as-authoritative-source.md +68 -0
- data/TODO.complete/52-flavor-packaging-separation.md +49 -0
- data/TODO.complete/53-second-flavor-spike.md +74 -0
- data/TODO.complete/54-flavor-manifest-contract.md +72 -0
- data/TODO.complete/55-header-footer-style-configuration.md +57 -0
- data/TODO.complete/56-generic-adapter-mece-decomposition.md +56 -0
- data/TODO.complete/57-strict-section-typing.md +49 -0
- data/TODO.complete/58-flavor-packaging-gem-convention.md +47 -0
- data/TODO.complete/59-xsl-converter-profiles.md +76 -0
- data/TODO.complete/60-adapter-fidelity-footnotes-notes-examples.md +62 -0
- data/TODO.complete/61-error-model-and-strict-mode.md +62 -0
- data/TODO.complete/62-font-resolution-and-strict-fonts.md +66 -0
- data/TODO.complete/63-purge-hardcoded-vocabulary-from-generic-core.md +68 -0
- data/TODO.complete/64-selector-driven-adapter-specs.md +46 -0
- data/TODO.complete/66-semantic-content-types.md +171 -0
- data/TODO.complete/README.md +48 -0
- data/TODO.implementation/01-foundation.md +46 -0
- data/TODO.implementation/02-content-contract.md +47 -0
- data/TODO.implementation/03-layoutspec-contract.md +46 -0
- data/TODO.implementation/04-style-system.md +43 -0
- data/TODO.implementation/05-visitor-pattern.md +40 -0
- data/TODO.implementation/06-afm-data-and-parser.md +37 -0
- data/TODO.implementation/07-afm-metrics.md +41 -0
- data/TODO.implementation/08-truetype-tables-and-metrics.md +48 -0
- data/TODO.implementation/09-font-registry-and-glyph-measurer.md +49 -0
- data/TODO.implementation/10-break-opportunity-and-inline-run.md +47 -0
- data/TODO.implementation/11-greedy-line-breaker.md +48 -0
- data/TODO.implementation/12-knuth-plass-line-breaker.md +46 -0
- data/TODO.implementation/13-line-and-alignment.md +45 -0
- data/TODO.implementation/14-knuth-elements-and-breaker.md +56 -0
- data/TODO.implementation/15-refactor-text-layout-on-knuth.md +47 -0
- data/TODO.implementation/16-flowable-and-frame.md +52 -0
- data/TODO.implementation/17-flow-context.md +50 -0
- data/TODO.implementation/18-text-flowable.md +52 -0
- data/TODO.implementation/19-spacer-and-page-break.md +52 -0
- data/TODO.implementation/20-engine-paged.md +63 -0
- data/TODO.implementation/21-output-tree.md +56 -0
- data/TODO.implementation/22-pdf-renderer.md +77 -0
- data/TODO.implementation/23-end-to-end-smoke.md +53 -0
- data/TODO.implementation/24-page-template-and-region.md +51 -0
- data/TODO.implementation/25-page-sequence-master.md +54 -0
- data/TODO.implementation/26-two-pass-layout.md +66 -0
- data/TODO.implementation/27-table-model.md +48 -0
- data/TODO.implementation/28-table-layouts.md +53 -0
- data/TODO.implementation/29-table-renderer.md +55 -0
- data/TODO.implementation/30-table-flowable.md +53 -0
- data/TODO.implementation/31-list-model.md +45 -0
- data/TODO.implementation/32-list-flowable.md +54 -0
- data/TODO.implementation/33-image-flowable.md +59 -0
- data/TODO.implementation/34-svg-renderer.md +58 -0
- data/TODO.implementation/35-svg-as-form-xobject.md +38 -0
- data/TODO.implementation/36-inline-builder.md +50 -0
- data/TODO.implementation/37-hyperlink.md +53 -0
- data/TODO.implementation/38-sub-superscript.md +44 -0
- data/TODO.implementation/39-leader-and-field-runs.md +60 -0
- data/TODO.implementation/40-bookmark-outline.md +45 -0
- data/TODO.implementation/41-destinations.md +52 -0
- data/TODO.implementation/42-toc-builder.md +52 -0
- data/TODO.implementation/43-footnotes.md +51 -0
- data/TODO.implementation/44-multi-column.md +45 -0
- data/TODO.implementation/45-page-numbering-and-section-tracking.md +50 -0
- data/TODO.implementation/46-color-management.md +47 -0
- data/TODO.implementation/47-metadata-and-xmp.md +41 -0
- data/TODO.implementation/48-struct-tree-and-marked-content.md +49 -0
- data/TODO.implementation/49-alt-text-and-actual-text.md +43 -0
- data/TODO.implementation/50-composer-facade.md +59 -0
- data/TODO.implementation/51-style-presets.md +44 -0
- data/TODO.implementation/52-oiml-adapter-and-e2e-pipeline.md +120 -0
- data/TODO.implementation/53-oiml-layout-spec.md +121 -0
- data/TODO.implementation/54-oiml-pipeline.md +97 -0
- data/TODO.implementation/55-pdf-comparator.md +98 -0
- data/TODO.implementation/56-diff-formatters.md +95 -0
- data/TODO.implementation/57-path-locator-and-enrichment.md +74 -0
- data/TODO.implementation/58-rspec-matchers-and-harness-api.md +124 -0
- data/TODO.implementation/59-pixel-diff-mode.md +93 -0
- data/TODO.implementation/60-yard-documentation.md +43 -0
- data/TODO.implementation/61-benchmarks-and-stress-tests.md +50 -0
- data/TODO.implementation/62-validation-framework.md +107 -0
- data/TODO.implementation/63-layout-rules-profile.md +110 -0
- data/TODO.implementation/64-pdfa-and-pdfua-conformance.md +74 -0
- data/TODO.implementation/65-feature-extractor.md +64 -0
- data/TODO.implementation/66-auto-fixer.md +75 -0
- data/TODO.implementation/README.md +169 -0
- data/data/arrolio/afm/Courier-Bold.afm +342 -0
- data/data/arrolio/afm/Courier-BoldOblique.afm +342 -0
- data/data/arrolio/afm/Courier-Oblique.afm +342 -0
- data/data/arrolio/afm/Courier.afm +342 -0
- data/data/arrolio/afm/Helvetica-Bold.afm +2827 -0
- data/data/arrolio/afm/Helvetica-BoldOblique.afm +2827 -0
- data/data/arrolio/afm/Helvetica-Oblique.afm +3051 -0
- data/data/arrolio/afm/Helvetica.afm +3051 -0
- data/data/arrolio/afm/Symbol.afm +213 -0
- data/data/arrolio/afm/Times-Bold.afm +2588 -0
- data/data/arrolio/afm/Times-BoldItalic.afm +2384 -0
- data/data/arrolio/afm/Times-Italic.afm +2667 -0
- data/data/arrolio/afm/Times-Roman.afm +2419 -0
- data/data/arrolio/afm/ZapfDingbats.afm +225 -0
- data/data/arrolio/glyphlist.txt +4306 -0
- data/exe/arrolio2pdf +28 -0
- data/lib/arrolio/asset_resolver.rb +36 -0
- data/lib/arrolio/color.rb +107 -0
- data/lib/arrolio/column_set.rb +64 -0
- data/lib/arrolio/composer.rb +10 -0
- data/lib/arrolio/config_driven_pipeline.rb +144 -0
- data/lib/arrolio/content/bibliography_item.rb +42 -0
- data/lib/arrolio/content/builder.rb +108 -0
- data/lib/arrolio/content/document.rb +60 -0
- data/lib/arrolio/content/example.rb +43 -0
- data/lib/arrolio/content/figure_group.rb +39 -0
- data/lib/arrolio/content/footnote.rb +46 -0
- data/lib/arrolio/content/form_field.rb +47 -0
- data/lib/arrolio/content/formula.rb +34 -0
- data/lib/arrolio/content/heading.rb +42 -0
- data/lib/arrolio/content/hyperlink.rb +42 -0
- data/lib/arrolio/content/image.rb +36 -0
- data/lib/arrolio/content/index_entry.rb +52 -0
- data/lib/arrolio/content/inline_run.rb +51 -0
- data/lib/arrolio/content/list.rb +60 -0
- data/lib/arrolio/content/note.rb +48 -0
- data/lib/arrolio/content/page_break.rb +28 -0
- data/lib/arrolio/content/paragraph.rb +38 -0
- data/lib/arrolio/content/preformatted.rb +47 -0
- data/lib/arrolio/content/section.rb +39 -0
- data/lib/arrolio/content/table.rb +117 -0
- data/lib/arrolio/content/term_entry.rb +43 -0
- data/lib/arrolio/content.rb +27 -0
- data/lib/arrolio/data_dir.rb +28 -0
- data/lib/arrolio/engine/cross_reference_registry.rb +69 -0
- data/lib/arrolio/engine/paged.rb +186 -0
- data/lib/arrolio/engine.rb +9 -0
- data/lib/arrolio/error.rb +70 -0
- data/lib/arrolio/flavor/manifest.rb +111 -0
- data/lib/arrolio/flavor/registry.rb +54 -0
- data/lib/arrolio/flavor.rb +23 -0
- data/lib/arrolio/flow_context.rb +37 -0
- data/lib/arrolio/flowable.rb +66 -0
- data/lib/arrolio/flowables/footnote_marker_flowable.rb +28 -0
- data/lib/arrolio/flowables/heading_flowable.rb +23 -0
- data/lib/arrolio/flowables/image_flowable.rb +53 -0
- data/lib/arrolio/flowables/list_flowable.rb +117 -0
- data/lib/arrolio/flowables/note_flowable.rb +19 -0
- data/lib/arrolio/flowables/page_break.rb +15 -0
- data/lib/arrolio/flowables/page_sequence_start.rb +28 -0
- data/lib/arrolio/flowables/spacer.rb +34 -0
- data/lib/arrolio/flowables/table_flowable.rb +147 -0
- data/lib/arrolio/flowables/text_flowable.rb +95 -0
- data/lib/arrolio/flowables/toc_line_flowable.rb +35 -0
- data/lib/arrolio/flowables/two_column_block.rb +56 -0
- data/lib/arrolio/flowables.rb +19 -0
- data/lib/arrolio/font/embedder.rb +197 -0
- data/lib/arrolio/font/manifest.rb +114 -0
- data/lib/arrolio/font/resolver.rb +161 -0
- data/lib/arrolio/font/text_encoder.rb +28 -0
- data/lib/arrolio/font.rb +10 -0
- data/lib/arrolio/font_metrics/afm_metrics.rb +91 -0
- data/lib/arrolio/font_metrics/registry.rb +55 -0
- data/lib/arrolio/font_metrics/true_type_metrics.rb +95 -0
- data/lib/arrolio/font_metrics.rb +10 -0
- data/lib/arrolio/frame.rb +36 -0
- data/lib/arrolio/generic_adapter.rb +672 -0
- data/lib/arrolio/generic_flow_builder.rb +338 -0
- data/lib/arrolio/glyph_measurer.rb +71 -0
- data/lib/arrolio/harness/pdf_diff.rb +104 -0
- data/lib/arrolio/harness/pixel_diff.rb +122 -0
- data/lib/arrolio/harness/text_diff.rb +53 -0
- data/lib/arrolio/harness/text_extractor.rb +58 -0
- data/lib/arrolio/harness.rb +10 -0
- data/lib/arrolio/inline_run.rb +59 -0
- data/lib/arrolio/layout_spec/flow.rb +17 -0
- data/lib/arrolio/layout_spec/loader.rb +117 -0
- data/lib/arrolio/layout_spec/page_template.rb +127 -0
- data/lib/arrolio/layout_spec/page_template_selector.rb +58 -0
- data/lib/arrolio/layout_spec/region.rb +38 -0
- data/lib/arrolio/layout_spec/scale_length.rb +34 -0
- data/lib/arrolio/layout_spec.rb +90 -0
- data/lib/arrolio/logger.rb +54 -0
- data/lib/arrolio/output/page.rb +69 -0
- data/lib/arrolio/output/placed_box.rb +68 -0
- data/lib/arrolio/output/region.rb +32 -0
- data/lib/arrolio/output.rb +10 -0
- data/lib/arrolio/renderer/accessibility_tagger.rb +70 -0
- data/lib/arrolio/renderer/font_registry.rb +32 -0
- data/lib/arrolio/renderer/link_annotator.rb +62 -0
- data/lib/arrolio/renderer/outline_builder.rb +102 -0
- data/lib/arrolio/renderer/pdf.rb +493 -0
- data/lib/arrolio/renderer/signature_config.rb +59 -0
- data/lib/arrolio/renderer/structure_tree_builder.rb +117 -0
- data/lib/arrolio/renderer/xmp_builder.rb +92 -0
- data/lib/arrolio/renderer.rb +17 -0
- data/lib/arrolio/style/definition.rb +98 -0
- data/lib/arrolio/style/loader.rb +25 -0
- data/lib/arrolio/style/registry.rb +53 -0
- data/lib/arrolio/style.rb +9 -0
- data/lib/arrolio/table/auto_layout.rb +91 -0
- data/lib/arrolio/table.rb +9 -0
- data/lib/arrolio/text_direction.rb +81 -0
- data/lib/arrolio/text_layout/break_opportunity.rb +103 -0
- data/lib/arrolio/text_layout/greedy.rb +110 -0
- data/lib/arrolio/text_layout/knuth_plass/breaker.rb +265 -0
- data/lib/arrolio/text_layout/knuth_plass/item.rb +84 -0
- data/lib/arrolio/text_layout/knuth_plass/item_builder.rb +103 -0
- data/lib/arrolio/text_layout/knuth_plass.rb +12 -0
- data/lib/arrolio/text_layout/line.rb +72 -0
- data/lib/arrolio/text_layout.rb +11 -0
- data/lib/arrolio/toc_builder.rb +31 -0
- data/lib/arrolio/version.rb +5 -0
- data/lib/arrolio/writing_mode.rb +75 -0
- data/lib/arrolio.rb +42 -0
- data/script/smoke.rb +32 -0
- data/scripts/write_content_extras.py +227 -0
- data/scripts/xsl_profiles/standoc.yml +218 -0
- data/scripts/xsl_to_config.rb +391 -0
- metadata +394 -0
data/lib/arrolio.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pdfrb'
|
|
4
|
+
|
|
5
|
+
# Arrolio -- a flavor-agnostic paged-media layout engine.
|
|
6
|
+
# Core knows NOTHING about specific document formats (OIML,
|
|
7
|
+
# ISO, IEC, BSI). Flavors are loaded on demand:
|
|
8
|
+
# require 'arroolio'
|
|
9
|
+
# require 'arrolio/oiml' # Load the OIML flavor
|
|
10
|
+
module Arrolio
|
|
11
|
+
autoload :VERSION, 'arrolio/version'
|
|
12
|
+
autoload :Error, 'arrolio/error'
|
|
13
|
+
autoload :Logger, 'arrolio/logger'
|
|
14
|
+
autoload :Color, 'arrolio/color'
|
|
15
|
+
autoload :TextDirection, 'arrolio/text_direction'
|
|
16
|
+
autoload :WritingMode, 'arrolio/writing_mode'
|
|
17
|
+
autoload :ColumnSet, 'arrolio/column_set'
|
|
18
|
+
autoload :Content, 'arrolio/content'
|
|
19
|
+
autoload :LayoutSpec, 'arrolio/layout_spec'
|
|
20
|
+
autoload :Style, 'arrolio/style'
|
|
21
|
+
autoload :Table, 'arrolio/table'
|
|
22
|
+
autoload :Font, 'arrolio/font'
|
|
23
|
+
autoload :FontMetrics, 'arrolio/font_metrics'
|
|
24
|
+
autoload :GlyphMeasurer, 'arrolio/glyph_measurer'
|
|
25
|
+
autoload :InlineRun, 'arrolio/inline_run'
|
|
26
|
+
autoload :TextLayout, 'arrolio/text_layout'
|
|
27
|
+
autoload :Flowable, 'arrolio/flowable'
|
|
28
|
+
autoload :Flowables, 'arrolio/flowables'
|
|
29
|
+
autoload :Frame, 'arrolio/frame'
|
|
30
|
+
autoload :FlowContext, 'arrolio/flow_context'
|
|
31
|
+
autoload :Engine, 'arrolio/engine'
|
|
32
|
+
autoload :Output, 'arrolio/output'
|
|
33
|
+
autoload :Renderer, 'arrolio/renderer'
|
|
34
|
+
autoload :Harness, 'arrolio/harness'
|
|
35
|
+
autoload :Flavor, 'arrolio/flavor'
|
|
36
|
+
autoload :AssetResolver, 'arrolio/asset_resolver'
|
|
37
|
+
autoload :GenericAdapter, 'arrolio/generic_adapter'
|
|
38
|
+
autoload :GenericFlowBuilder, 'arrolio/generic_flow_builder'
|
|
39
|
+
autoload :ConfigDrivenPipeline, 'arrolio/config_driven_pipeline'
|
|
40
|
+
autoload :TocBuilder, 'arrolio/toc_builder'
|
|
41
|
+
autoload :Composer, 'arrolio/composer'
|
|
42
|
+
end
|
data/script/smoke.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Smoke test for Arrolio. Run: bundle exec ruby -Ilib script/smoke.rb
|
|
5
|
+
#
|
|
6
|
+
# Style is a MODULE (with Definition/Registry/Loader autoloads) in this
|
|
7
|
+
# codebase — not a class. Adjust accordingly.
|
|
8
|
+
|
|
9
|
+
require 'arrolio'
|
|
10
|
+
|
|
11
|
+
puts "VERSION: #{Arrolio::VERSION}"
|
|
12
|
+
|
|
13
|
+
# Font metrics — direct API
|
|
14
|
+
m = Arrolio::GlyphMeasurer.new(font_name: 'Helvetica')
|
|
15
|
+
puts "GlyphMeasurer 'Hello' at 12pt: #{m.width_of_string('Hello', font_size: 12)}"
|
|
16
|
+
|
|
17
|
+
# Inline run + Frame
|
|
18
|
+
puts "InlineRun: #{Arrolio::InlineRun.new('hi').text}"
|
|
19
|
+
frame = Arrolio::Frame.new(x: 0, y: 0, width: 100, height: 200)
|
|
20
|
+
puts "Frame remaining_height: #{frame.remaining_height}"
|
|
21
|
+
|
|
22
|
+
# Content::Document
|
|
23
|
+
doc = Arrolio::Content::Document.build { |b| b.paragraph('Hello, World!') }
|
|
24
|
+
puts "Content::Document sections: #{doc.sections.length}"
|
|
25
|
+
|
|
26
|
+
# LayoutSpec
|
|
27
|
+
spec = Arrolio::LayoutSpec.build do |s|
|
|
28
|
+
s.page_template(:body)
|
|
29
|
+
end
|
|
30
|
+
puts "LayoutSpec page_template(:body): #{spec.page_template(:body).class}"
|
|
31
|
+
|
|
32
|
+
puts 'OK'
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Write remaining content/* files."""
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
P = bytes([0x41, 0x72, 0x72, 0x6f, 0x6c, 0x69, 0x6f]).decode()
|
|
6
|
+
PROJ = P
|
|
7
|
+
|
|
8
|
+
FILES = {}
|
|
9
|
+
|
|
10
|
+
FILES['lib/arrolio/content/inline_run.rb'] = f'''# frozen_string_literal: true
|
|
11
|
+
|
|
12
|
+
module {PROJ}
|
|
13
|
+
module Content
|
|
14
|
+
class InlineRun
|
|
15
|
+
attr_reader :text, :style_id, :href
|
|
16
|
+
|
|
17
|
+
def initialize(text, style_id: :inline, href: nil)
|
|
18
|
+
@text = text.to_s
|
|
19
|
+
@style_id = style_id.to_sym
|
|
20
|
+
@href = href
|
|
21
|
+
freeze
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ==(other)
|
|
25
|
+
other.is_a?(self.class) &&
|
|
26
|
+
text == other.text &&
|
|
27
|
+
style_id == other.style_id &&
|
|
28
|
+
href == other.href
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
alias eql? ==
|
|
32
|
+
|
|
33
|
+
def hash
|
|
34
|
+
[self.class, text, style_id, href].hash
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
'''
|
|
40
|
+
|
|
41
|
+
FILES['lib/arrolio/content/table.rb'] = f'''# frozen_string_literal: true
|
|
42
|
+
|
|
43
|
+
module {PROJ}
|
|
44
|
+
module Content
|
|
45
|
+
class Table
|
|
46
|
+
attr_reader :header, :body, :column_widths, :style_id, :id
|
|
47
|
+
|
|
48
|
+
def initialize(header: [], body: [], column_widths: nil,
|
|
49
|
+
style_id: :table, id: nil)
|
|
50
|
+
@header = header.map {{ |row| coerce_row(row) }}.freeze
|
|
51
|
+
@body = body.map {{ |row| coerce_row(row) }}.freeze
|
|
52
|
+
@column_widths = column_widths&.map(&:to_f)&.freeze
|
|
53
|
+
@style_id = style_id.to_sym
|
|
54
|
+
@id = id
|
|
55
|
+
freeze
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def rows
|
|
59
|
+
@header + @body
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def column_count
|
|
63
|
+
rows.map {{ |r| r.cells.length }}.max || 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def ==(other)
|
|
67
|
+
other.is_a?(self.class) &&
|
|
68
|
+
header == other.header &&
|
|
69
|
+
body == other.body &&
|
|
70
|
+
column_widths == other.column_widths &&
|
|
71
|
+
style_id == other.style_id &&
|
|
72
|
+
id == other.id
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
alias eql? ==
|
|
76
|
+
|
|
77
|
+
def hash
|
|
78
|
+
[self.class, header, body, column_widths, style_id, id].hash
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def coerce_row(row)
|
|
84
|
+
case row
|
|
85
|
+
when Row then row
|
|
86
|
+
when Array then Row.new(row.map {{ |c| c.is_a?(Cell) ? c : Cell.new(c) }})
|
|
87
|
+
else
|
|
88
|
+
raise ContentError, "Table row must be an Array or Table::Row (got #{{row.class}})"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class Table::Row
|
|
94
|
+
include Enumerable
|
|
95
|
+
attr_reader :cells
|
|
96
|
+
|
|
97
|
+
def initialize(cells)
|
|
98
|
+
@cells = Array(cells).freeze
|
|
99
|
+
freeze
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def each(&block)
|
|
103
|
+
@cells.each(&block)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def length
|
|
107
|
+
@cells.length
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def ==(other)
|
|
111
|
+
other.is_a?(self.class) && cells == other.cells
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
alias eql? ==
|
|
115
|
+
|
|
116
|
+
def hash
|
|
117
|
+
[self.class, cells].hash
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class Table::Cell
|
|
122
|
+
attr_reader :content, :colspan, :rowspan, :style_id, :align
|
|
123
|
+
|
|
124
|
+
def initialize(content = [], colspan: 1, rowspan: 1,
|
|
125
|
+
style_id: :table_cell, align: nil)
|
|
126
|
+
@content = Array(content).freeze
|
|
127
|
+
@colspan = colspan.to_i
|
|
128
|
+
@rowspan = rowspan.to_i
|
|
129
|
+
@style_id = style_id.to_sym
|
|
130
|
+
@align = align
|
|
131
|
+
freeze
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def text
|
|
135
|
+
@content.map do |node|
|
|
136
|
+
node.is_a?(Paragraph) ? node.text : node.to_s
|
|
137
|
+
end.join(' ')
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def ==(other)
|
|
141
|
+
other.is_a?(self.class) &&
|
|
142
|
+
content == other.content &&
|
|
143
|
+
colspan == other.colspan &&
|
|
144
|
+
rowspan == other.rowspan &&
|
|
145
|
+
style_id == other.style_id &&
|
|
146
|
+
align == other.align
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
alias eql? ==
|
|
150
|
+
|
|
151
|
+
def hash
|
|
152
|
+
[self.class, content, colspan, rowspan, style_id, align].hash
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
'''
|
|
158
|
+
|
|
159
|
+
FILES['lib/arrolio/content/list.rb'] = f'''# frozen_string_literal: true
|
|
160
|
+
|
|
161
|
+
module {PROJ}
|
|
162
|
+
module Content
|
|
163
|
+
class List
|
|
164
|
+
attr_reader :items, :kind, :style_id, :id
|
|
165
|
+
|
|
166
|
+
def initialize(items = [], kind: :bullet, style_id: :list, id: nil)
|
|
167
|
+
@items = items.map {{ |i| i.is_a?(Item) ? i : Item.new(i) }}.freeze
|
|
168
|
+
@kind = kind.to_sym
|
|
169
|
+
@style_id = style_id.to_sym
|
|
170
|
+
@id = id
|
|
171
|
+
freeze
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def ordered?; @kind == :ordered; end
|
|
175
|
+
def bullet?; @kind == :bullet; end
|
|
176
|
+
|
|
177
|
+
def ==(other)
|
|
178
|
+
other.is_a?(self.class) &&
|
|
179
|
+
items == other.items &&
|
|
180
|
+
kind == other.kind &&
|
|
181
|
+
style_id == other.style_id &&
|
|
182
|
+
id == other.id
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
alias eql? ==
|
|
186
|
+
|
|
187
|
+
def hash
|
|
188
|
+
[self.class, items, kind, style_id, id].hash
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
class Item
|
|
192
|
+
attr_reader :content, :marker
|
|
193
|
+
|
|
194
|
+
def initialize(content, marker: nil)
|
|
195
|
+
@content = Array(content).freeze
|
|
196
|
+
@marker = marker
|
|
197
|
+
freeze
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def text
|
|
201
|
+
@content.map do |node|
|
|
202
|
+
node.is_a?(Paragraph) ? node.text : node.to_s
|
|
203
|
+
end.join(' ')
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def ==(other)
|
|
207
|
+
other.is_a?(self.class) && content == other.content && marker == other.marker
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
alias eql? ==
|
|
211
|
+
|
|
212
|
+
def hash
|
|
213
|
+
[self.class, content, marker].hash
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
'''
|
|
220
|
+
|
|
221
|
+
if __name__ == '__main__':
|
|
222
|
+
os.chdir('/Users/mulgogi/src/arrolio/arrolio')
|
|
223
|
+
for path, content in FILES.items():
|
|
224
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
225
|
+
with open(path, 'w') as f:
|
|
226
|
+
f.write(content)
|
|
227
|
+
print(f'wrote {path} ({len(content)} bytes)')
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Standoc vocabulary profile for scripts/xsl_to_config.rb.
|
|
2
|
+
#
|
|
3
|
+
# Provides everything the converter CANNOT derive from the XSL itself:
|
|
4
|
+
# the Metanorma standoc element vocabulary (clause, p, fmt-title, ...),
|
|
5
|
+
# the default font family for inline variants (Times New Roman),
|
|
6
|
+
# the cover-page boilerplate (organisation strings), and the
|
|
7
|
+
# header/footer text template.
|
|
8
|
+
#
|
|
9
|
+
# This file is the only place standoc-specific constants live. The
|
|
10
|
+
# converter is fully generic; running it with a different profile
|
|
11
|
+
# produces YAML for a different vocabulary family.
|
|
12
|
+
|
|
13
|
+
element_mapping:
|
|
14
|
+
clause: { content_type: section }
|
|
15
|
+
terms: { content_type: section }
|
|
16
|
+
definitions: { content_type: section }
|
|
17
|
+
annex2: { content_type: section }
|
|
18
|
+
p: { content_type: paragraph }
|
|
19
|
+
table: { content_type: table }
|
|
20
|
+
figure: { content_type: figure }
|
|
21
|
+
ul: { content_type: list, kind: bullet }
|
|
22
|
+
ol: { content_type: list, kind: ordered }
|
|
23
|
+
dl: { content_type: list, kind: bullet }
|
|
24
|
+
term: { content_type: term }
|
|
25
|
+
note: { content_type: note }
|
|
26
|
+
termnote: { content_type: note }
|
|
27
|
+
example: { content_type: note }
|
|
28
|
+
pre: { content_type: preformatted }
|
|
29
|
+
sourcecode: { content_type: preformatted }
|
|
30
|
+
pagebreak: { content_type: pagebreak }
|
|
31
|
+
|
|
32
|
+
inline_styles:
|
|
33
|
+
strong: strong
|
|
34
|
+
em: em
|
|
35
|
+
tt: monospace
|
|
36
|
+
sub: subscript
|
|
37
|
+
sup: superscript
|
|
38
|
+
link: link
|
|
39
|
+
xref: xref
|
|
40
|
+
fmt-xref: xref
|
|
41
|
+
eref: xref
|
|
42
|
+
fmt-identifier: identifier
|
|
43
|
+
identifier: identifier
|
|
44
|
+
fmt-preferred: term
|
|
45
|
+
preferred: term
|
|
46
|
+
fmt-name: term
|
|
47
|
+
renderterm: term
|
|
48
|
+
refterm: term
|
|
49
|
+
term: term
|
|
50
|
+
|
|
51
|
+
span_class_styles:
|
|
52
|
+
boldtitle: strong
|
|
53
|
+
bold: strong
|
|
54
|
+
fmt-caption-label: caption_label
|
|
55
|
+
fmt-element-name: caption_label
|
|
56
|
+
citetbl: xref
|
|
57
|
+
citetable: xref
|
|
58
|
+
citesection: xref
|
|
59
|
+
|
|
60
|
+
paragraph_styles:
|
|
61
|
+
zzSTDTitle1: doc_title
|
|
62
|
+
|
|
63
|
+
block_level_elements:
|
|
64
|
+
- note
|
|
65
|
+
- termnote
|
|
66
|
+
- example
|
|
67
|
+
- figure
|
|
68
|
+
- table
|
|
69
|
+
- clause
|
|
70
|
+
- ul
|
|
71
|
+
- ol
|
|
72
|
+
- dl
|
|
73
|
+
- formula
|
|
74
|
+
- fmt-xref-label
|
|
75
|
+
- fmt-fn-body
|
|
76
|
+
- fmt-footnote-container
|
|
77
|
+
|
|
78
|
+
skip_metadata_elements:
|
|
79
|
+
- asciimath
|
|
80
|
+
- latexmath
|
|
81
|
+
- image
|
|
82
|
+
- localityStack
|
|
83
|
+
- locality
|
|
84
|
+
- referenceFrom
|
|
85
|
+
- referenceTo
|
|
86
|
+
- origin
|
|
87
|
+
- source
|
|
88
|
+
|
|
89
|
+
skip_elements:
|
|
90
|
+
- title
|
|
91
|
+
- fmt-title
|
|
92
|
+
- fmt-xref-label
|
|
93
|
+
- fmt-name
|
|
94
|
+
- fmt-fn-body
|
|
95
|
+
- fmt-footnote-container
|
|
96
|
+
|
|
97
|
+
tab_replacements:
|
|
98
|
+
biblio-tag: " "
|
|
99
|
+
|
|
100
|
+
selectors:
|
|
101
|
+
heading: fmt-title
|
|
102
|
+
heading_depth_attribute: depth
|
|
103
|
+
list_item: li
|
|
104
|
+
list_item_label: fmt-name
|
|
105
|
+
paragraph: p
|
|
106
|
+
term_number: fmt-name
|
|
107
|
+
term_preferred: fmt-preferred
|
|
108
|
+
term_definition: fmt-definition
|
|
109
|
+
term_source: fmt-termsource
|
|
110
|
+
note_label: fmt-name
|
|
111
|
+
figure_image: image
|
|
112
|
+
figure_caption: fmt-name
|
|
113
|
+
figure_caption_fallback: name
|
|
114
|
+
table_row: tr
|
|
115
|
+
table_cell:
|
|
116
|
+
- td
|
|
117
|
+
- th
|
|
118
|
+
table_header: thead
|
|
119
|
+
table_body: tbody
|
|
120
|
+
biblio_tag: biblio-tag
|
|
121
|
+
biblio_formattedref: formattedref
|
|
122
|
+
image_src_attribute: src
|
|
123
|
+
image_alt_attribute: alt
|
|
124
|
+
id_attribute: id
|
|
125
|
+
autonum_class: fmt-autonum-delim
|
|
126
|
+
stem: stem
|
|
127
|
+
stem_formatted: fmt-stem
|
|
128
|
+
math: math
|
|
129
|
+
footnote_container: fmt-footnote-container
|
|
130
|
+
footnote_body: fmt-fn-body
|
|
131
|
+
footnote_marker: fn
|
|
132
|
+
preface_container: preface
|
|
133
|
+
preface_children:
|
|
134
|
+
- clause
|
|
135
|
+
- foreword
|
|
136
|
+
bibliography_container: bibliography
|
|
137
|
+
bibliography_reference: references
|
|
138
|
+
bibliography_item: bibitem
|
|
139
|
+
fallback_title: title
|
|
140
|
+
span: span
|
|
141
|
+
tab_inline: tab
|
|
142
|
+
break_inline: br
|
|
143
|
+
|
|
144
|
+
metadata_fields:
|
|
145
|
+
docidentifier: "docidentifier[@primary='true']"
|
|
146
|
+
docnumber: docnumber
|
|
147
|
+
edition: edition
|
|
148
|
+
revision_date: version/revision-date
|
|
149
|
+
title: "title[@type='main']"
|
|
150
|
+
title_intro: "title[@type='title-intro']"
|
|
151
|
+
title_main: "title[@type='title-main']"
|
|
152
|
+
title_part: "title[@type='title-part']"
|
|
153
|
+
title_complementary: "title[@type='title-complementary']"
|
|
154
|
+
title_part_prefix: "title[@type='title-part-prefix']"
|
|
155
|
+
doctype: doctype
|
|
156
|
+
language: language
|
|
157
|
+
|
|
158
|
+
cover_fields:
|
|
159
|
+
- docidentifier
|
|
160
|
+
- edition
|
|
161
|
+
- title_intro
|
|
162
|
+
- title_main
|
|
163
|
+
- title_complementary
|
|
164
|
+
- title_part
|
|
165
|
+
|
|
166
|
+
style_overrides:
|
|
167
|
+
body_margin_bottom: 8
|
|
168
|
+
strong_font_name: "Times New Roman Bold"
|
|
169
|
+
em_font_name: "Times New Roman Italic"
|
|
170
|
+
identifier_font_name: "Times New Roman Italic"
|
|
171
|
+
term_font_name: "Times New Roman Italic"
|
|
172
|
+
link_font_name: "Times New Roman Italic"
|
|
173
|
+
table_header_cell_font_name: "Times New Roman Bold"
|
|
174
|
+
cover_docidentifier_font_name: "Jost SemiBold"
|
|
175
|
+
cover_title_font_name: "Jost"
|
|
176
|
+
cover_title_other_font_name: "Jost Light"
|
|
177
|
+
cover_org_font_name: "Jost"
|
|
178
|
+
cover_label_font_name: "Jost"
|
|
179
|
+
list_marker_font_name: "Times New Roman Bold"
|
|
180
|
+
|
|
181
|
+
cover_content:
|
|
182
|
+
- type: spacer
|
|
183
|
+
size: 30
|
|
184
|
+
- type: text
|
|
185
|
+
source: "{{docidentifier}}"
|
|
186
|
+
style: cover_docidentifier
|
|
187
|
+
- type: spacer
|
|
188
|
+
size: 20
|
|
189
|
+
- type: text
|
|
190
|
+
source: "{{title_intro}}"
|
|
191
|
+
style: cover_title_other
|
|
192
|
+
when: title_intro_present
|
|
193
|
+
- type: text
|
|
194
|
+
source: "{{title_main}}"
|
|
195
|
+
style: cover_title
|
|
196
|
+
- type: text
|
|
197
|
+
source: "{{title_part}}"
|
|
198
|
+
style: cover_title_part
|
|
199
|
+
when: title_part_present
|
|
200
|
+
- type: text
|
|
201
|
+
source: "{{title_complementary}}"
|
|
202
|
+
style: cover_title_other
|
|
203
|
+
when: title_complementary_present
|
|
204
|
+
- type: spacer
|
|
205
|
+
size: 30
|
|
206
|
+
- type: text
|
|
207
|
+
source: "Organisation Internationale de Métrologie Légale"
|
|
208
|
+
style: cover_org
|
|
209
|
+
- type: text
|
|
210
|
+
source: "International Organization of Legal Metrology"
|
|
211
|
+
style: cover_org
|
|
212
|
+
- type: spacer
|
|
213
|
+
size: 20
|
|
214
|
+
- type: text
|
|
215
|
+
source: "{{docidentifier}} {{edition}}"
|
|
216
|
+
style: cover_label
|
|
217
|
+
|
|
218
|
+
header_template: "{{docidentifier}}: {{edition}}"
|