isodoc 1.0.28 → 1.1.3.pre.alpha

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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +4 -8
  3. data/.github/workflows/ubuntu.yml +18 -16
  4. data/.github/workflows/windows.yml +4 -8
  5. data/Rakefile +3 -1
  6. data/isodoc.gemspec +2 -2
  7. data/lib/isodoc.rb +2 -0
  8. data/lib/isodoc/base_style/metanorma_word.scss +0 -1
  9. data/lib/isodoc/base_style/reset.scss +3 -3
  10. data/lib/isodoc/common.rb +0 -4
  11. data/lib/isodoc/convert.rb +121 -58
  12. data/lib/isodoc/function/blocks.rb +42 -53
  13. data/lib/isodoc/function/blocks_example_note.rb +108 -0
  14. data/lib/isodoc/function/i18n.rb +1 -0
  15. data/lib/isodoc/function/inline.rb +25 -8
  16. data/lib/isodoc/function/lists.rb +12 -6
  17. data/lib/isodoc/function/references.rb +31 -36
  18. data/lib/isodoc/function/reqt.rb +14 -5
  19. data/lib/isodoc/function/section.rb +7 -11
  20. data/lib/isodoc/function/table.rb +4 -4
  21. data/lib/isodoc/function/terms.rb +3 -3
  22. data/lib/isodoc/function/to_word_html.rb +2 -2
  23. data/lib/isodoc/function/utils.rb +57 -50
  24. data/lib/isodoc/gem_tasks.rb +110 -0
  25. data/lib/isodoc/headlesshtml_convert.rb +7 -6
  26. data/lib/isodoc/html_convert.rb +2 -1
  27. data/lib/isodoc/html_function/html.rb +2 -2
  28. data/lib/isodoc/html_function/postprocess.rb +1 -1
  29. data/lib/isodoc/metadata.rb +69 -63
  30. data/lib/isodoc/pdf_convert.rb +8 -6
  31. data/lib/isodoc/presentation_xml_convert.rb +29 -0
  32. data/lib/isodoc/sassc_importer.rb +11 -0
  33. data/lib/isodoc/version.rb +1 -1
  34. data/lib/isodoc/word_convert.rb +2 -1
  35. data/lib/isodoc/word_function/body.rb +14 -48
  36. data/lib/isodoc/word_function/inline.rb +75 -0
  37. data/lib/isodoc/word_function/postprocess.rb +1 -0
  38. data/lib/isodoc/word_function/table.rb +3 -3
  39. data/lib/isodoc/xref.rb +59 -0
  40. data/lib/isodoc/{function → xref}/xref_anchor.rb +10 -21
  41. data/lib/isodoc/xref/xref_counter.rb +74 -0
  42. data/lib/isodoc/{function → xref}/xref_gen.rb +9 -22
  43. data/lib/isodoc/{function → xref}/xref_gen_seq.rb +41 -32
  44. data/lib/isodoc/{function → xref}/xref_sect_gen.rb +33 -23
  45. data/lib/isodoc/xslfo_convert.rb +16 -4
  46. data/spec/assets/{html.css → html.scss} +0 -0
  47. data/spec/assets/odf.emf +0 -0
  48. data/spec/assets/odf.svg +4 -0
  49. data/spec/assets/odf1.svg +4 -0
  50. data/spec/isodoc/blocks_spec.rb +216 -44
  51. data/spec/isodoc/footnotes_spec.rb +2 -2
  52. data/spec/isodoc/inline_spec.rb +208 -1
  53. data/spec/isodoc/lists_spec.rb +8 -8
  54. data/spec/isodoc/metadata_spec.rb +107 -3
  55. data/spec/isodoc/postproc_spec.rb +1320 -1350
  56. data/spec/isodoc/presentation_xml_spec.rb +20 -0
  57. data/spec/isodoc/ref_spec.rb +5 -5
  58. data/spec/isodoc/section_spec.rb +52 -0
  59. data/spec/isodoc/table_spec.rb +4 -4
  60. data/spec/isodoc/terms_spec.rb +7 -7
  61. data/spec/isodoc/xref_spec.rb +165 -45
  62. metadata +37 -29
  63. data/lib/isodoc/function/blocks_example.rb +0 -53
  64. data/lib/isodoc/function/xref_counter.rb +0 -50
