coradoc-html 1.1.14 → 1.1.15

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.
@@ -15,25 +15,27 @@ module Coradoc
15
15
  @dist_assets_cache = {}
16
16
  end
17
17
 
18
- def render_static(document, body_html, options)
18
+ def render_static(document, body_html, opts)
19
+ opts = RenderOptions.new(**opts) unless opts.is_a?(RenderOptions)
19
20
  layout_template = load_layout('default')
20
- return build_static_fallback(document, body_html, options) unless layout_template
21
+ return build_static_fallback(document, body_html, opts) unless layout_template
21
22
 
22
- layout_template.render(build_static_layout_data(document, body_html, options)).strip
23
+ layout_template.render(build_static_layout_data(document, body_html, opts)).strip
23
24
  end
24
25
 
25
- def render_spa(document, options, body_html, toc_data)
26
- dist_dir = options[:dist_dir] || File.expand_path('../../../frontend/dist', __dir__)
26
+ def render_spa(document, opts, body_html, toc_data)
27
+ opts = RenderOptions.new(**opts) unless opts.is_a?(RenderOptions)
28
+ dist_dir = opts.dist_dir || File.expand_path('../../../frontend/dist', __dir__)
27
29
  assets = load_dist_assets(dist_dir)
28
30
 
29
- content_data = build_spa_content_data(document, body_html, options, toc_data)
31
+ content_data = build_spa_content_data(document, body_html, opts, toc_data)
30
32
  safe_json = Escape.safe_json(content_data)
31
33
 
32
34
  layout_template = load_layout('spa')
33
35
  if layout_template
34
- layout_template.render(build_spa_layout_data(document, options, assets, safe_json)).strip
36
+ layout_template.render(build_spa_layout_data(document, opts, assets, safe_json)).strip
35
37
  else
36
- build_spa_fallback(document, options, assets, safe_json)
38
+ build_spa_fallback(document, opts, assets, safe_json)
37
39
  end
38
40
  end
39
41
 
@@ -47,25 +49,25 @@ module Coradoc
47
49
  TitleText.escape(document&.title) || Config::DEFAULT_TITLE
48
50
  end
49
51
 
50
- def resolve_lang(options)
51
- options[:lang] || Config::DEFAULT_LANG
52
+ def resolve_lang(opts)
53
+ opts.lang || Config::DEFAULT_LANG
52
54
  end
53
55
 
54
- def build_static_layout_data(document, body_html, options)
56
+ def build_static_layout_data(document, body_html, opts)
55
57
  {
56
- 'lang' => resolve_lang(options),
58
+ 'lang' => resolve_lang(opts),
57
59
  'title' => resolve_escaped_title(document),
58
- 'author' => options[:author],
59
- 'description' => options[:description],
60
+ 'author' => opts.author,
61
+ 'description' => opts.description,
60
62
  'generator_version' => Coradoc::VERSION.to_s,
61
63
  'body' => body_html,
62
- 'custom_css' => options[:custom_css]
64
+ 'custom_css' => opts.custom_css
63
65
  }
64
66
  end
65
67
 
66
- def build_static_fallback(document, body_html, options)
68
+ def build_static_fallback(document, body_html, opts)
67
69
  Nokogiri::HTML::Builder.new do |doc|
68
- doc.html(lang: resolve_lang(options)) do
70
+ doc.html(lang: resolve_lang(opts)) do
69
71
  doc.head do
70
72
  doc.meta(charset: 'UTF-8')
71
73
  doc.meta(name: 'viewport', content: 'width=device-width, initial-scale=1.0')
@@ -76,42 +78,42 @@ module Coradoc
76
78
  end.to_html
77
79
  end
78
80
 
79
- def build_spa_content_data(document, body_html, options, toc_data)
81
+ def build_spa_content_data(document, body_html, opts, toc_data)
80
82
  {
81
83
  mode: 'classic',
82
84
  contentHtml: body_html,
83
85
  toc: toc_data,
84
- meta: build_spa_meta(document, options),
85
- options: build_spa_options(options)
86
+ meta: build_spa_meta(document, opts),
87
+ options: build_spa_options(opts)
86
88
  }
87
89
  end
88
90
 
89
- def build_spa_meta(document, options)
91
+ def build_spa_meta(document, _opts)
90
92
  {
91
93
  title: TitleText.resolve(document&.title) || Config::DEFAULT_TITLE,
92
- author: options[:author],
93
- date: options[:revdate],
94
+ author: _opts.author,
95
+ date: nil,
94
96
  generator: "Coradoc #{Coradoc::VERSION}"
95
97
  }