@@ -2,7 +2,7 @@ module IsoDoc::Function
2
2
  module Blocks
3
3
  def recommendation_labels(node)
4
4
  [node.at(ns("./label")), node.at(ns("./title")),
5
- anchor(node['id'], :label, false)]
5
+ @xrefs.anchor(node['id'], :label, false)]
6
6
  end
7
7
 
8
8
  def recommendation_name(node, out, type)
@@ -60,8 +60,12 @@ module IsoDoc::Function
60
60
  %w(label title subject classification tag value inherit).include? n.name
61
61
  end
62
62
 
63
+ def reqt_attrs(node, klass)
64
+ attr_code(class: klass, id: node["id"], style: keep_style(node))
65
+ end
66
+
63
67
  def recommendation_parse(node, out)
64
- out.div **{ class: "recommend" } do |t|
68
+ out.div **reqt_attrs(node, "recommend") do |t|
65
69
  recommendation_name(node, t, @recommendation_lbl)
66
70
  recommendation_attributes(node, out)
67
71
  node.children.each do |n|
@@ -71,7 +75,7 @@ module IsoDoc::Function
71
75
  end
72
76
 
73
77
  def requirement_parse(node, out)
74
- out.div **{ class: "require" } do |t|
78
+ out.div **reqt_attrs(node, "require") do |t|
75
79
  recommendation_name(node, t, @requirement_lbl)
76
80
  recommendation_attributes(node, out)
77
81
  node.children.each do |n|
@@ -81,7 +85,7 @@ module IsoDoc::Function
81
85
  end
82
86
 
83
87
  def permission_parse(node, out)
84
- out.div **{ class: "permission" } do |t|
88
+ out.div **reqt_attrs(node, "permission") do |t|
85
89
  recommendation_name(node, t, @permission_lbl)
86
90
  recommendation_attributes(node, out)
87
91
  node.children.each do |n|
@@ -90,9 +94,14 @@ module IsoDoc::Function
90
94
  end
91
95
  end
92
96
 
97
+ def reqt_component_attrs(node)
98
+ attr_code(class: "requirement-" + node.name,
99
+ style: keep_style(node))
100
+ end
101
+
93
102
  def requirement_component_parse(node, out)
94
103
  return if node["exclude"] == "true"
95
- out.div **{ class: "requirement-" + node.name } do |div|
104
+ out.div **reqt_component_attrs(node) do |div|
96
105
  node.children.each do |n|
97
106
  parse(n, div)
98
107
  end
@@ -11,8 +11,8 @@ module IsoDoc::Function
11
11
  def inline_header_title(out, node, c1)
12
12
  out.span **{ class: "zzMoveToFollowing" } do |s|
13
13
  s.b do |b|
14
- if anchor(node['id'], :label, false) && !@suppressheadingnumbers
15
- b << "#{anchor(node['id'], :label)}#{clausedelim}"
14
+ if @xrefs.anchor(node['id'], :label, false) && !@suppressheadingnumbers
15
+ b << "#{@xrefs.anchor(node['id'], :label)}#{clausedelim}"
16
16
  clausedelimspace(out)
17
17
  end
18
18
  c1&.children&.each { |c2| parse(c2, b) }
@@ -26,8 +26,8 @@ module IsoDoc::Function
26
26
  if node["inline-header"] == "true"
27
27
  inline_header_title(out, node, c1)
28
28
  else