96
98
  end
97
99
 
98
- def build_spa_options(options)
100
+ def build_spa_options(opts)
99
101
  {
100
- toc: options[:toc] ? true : false,
101
- tocPlacement: (options[:toc_placement] || :auto).to_s,
102
- sectnums: options[:section_numbers] == true,
103
- themeToggle: options[:theme_toggle] != false,
104
- readingProgress: options[:reading_progress] != false,
105
- lang: resolve_lang(options)
102
+ toc: opts.toc ? true : false,
103
+ tocPlacement: (opts.toc_placement || :auto).to_s,
104
+ sectnums: opts.section_numbers == true,
105
+ themeToggle: opts.theme_toggle != false,
106
+ readingProgress: opts.reading_progress != false,
107
+ lang: resolve_lang(opts)
106
108
  }
107
109
  end
108
110
 
109
- def build_spa_layout_data(document, options, assets, safe_json)
111
+ def build_spa_layout_data(document, opts, assets, safe_json)
110
112
  {
111
- 'lang' => resolve_lang(options),
113
+ 'lang' => resolve_lang(opts),
112
114
  'title' => resolve_escaped_title(document),
113
- 'author' => options[:author],
114
- 'description' => options[:description],
115
+ 'author' => opts.author,
116
+ 'description' => opts.description,
115
117
  'generator_version' => Coradoc::VERSION.to_s,
116
118
  'css' => assets[:css],
117
119
  'js' => assets[:js],
@@ -119,9 +121,9 @@ module Coradoc
119
121
  }
120
122
  end
121
123
 
122
- def build_spa_fallback(document, options, assets, safe_json)
124
+ def build_spa_fallback(document, opts, assets, safe_json)
123
125
  Nokogiri::HTML::Builder.new do |doc|
124
- doc.html(lang: resolve_lang(options)) do
126
+ doc.html(lang: resolve_lang(opts)) do
125
127
  doc.head do
126
128
  doc.meta(charset: 'UTF-8')
127
129
  doc.meta(name: 'viewport', content: 'width=device-width, initial-scale=1.0')
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module Html
5
+ class RenderOptions
6
+ attr_reader :layout, :lang, :toc, :toc_levels, :section_numbers,
7
+ :section_number_levels, :author, :description, :custom_css,
8
+ :dist_dir, :theme_toggle, :reading_progress, :toc_placement
9
+
10
+ def initialize(layout: :static, lang: 'en', toc: false, toc_levels: 2,
11
+ section_numbers: false, section_number_levels: 3,
12
+ author: nil, description: nil, custom_css: nil,
13
+ dist_dir: nil, theme_toggle: true, reading_progress: true,
14
+ toc_placement: :auto)
15
+ @layout = layout
16
+ @lang = lang
17
+ @toc = toc
18
+ @toc_levels = toc_levels
19
+ @section_numbers = section_numbers
20
+ @section_number_levels = section_number_levels
21
+ @author = author
22
+ @description = description
23
+ @custom_css = custom_css
24
+ @dist_dir = dist_dir
25
+ @theme_toggle = theme_toggle
26
+ @reading_progress = reading_progress
27
+ @toc_placement = toc_placement
28
+ freeze
29
+ end
30
+
31
+ def spa?
32
+ @layout == :spa
33
+ end
34
+
35
+ def static?
36
+ @layout == :static
37
+ end
38
+ end
39
+ end
40
+ end
@@ -48,8 +48,9 @@ module Coradoc
48
48
  template.render(assigns, registers: { renderer: self, section_numbers: @section_numbers }).strip
49
49
  end
50
50
 
51
- def render_html5(document, **options)
52
- builder = TocBuilder.from_options(options)
51
+ def render_html5(document, **)
52
+ opts = RenderOptions.new(**)
53
+ builder = TocBuilder.from_options(opts)
53
54
  @toc, @section_numbers = if document.is_a?(CoreModel::StructuralElement)
54
55
  builder.build_with_numbers(document)
55
56
  else
@@ -58,10 +59,10 @@ module Coradoc
58
59
 
59
60
  body_html = render(document)
60
61
 
61
- if options[:layout] == :spa
62
- render_spa_layout(document, body_html, options)
62
+ if opts.spa?
63
+ render_spa_layout(document, body_html, opts)
63
64
  else
64
- render_static_layout(document, body_html, options)
65
+ render_static_layout(document, body_html, opts)
65
66
  end
66
67
  end
67
68
 
@@ -79,22 +80,22 @@ module Coradoc
79
80
 
80
81
  private
81
82
 
82
- def render_static_layout(document, body_html, options)
83
- if options[:toc] && @toc
83
+ def render_static_layout(document, body_html, opts)
84
+ if opts.toc && @toc
84
85
  toc_html = render(@toc)
85
86
  body_html = "#{toc_html}\n#{body_html}" unless toc_html.empty?
86
87
  end
87
- @layout_renderer.render_static(document, body_html, options)
88
+ @layout_renderer.render_static(document, body_html, opts)
88
89
  end
89
90
 
90
- def render_spa_layout(document, body_html, options)
91
- numbered = options[:section_numbers] == true
91
+ def render_spa_layout(document, body_html, opts)
92
+ numbered = opts.section_numbers == true
92
93
  toc_data = if @toc
93
94
  { entries: TocSerializer.new.serialize_entries(@toc.entries), numbered: numbered }
94
95
  else
95
96
  { entries: [], numbered: false }
96
97
  end
97
- @layout_renderer.render_spa(document, options, body_html, toc_data)
98
+ @layout_renderer.render_spa(document, opts, body_html, toc_data)
98
99
  end
99
100
 
100
101
  def find_and_load_template(type_name)
@@ -12,33 +12,16 @@ module Coradoc
12
12
  # Uses the unified Liquid template pipeline.
13
13
  class Spa < ConverterBase
14
14
  class Configuration < ConverterBase::ConfigurationBase
15
- attr_accessor :theme_toggle, :reading_progress,
16
- :toc_sticky, :toc_levels, :lang,
17
- :template_dirs, :dist_dir
18
-
19
- def initialize(**options)
20
- @theme_toggle = options.fetch(:theme_toggle, true)
21
- @reading_progress = options.fetch(:reading_progress, true)
22
- @toc_sticky = options.fetch(:toc_sticky, true)
23
- @toc_levels = options[:toc_levels] || 2
24
- @lang = options[:lang] || 'en'
25
- @template_dirs = options[:template_dirs]
26
- @dist_dir = options[:dist_dir]
27
- end
28
-
29
- def to_h
30
- {
31
- theme_toggle: @theme_toggle, reading_progress: @reading_progress,
32
- toc_sticky: @toc_sticky, toc_levels: @toc_levels,
33
- lang: @lang, template_dirs: @template_dirs, dist_dir: @dist_dir
34
- }
35
- end
15
+ attribute :theme_toggle, default: true
16
+ attribute :reading_progress, default: true
17
+ attribute :toc_sticky, default: true
18
+ attribute :toc_levels, default: 2
19
+ attribute :lang, default: 'en'
20
+ attribute :template_dirs
21
+ attribute :dist_dir
36
22
 
37
23
  def validate!
38
- return if @toc_levels.is_a?(Integer) && @toc_levels.between?(1, 5)
39
-
40
- raise ConverterBase::ValidationError,
41
- 'TOC levels must be an integer between 1 and 5'
24
+ range_check(:toc_levels, 1, 5, label: 'TOC levels')
42
25
  end
43
26
  end
44
27
 
@@ -12,44 +12,19 @@ module Coradoc
12
12
  # the unified Liquid template pipeline.
13
13
  class Static < ConverterBase
14
14
  class Configuration < ConverterBase::ConfigurationBase
15
- attr_accessor :include_toc, :toc_levels,
16
- :section_numbering, :section_numbering_levels,
17
- :lang, :meta_tags, :custom_css, :embedded,
18
- :template_dirs
19
-
20
- def initialize(**options)
21
- @include_toc = options.fetch(:include_toc, false)
22
- @toc_levels = options[:toc_levels] || 2
23
- @section_numbering = options.fetch(:section_numbering, false)
24
- @section_numbering_levels = options[:section_numbering_levels] || 3
25
- @lang = options[:lang] || 'en'
26
- @meta_tags = options[:meta_tags] || {}
27
- @custom_css = options[:custom_css]
28
- @embedded = options.fetch(:embedded, false)
29
- @template_dirs = options[:template_dirs]
30
- end
31
-
32
- def to_h
33
- {
34
- include_toc: @include_toc, toc_levels: @toc_levels,
35
- section_numbering: @section_numbering,
36
- section_numbering_levels: @section_numbering_levels,
37
- lang: @lang, meta_tags: @meta_tags, custom_css: @custom_css,
38
- embedded: @embedded, template_dirs: @template_dirs
39
- }
40
- end
15
+ attribute :include_toc, default: false
16
+ attribute :toc_levels, default: 2
17
+ attribute :section_numbering, default: false
18
+ attribute :section_numbering_levels, default: 3
19
+ attribute :lang, default: 'en'
20
+ attribute :meta_tags, default: {}
21
+ attribute :custom_css
22
+ attribute :embedded, default: false
23
+ attribute :template_dirs
41
24
 