29
- div.send "h#{anchor(node['id'], :level, false) || '1'}" do |h|
30
- lbl = anchor(node['id'], :label, false)
29
+ div.send "h#{@xrefs.anchor(node['id'], :level, false) || '1'}" do |h|
30
+ lbl = @xrefs.anchor(node['id'], :label, false)
31
31
  h << "#{lbl}#{clausedelim}" if lbl && !@suppressheadingnumbers
32
32
  clausedelimspace(out) if lbl && !@suppressheadingnumbers
33
33
  c1&.children&.each { |c2| parse(c2, h) }
@@ -58,14 +58,10 @@ module IsoDoc::Function
58
58
  div.parent.at(".//h1")
59
59
  end
60
60
 
61
- MIDDLE_CLAUSE =
62
- "//clause[parent::sections][not(xmlns:title = 'Scope')]"\
63
- "[not(descendant::terms)]".freeze
64
-
65
61
  def clause(isoxml, out)
66
- isoxml.xpath(ns(self.class::MIDDLE_CLAUSE)).each do |c|
62
+ isoxml.xpath(ns(middle_clause)).each do |c|
67
63
  out.div **attr_code(id: c["id"]) do |s|
68
- clause_name(anchor(c['id'], :label),
64
+ clause_name(@xrefs.anchor(c['id'], :label),
69
65
  c&.at(ns("./title")), s, nil)
70
66
  c.elements.reject { |c1| c1.name == "title" }.each do |c1|
71
67
  parse(c1, s)
@@ -76,7 +72,7 @@ module IsoDoc::Function
76
72
 
77
73
  def annex_name(annex, name, div)
78
74
  div.h1 **{ class: "Annex" } do |t|
79
- t << "#{anchor(annex['id'], :label)}<br/><br/>"
75
+ t << "#{@xrefs.anchor(annex['id'], :label)}<br/><br/>"
80
76
  t.b do |b|
81
77
  name&.children&.each { |c2| parse(c2, b) }
82
78
  end
@@ -3,7 +3,7 @@ module IsoDoc::Function
3
3
 
4
4
  def table_title_parse(node, out)
5
5
  name = node.at(ns("./name"))
6
- lbl = anchor(node['id'], :label, false)
6
+ lbl = @xrefs.anchor(node['id'], :label, false)
7
7
  lbl = nil if labelled_ancestor(node)
8
8
  return if name.nil? && lbl.nil?
9
9
  out.p **{ class: "TableTitle", style: "text-align:center;" } do |p|
@@ -44,12 +44,12 @@ module IsoDoc::Function
44
44
  end
45
45
  end
46
46
 
47
- def make_table_attr(node)
47
+ def table_attrs(node)
48
48
  width = node["width"] ? "width:#{node['width']};" : nil
49
49
  attr_code(
50
50
  id: node["id"],
51
51
  class: "MsoISOTable",
52
- style: "border-width:1px;border-spacing:0;#{width}",
52
+ style: "border-width:1px;border-spacing:0;#{width}#{keep_style(node)}",
53
53
  title: node["alt"]
54
54
  )
55
55
  end
@@ -66,7 +66,7 @@ module IsoDoc::Function
66
66
  def table_parse(node, out)
67
67
  @in_table = true
68
68
  table_title_parse(node, out)
69
- out.table **make_table_attr(node) do |t|
69
+ out.table **table_attrs(node) do |t|
70
70
  tcaption(node, t)
71
71
  thead_parse(node, t)
72
72
  tbody_parse(node, t)
@@ -40,10 +40,10 @@ module IsoDoc::Function
40
40
  end
41
41
 
42
42
  def termnote_parse(node, out)
43
- out.div **{ class: "Note" } do |div|
43
+ out.div **note_attrs(node) do |div|
44
44
  first = node.first_element_child
45
45
  div.p do |p|
46
- p << "#{anchor(node['id'], :label) || '???'}: "
46
+ p << "#{@xrefs.anchor(node['id'], :label) || '???'}: "
47
47
  para_then_remainder(first, node, p, div)
48
48
  end
49
49
  end
@@ -59,7 +59,7 @@ module IsoDoc::Function
59
59
 
60
60
  def termdef_parse(node, out)
61
61
  out.p **{ class: "TermNum", id: node["id"] } do |p|
62
- p << "#{get_anchors[node["id"]][:label]}#{clausedelim}"
62
+ p << "#{@xrefs.get[node["id"]][:label]}#{clausedelim}"
63
63
  end
64
64
  set_termdomain("")
65
65
  node.children.each { |n| parse(n, out) }
@@ -18,7 +18,7 @@ module IsoDoc::Function
18
18
 
19
19
  def init_file(filename, debug)
20
20
  filepath = Pathname.new(filename)
21
- filename = filepath.sub_ext('').to_s
21
+ filename = filepath.sub_ext('').sub(/\.presentation$/, "").to_s
22
22
  dir = "#{filename}_files"
23
23
  unless debug
24
24
  Dir.mkdir(dir, 0777) unless File.exists?(dir)
@@ -45,7 +45,7 @@ module IsoDoc::Function
45
45
  head.style do |style|
46
46
  @standardstylesheet.open
47
47
  stylesheet = @standardstylesheet.read.
48
- gsub("FILENAME", File.basename(filename))
48
+ gsub("FILENAME", File.basename(filename).sub(/\.presentation$/, ""))
49
49
  style.comment "\n#{stylesheet}\n"
50
50
  end
51
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module IsoDoc::Function
2
4
  module Utils
3
5
  def date_range(date)
@@ -9,50 +11,50 @@ module IsoDoc::Function
9
11
  end
10
12
 
11
13
  def insert_tab(out, n)
12
- [1..n].each { out << "&nbsp; " }
14
+ [1..n].each { out << '&nbsp; ' }
13
15
  end
14
16
 
15
17
  # add namespaces for Word fragments
16
- NOKOHEAD = <<~HERE.freeze
17
- <!DOCTYPE html SYSTEM
18
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
19
- <html xmlns="http://www.w3.org/1999/xhtml">
20
- <head> <title></title> <meta charset="UTF-8" /> </head>
21
- <body> </body> </html>
18
+ NOKOHEAD = <<~HERE
19
+ <!DOCTYPE html SYSTEM
20
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
21
+ <html xmlns="http://www.w3.org/1999/xhtml">
22
+ <head> <title></title> <meta charset="UTF-8" /> </head>
23
+ <body> </body> </html>
22
24
  HERE
23
25
 
24
26
  # block for processing XML document fragments as XHTML,
25
27
  # to allow for HTMLentities
26
28
  def noko(&block)
27
29
  doc = ::Nokogiri::XML.parse(NOKOHEAD)
28
- fragment = doc.fragment("")
30
+ fragment = doc.fragment('')
29
31
  ::Nokogiri::XML::Builder.with fragment, &block
30
- fragment.to_xml(encoding: "US-ASCII").lines.map do |l|
31
- l.gsub(/\s*\n/, "")
32
+ fragment.to_xml(encoding: 'US-ASCII').lines.map do |l|
33
+ l.gsub(/\s*\n/, '')
32
34
  end
33
35
  end
34
36
 
35
37
  def attr_code(attributes)
36
38
  attributes = attributes.reject { |_, val| val.nil? }.map
37
39
  attributes.map do |k, v|
38
- [k, (v.is_a? String) ? HTMLEntities.new.decode(v) : v]
40
+ [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
39
41
  end.to_h
40
42
  end
41
43
 
42
44
  DOCTYPE_HDR = '<!DOCTYPE html SYSTEM '\
43
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
45
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
44
46
 
45
47
  def to_xhtml(xml)
46
- xml.gsub!(/<\?xml[^>]*>/, "")
47
- /<!DOCTYPE /.match xml or xml = DOCTYPE_HDR + xml
48
+ xml.gsub!(/<\?xml[^>]*>/, '')
49
+ /<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
48
50
  xml = xml.split(/(\&[^ \r\n\t#;]+;)/).map do |t|
49
- /^(\&[^ \t\r\n#;]+;)/.match(t) ?
51
+ /^(\&[^ \t\r\n#;]+;)/.match?(t) ?
50
52
  HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
51
- end.join("")
53
+ end.join('')
52
54
  begin
53
- Nokogiri::XML.parse(xml) { |config| config.strict }
55
+ Nokogiri::XML.parse(xml, &:strict)
54
56
  rescue Nokogiri::XML::SyntaxError => e
55
- File.open("#{@filename}.#{@format}.err", "w:UTF-8") { |f| f.write xml }
57
+ File.open("#{@filename}.#{@format}.err", 'w:UTF-8') { |f| f.write xml }
56
58
  abort "Malformed Output XML for #{@format}: #{e} (see #{@filename}.#{@format}.err)"
57
59
  end
58
60
  end
@@ -64,7 +66,7 @@ module IsoDoc::Function
64
66
  end
65
67
 
66
68
  def from_xhtml(xml)
67
- xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, "")
69
+ xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, '')
68
70
  end
69
71
 
70
72
  CLAUSE_ANCESTOR =
@@ -72,7 +74,7 @@ module IsoDoc::Function
72
74
  "local-name() = 'acknowledgements' or local-name() = 'term' or "\
73
75
  "local-name() = 'appendix' or local-name() = 'foreword' or "\
74
76
  "local-name() = 'introduction' or local-name() = 'terms' or "\
75
- "local-name() = 'clause' or local-name() = 'references']/@id".freeze
77
+ "local-name() = 'clause' or local-name() = 'references']/@id"
76
78
 
77
79
  def get_clause_id(node)
78
80
  clause = node.xpath(CLAUSE_ANCESTOR)
@@ -86,7 +88,7 @@ module IsoDoc::Function
86
88
  "local-name() = 'acknowledgements' or local-name() = 'term' or "\
87
89
  "local-name() = 'clause' or local-name() = 'references' or "\
88
90
  "local-name() = 'figure' or local-name() = 'formula' or "\
89
- "local-name() = 'table' or local-name() = 'example']/@id".freeze
91
+ "local-name() = 'table' or local-name() = 'example']/@id"
90
92
 
91
93
  def get_note_container_id(node)
92
94
  container = node.xpath(NOTE_CONTAINER_ANCESTOR)
@@ -94,7 +96,7 @@ module IsoDoc::Function
94
96
  end
95
97
 
96
98
  def sentence_join(array)
97
- return "" if array.nil? || array.empty?
99
+ return '' if array.nil? || array.empty?
98
100
  if array.length == 1 then array[0]
99
101
  else
100
102
  IsoDoc::Function::I18n::l10n("#{array[0..-2].join(', ')} "\
@@ -105,25 +107,25 @@ module IsoDoc::Function
105
107
 
106
108
  # avoid `; avoid {{ (Liquid Templates); avoid [[ (Javascript)
107
109
  def extract_delims(text)
108
- @openmathdelim = "(#("
109
- @closemathdelim = ")#)"
110
+ @openmathdelim = '(#('
111
+ @closemathdelim = ')#)'
110
112
  while text.include?(@openmathdelim) || text.include?(@closemathdelim)
111
- @openmathdelim += "("
112
- @closemathdelim += ")"
113
+ @openmathdelim += '('
114
+ @closemathdelim += ')'
113
115
  end
114
116
  [@openmathdelim, @closemathdelim]
115
117
  end
116
118
 
117
119
  def header_strip(h)
118
- h = h.to_s.gsub(%r{<br\s*/>}, " ").gsub(/<\/?h[123456][^>]*>/, "").
119
- gsub(/<\/?b[^>]*>/, "")
120
+ h = h.to_s.gsub(%r{<br\s*/>}, ' ').gsub(/<\/?h[123456][^>]*>/, '')
121
+ .gsub(/<\/?b[^>]*>/, '')
120
122
  h1 = to_xhtml_fragment(h.dup)
121
123
  h1.traverse do |x|
122
- x.replace(" ") if x.name == "span" && /mso-tab-count/.match(x["style"])
123
- x.remove if x.name == "span" && x["class"] == "MsoCommentReference"
124
- x.remove if x.name == "a" && x["class"] == "FootnoteRef"
125
- x.remove if x.name == "span" && /mso-bookmark/.match(x["style"])
126
- x.replace(x.children) if x.name == "a"
124
+ x.replace(' ') if x.name == 'span' && /mso-tab-count/.match(x['style'])
125
+ x.remove if x.name == 'span' && x['class'] == 'MsoCommentReference'
126
+ x.remove if x.name == 'a' && x['class'] == 'FootnoteRef'
127
+ x.remove if x.name == 'span' && /mso-bookmark/.match(x['style'])
128
+ x.replace(x.children) if x.name == 'a'
127
129
  end
128
130
  from_xhtml(h1)
129
131
  end
@@ -135,9 +137,9 @@ module IsoDoc::Function
135
137
  def liquid(doc)
136
138
  # unescape HTML escapes in doc
137
139
  doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
138
- a[2] = a[2].gsub(/\&lt;/, "<").gsub(/\&gt;/, ">") if a.size > 2
139
- a.join("")
140
- end.join("")
140
+ a[2] = a[2].gsub(/\&lt;/, '<').gsub(/\&gt;/, '>') if a.size > 2
141
+ a.join('')
142
+ end.join('')
141
143
  Liquid::Template.parse(doc)
142
144
  end
143
145
 
@@ -147,36 +149,41 @@ module IsoDoc::Function
147
149
  end
148
150
 
149
151
  def populate_template(docxml, _format = nil)
150
- meta = @meta.get.merge(@labels || {})
152
+ meta = @meta
153
+ .get
154
+ .merge(@labels || {})
155
+ .merge(@meta.labels || {})
156
+ .merge(@meta.fonts_options || {})
151
157
  template = liquid(docxml)
152
- template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h).
153
- gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
158
+ template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
159
+ .gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
154
160
  end
155
161
 
156
- def save_dataimage(uri, relative_dir = true)
162
+ def save_dataimage(uri, _relative_dir = true)
157
163
  %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
158
- imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
159
- Tempfile.open(["image", ".#{imgtype}"]) do |f|
164
+ imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
165
+ imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
166
+ Tempfile.open(['image', ".#{imgtype}"]) do |f|
160
167
  f.binmode
161
168
  f.write(Base64.strict_decode64(imgdata))
162
- @tempfile_cache << f #persist to the end
169
+ @tempfile_cache << f # persist to the end
163
170
  f.path
164
171
  end
165
172
  end
166
173
 
167
174
  def image_localfile(i)
168
- if /^data:image/.match i["src"]
169
- save_dataimage(i["src"], false)
170
- elsif %r{^([A-Z]:)?/}.match i["src"]
171
- i["src"]
175
+ if /^data:image/.match? i['src']
176
+ save_dataimage(i['src'], false)
177
+ elsif %r{^([A-Z]:)?/}.match? i['src']
178
+ i['src']
172
179
  else
173
- File.join(@localdir, i["src"])
180
+ File.join(@localdir, i['src'])
174
181
  end
175
182
  end
176
183
 
177
184
  def labelled_ancestor(node)
178
- return !node.ancestors("example, requirement, recommendation, permission, "\
179
- "table, figure, sourcecode").empty?
185
+ !node.ancestors('example, requirement, recommendation, permission, '\
186
+ 'table, figure, sourcecode').empty?
180
187
  end
181
188
  end
182
189
  end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sassc'
4
+ require 'isodoc/sassc_importer'
5
+ require 'rake/clean'
6
+
7
+ module IsoDoc
8
+ module GemTasks
9
+ extend Rake::DSL if defined? Rake::DSL
10
+
11
+ module_function
12
+
13
+ def install
14
+ rule '.css' => [proc { |tn| tn.sub(/\.css$/, '.scss') }] do |current_task|
15
+ begin
16
+ puts(current_task)
17
+ compile_scss_task(current_task)
18
+ rescue StandardError => e
19
+ puts(e.message)
20
+ puts("skiping #{current_task}")
21
+ end
22
+ end
23
+
24
+ scss_files = Rake::FileList['lib/**/*.scss']
25
+ source_files = scss_files.ext('.css')
26
+
27
+ task :comment_out_liquid do
28
+ process_css_files(scss_files) do |file_name|
29
+ comment_out_liquid(File.read(file_name, encoding: 'UTF-8'))
30
+ end
31
+ end
32
+
33
+ task build_scss: [:comment_out_liquid].push(*source_files) do
34
+ process_css_files(scss_files) do |file_name|
35
+ uncomment_out_liquid(File.read(file_name, encoding: 'UTF-8'))
36
+ end
37
+ CLEAN.each do |css_file|
38
+ sh "git add #{css_file}"
39
+ end
40
+ puts('Built scss!')
41
+ end
42
+
43
+ Rake::Task['build'].enhance [:build_scss] do
44
+ CLEAN.each do |css_file|
45
+ sh "git rm --cached #{css_file}"
46
+ end
47
+ Rake::Task[:clean].invoke
48
+ end
49
+ end
50
+
51
+ def process_css_files(scss_files)
52
+ scss_files.each do |file_name|
53
+ result = yield(file_name)
54
+ File.open(file_name, 'w', encoding: 'UTF-8') do |file|
55
+ file.puts(result)
56
+ end
57
+ end
58
+ end
59
+
60
+ def comment_out_liquid(text)
61
+ text.split("\n").map do |line|
62
+ if line.match?(/{({|%).+(}|%)}/)
63
+ "/* LIQUID_COMMENT#{line}LIQUID_COMMENT */"
64
+ else
65
+ line
66
+ end
67
+ end
68
+ .join("\n")
69
+ end
70
+
71
+ def uncomment_out_liquid(text)
72
+ text
73
+ .gsub('/* LIQUID_COMMENT', '')
74
+ .gsub('LIQUID_COMMENT */', '')
75
+ .gsub('"{{', '{{').gsub('}}"', '}}')
76
+ end
77
+
78
+ def fonts_placeholder
79
+ <<~TEXT
80
+ $bodyfont: '{{bodyfont}}';
81
+ $headerfont: '{{headerfont}}';
82
+ $monospacefont: '{{monospacefont}}';
83
+ TEXT
84
+ end
85
+
86
+ def compile_scss(filename)
87
+ require 'sassc'
88
+ [File.join(Gem.loaded_specs['isodoc'].full_gem_path, 'lib', 'isodoc'),
89
+ File.dirname(filename)].each do |name|
90
+ SassC.load_paths << name
91
+ end
92
+ sheet_content = File.read(filename, encoding: 'UTF-8')
93
+ SassC::Engine.new(fonts_placeholder + sheet_content,
94
+ syntax: :scss,
95
+ importer: SasscImporter)
96
+ .render
97
+ end
98
+
99
+ def compile_scss_task(current_task)
100
+ filename = current_task.source
101
+ basename = File.basename(filename, '.*')
102
+ compiled_path = File.join(File.dirname(filename), "#{basename}.css")
103
+ content = uncomment_out_liquid(compile_scss(filename))
104
+ File.open(compiled_path, 'w:UTF-8') do |f|
105
+ f.write(content)
106
+ end
107
+ CLEAN << compiled_path
108
+ end
109
+ end
110
+ end