42
25
  def validate!
43
- unless @toc_levels.is_a?(Integer) && @toc_levels.between?(1, 5)
44
- raise ConverterBase::ValidationError,
45
- 'TOC levels must be an integer between 1 and 5'
46
- end
47
-
48
- unless @section_numbering_levels.is_a?(Integer) &&
49
- @section_numbering_levels.between?(1, 6)
50
- raise ConverterBase::ValidationError,
51
- 'Section numbering levels must be an integer between 1 and 6'
52
- end
26
+ range_check(:toc_levels, 1, 5, label: 'TOC levels')
27
+ range_check(:section_numbering_levels, 1, 6, label: 'Section numbering levels')
53
28
  end
54
29
  end
55
30
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module Html
5
+ module TagMapping
6
+ ELEMENT_TO_TAG = {
7
+ # Sections
8
+ section: 'section',
9
+ header: 'header',
10
+
11
+ # Blocks
12
+ paragraph: 'p',
13
+ example: 'div',
14
+ sidebar: 'aside',
15
+ quote: 'blockquote',
16
+ verse: 'div',
17
+ listing: 'pre',
18
+ literal: 'pre',
19
+ source: 'pre',
20
+ source_code: 'pre',
21
+ open: 'div',
22
+ horizontal_rule: 'hr',
23
+ comment: 'div',
24
+ pass: 'div',
25
+ reviewer: 'div',
26
+
27
+ # Lists
28
+ ordered_list: 'ol',
29
+ unordered_list: 'ul',
30
+ list_item: 'li',
31
+ description_list: 'dl',
32
+ description_term: 'dt',
33
+ description_detail: 'dd',
34
+
35
+ # List marker type aliases (from ListBlock#marker_type)
36
+ ordered: 'ol',
37
+ unordered: 'ul',
38
+ definition: 'dl',
39
+
40
+ # Tables
41
+ table: 'table',
42
+ table_row: 'tr',
43
+ table_cell: 'td',
44
+ table_header: 'th',
45
+
46
+ # Inline formatting (symbol keys from TagMapping, string keys from format_type)
47
+ bold: 'strong',
48
+ italic: 'em',
49
+ monospace: 'code',
50
+ highlight: 'mark',
51
+ superscript: 'sup',
52
+ subscript: 'sub',
53
+ underline: 'u',
54
+ strikethrough: 'del',
55
+ small_caps: 'span',
56
+
57
+ # Inline format type aliases (from InlineElement#resolve_format_type)
58
+ link: 'a',
59
+ xref: 'a',
60
+ footnote: 'sup',
61
+ span: 'span',
62
+ term: 'span',
63
+ quotation: 'q',
64
+ small: 'small',
65
+ stem: 'code',
66
+ attribute_reference: 'span',
67
+
68
+ # Links (semantic names)
69
+ anchor: 'a',
70
+ cross_reference: 'a',
71
+
72
+ # Media
73
+ image: 'img',
74
+ video: 'video',
75
+ audio: 'audio',
76
+
77
+ # Other
78
+ break: 'hr',
79
+ line_break: 'br',
80
+ admonition: 'div'
81
+ }.freeze
82
+
83
+ ELEMENT_CSS_CLASS = {
84
+ example: 'example',
85
+ sidebar: 'sidebar',
86
+ literal: 'literal'
87
+ }.freeze
88
+
89
+ def self.tag_for(element_type)
90
+ return 'div' if element_type.nil?
91
+
92
+ key = element_type.is_a?(Symbol) ? element_type : element_type.to_sym
93
+ ELEMENT_TO_TAG[key] || 'div'
94
+ end
95
+
96
+ def self.css_class_for(element_type)
97
+ return nil if element_type.nil?
98
+
99
+ key = element_type.is_a?(Symbol) ? element_type : element_type.to_sym
100
+ ELEMENT_CSS_CLASS[key]
101
+ end
102
+ end
103
+ end
104
+ end
@@ -19,11 +19,12 @@ module Coradoc
19
19
  #
20
20
  # @param options [Hash] options with :section_number_levels, :toc_levels, :section_numbers
21
21
  # @return [TocBuilder]
22
- def self.from_options(options)
23
- section_number_levels = options[:section_number_levels] || 3
24
- toc_levels = options[:toc_levels] || 2
22
+ def self.from_options(opts)
23
+ opts = RenderOptions.new(**opts) unless opts.is_a?(RenderOptions)
24
+ section_number_levels = opts.section_number_levels || 3
25
+ toc_levels = opts.toc_levels || 2
25
26
  max_level = [toc_levels, section_number_levels].min
26
- new(max_level: max_level, numbered: options[:section_numbers] == true, section_number_levels: section_number_levels)
27
+ new(max_level: max_level, numbered: opts.section_numbers == true, section_number_levels: section_number_levels)
27
28
  end
28
29
 
29
30
  # Build a Toc model from a document.
@@ -6,11 +6,12 @@ module Coradoc
6
6
  #
7
7
  # Used by the SPA layout to provide client-side navigation data.
8
8
  class TocSerializer
9
- def build_json(document, options)
9
+ def build_json(document, opts)
10
10
  return { entries: [], numbered: false } unless document.is_a?(CoreModel::StructuralElement)
11
11
 
12
- numbered = options[:section_numbers] == true
13
- builder = TocBuilder.from_options(options)
12
+ opts = RenderOptions.new(**opts) unless opts.is_a?(RenderOptions)
13
+ numbered = opts.section_numbers == true
14
+ builder = TocBuilder.from_options(opts)
14
15
  toc = builder.build(document)
15
16
  { entries: serialize_entries(toc.entries), numbered: numbered }
16
17
  end
@@ -10,6 +10,8 @@ module Coradoc
10
10
  # This transformer converts CoreModel to HTML strings by delegating
11
11
  # to the existing theme/renderer pipeline.
12
12
  class FromCoreModel
13
+ include Coradoc::Transform::Base
14
+
13
15
  class << self
14
16
  # Transform a CoreModel to HTML string
15
17
  #
@@ -12,6 +12,8 @@ module Coradoc
12
12
  # Nokogiri::XML::Document or Nokogiri::XML::Node objects into CoreModel
13
13
  # by delegating to the existing input converter pipeline.
14
14
  class ToCoreModel
15
+ include Coradoc::Transform::Base
16
+
15
17
  class << self
16
18
  # Transform an HTML model (Nokogiri node) to CoreModel
17
19
  #
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Coradoc
4
4
  module Html
5
- VERSION = '1.1.14'
5
+ VERSION = '1.1.15'
6
6
  end
7
7
  end
data/lib/coradoc/html.rb CHANGED
@@ -21,6 +21,8 @@ module Coradoc
21
21
  module Html
22
22
  # Autoload HTML components
23
23
  autoload :Config, 'coradoc/html/config'
24
+ autoload :AssetResolver, 'coradoc/html/asset_resolver'
25
+ autoload :TagMapping, 'coradoc/html/tag_mapping'
24
26
  autoload :Escape, 'coradoc/html/escape'
25
27
  autoload :SectionNumberable, 'coradoc/html/section_numberable'
26
28
  autoload :TemplateCaching, 'coradoc/html/template_caching'
@@ -43,6 +45,7 @@ module Coradoc
43
45
  require 'coradoc/html/template_helpers'
44
46
  autoload :Renderer, 'coradoc/html/renderer'
45
47
  autoload :LayoutRenderer, 'coradoc/html/layout_renderer'
48
+ autoload :RenderOptions, 'coradoc/html/render_options'
46
49
  autoload :TocSerializer, 'coradoc/html/toc_serializer'
47
50
 
48
51
  # CoreModel transformers
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coradoc-html
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.14
4
+ version: 1.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -117,6 +117,7 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - LICENSE.txt
119
119
  - lib/coradoc/html.rb
120
+ - lib/coradoc/html/asset_resolver.rb
120
121
  - lib/coradoc/html/config.rb
121
122
  - lib/coradoc/html/converter_base.rb
122
123
  - lib/coradoc/html/drop.rb
@@ -189,10 +190,12 @@ files:
189
190
  - lib/coradoc/html/input/postprocessor.rb
190
191
  - lib/coradoc/html/layout_renderer.rb
191
192
  - lib/coradoc/html/output.rb
193
+ - lib/coradoc/html/render_options.rb
192
194
  - lib/coradoc/html/renderer.rb
193
195
  - lib/coradoc/html/section_numberable.rb
194
196
  - lib/coradoc/html/spa.rb
195
197
  - lib/coradoc/html/static.rb
198
+ - lib/coradoc/html/tag_mapping.rb
196
199
  - lib/coradoc/html/template_caching.rb
197
200
  - lib/coradoc/html/template_config.rb
198
201
  - lib/coradoc/html/template_helpers.rb