openxml_docx_templater 0.1.3 → 0.2.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 +4 -4
- data/.rubocop.yml +40 -0
- data/Rakefile +2 -2
- data/circle.yml +7 -0
- data/examples/example.rb +1 -1
- data/examples/example_template_output.docx +0 -0
- data/lib/openxml_docx_templater.rb +2 -0
- data/lib/openxml_docx_templater/debug.rb +2 -0
- data/lib/openxml_docx_templater/docx_eruby.rb +15 -14
- data/lib/openxml_docx_templater/escape_xml.rb +9 -10
- data/lib/openxml_docx_templater/generator.rb +5 -3
- data/lib/openxml_docx_templater/line.rb +15 -20
- data/lib/openxml_docx_templater/node_type.rb +2 -0
- data/lib/openxml_docx_templater/template.rb +5 -3
- data/lib/openxml_docx_templater/version.rb +3 -1
- data/lib/openxml_docx_templater/xml_reader.rb +6 -8
- data/openxml_docx_templater.gemspec +15 -12
- metadata +11 -10
- data/.travis.yml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6acf4751ef96a4c85d4e5a17d23fe65263ea368a
|
4
|
+
data.tar.gz: 664cff7779ba79761ff6e3e9c2c1de51cfd5057c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e639d4980436809ba24516da4a442e0b090318643b22ca12c3da4f60c886f4fd3b3d6e91941d586f265dc39e1813954337c8da2fcff7bf471fb8a1ebaa0269d8
|
7
|
+
data.tar.gz: 22fa05283f6009d2817a32629097f60c43f1d1c19cd916ab7ce4c60066650b1650965d5aba2ea8f42f6891d5311847da33df4a869bbf65f7a999645ea98aae58
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
|
4
|
+
DisplayCopNames: true
|
5
|
+
DisplayStyleGuide: true
|
6
|
+
|
7
|
+
AsciiComments:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
ClassLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
MethodLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Documentation:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/ClassAndModuleChildren:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/PredicateName:
|
23
|
+
NameWhitelist:
|
24
|
+
- is_a?
|
25
|
+
|
26
|
+
Style/TrailingCommaInLiteral:
|
27
|
+
EnforcedStyleForMultiline: comma
|
28
|
+
|
29
|
+
Style/TrailingCommaInArguments:
|
30
|
+
EnforcedStyleForMultiline: comma
|
31
|
+
|
32
|
+
Layout/AlignParameters:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
LineLength:
|
36
|
+
Max: 120
|
37
|
+
|
38
|
+
Lint/UnifiedInteger:
|
39
|
+
Description: 'Use Integer instead of Fixnum or Bignum'
|
40
|
+
Enabled: false
|
data/Rakefile
CHANGED
data/circle.yml
ADDED
data/examples/example.rb
CHANGED
Binary file
|
@@ -1,45 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OpenxmlDocxTemplater
|
2
4
|
class DocxEruby
|
3
5
|
include Debug
|
4
6
|
|
5
7
|
EMBEDDED_PATTERN = /\{%([=%]+)?(.*?)-?%\}/m
|
6
8
|
|
7
|
-
def initialize
|
9
|
+
def initialize(template)
|
8
10
|
@src = convert template
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
11
|
+
return unless debug?
|
12
|
+
File.open(debug_file_path, 'w') do |f|
|
13
|
+
f << @src
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
def evaluate
|
17
|
+
def evaluate(context)
|
17
18
|
eval(@src, context)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def convert
|
23
|
+
def convert(template)
|
23
24
|
src = "_buf = '';"
|
24
25
|
buffer = []
|
25
26
|
|
26
|
-
template.each_node do |node,
|
27
|
+
template.each_node do |node, _type|
|
27
28
|
buffer << process_instruction(node)
|
28
29
|
buffer.flatten!
|
29
30
|
end
|
30
31
|
|
31
|
-
buffer.each { |line| src
|
32
|
-
src
|
32
|
+
buffer.each { |line| src += line.to_buf }
|
33
|
+
src += "\n_buf.to_s\n"
|
33
34
|
end
|
34
35
|
|
35
|
-
def process_instruction
|
36
|
+
def process_instruction(text)
|
36
37
|
pos = 0
|
37
38
|
src = []
|
38
39
|
|
39
40
|
text.scan(EMBEDDED_PATTERN) do |indicator, code|
|
40
41
|
m = Regexp.last_match
|
41
42
|
middle = text[pos...m.begin(0)]
|
42
|
-
pos
|
43
|
+
pos = m.end(0)
|
43
44
|
src << Line.text(middle) unless middle.empty?
|
44
45
|
|
45
46
|
if !indicator # <% %>
|
@@ -51,9 +52,9 @@ module OpenxmlDocxTemplater
|
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
rest = pos
|
55
|
+
rest = pos.zero? ? text : text[pos..-1]
|
55
56
|
|
56
|
-
src << Line.text(rest) unless rest.nil?
|
57
|
+
src << Line.text(rest) unless rest.nil? || rest.empty?
|
57
58
|
src
|
58
59
|
end
|
59
60
|
end
|
@@ -1,26 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class String
|
3
4
|
CODE_LINE_PATTERN = /{(.*?)%(.+?)%(.*?)}/
|
4
5
|
TAG_PATTERN = /<(.+?)>[\n]?/m
|
5
6
|
|
6
7
|
def escape_xml
|
7
|
-
mgsub
|
8
|
+
mgsub(/&/ => '&', /</ => '<', />/ => '>')
|
8
9
|
end
|
9
10
|
|
10
11
|
def convert_newlines
|
11
|
-
gsub
|
12
|
-
self
|
12
|
+
gsub("\n", '<w:br/>')
|
13
13
|
end
|
14
14
|
|
15
15
|
def refact
|
16
|
-
gsub(CODE_LINE_PATTERN) { |result| result.gsub(TAG_PATTERN,
|
16
|
+
gsub(CODE_LINE_PATTERN) { |result| result.gsub(TAG_PATTERN, '') }
|
17
17
|
end
|
18
18
|
|
19
|
-
def mgsub
|
20
|
-
regexp_fragments = key_value_pairs.
|
21
|
-
gsub
|
22
|
-
key_value_pairs.detect { |k,
|
19
|
+
def mgsub(key_value_pairs = {})
|
20
|
+
regexp_fragments = key_value_pairs.keys
|
21
|
+
gsub(Regexp.union(*regexp_fragments)) do |match|
|
22
|
+
key_value_pairs.detect { |k, _v| k =~ match }[1]
|
23
23
|
end
|
24
|
-
self
|
25
24
|
end
|
26
25
|
end
|
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OpenxmlDocxTemplater
|
2
4
|
module Generator
|
3
|
-
def render_msword
|
5
|
+
def render_msword(template_path, output_path = output_name(template_path))
|
4
6
|
template = Template.new template_path, output_path
|
5
7
|
template.process binding
|
6
8
|
end
|
7
9
|
|
8
10
|
private
|
9
11
|
|
10
|
-
def output_name
|
12
|
+
def output_name(input)
|
11
13
|
if input =~ /(.+)\.docx\Z/
|
12
|
-
"#{
|
14
|
+
"#{Regexp.last_match(1)}_output.docx"
|
13
15
|
else
|
14
16
|
"#{input}_output.docx"
|
15
17
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OpenxmlDocxTemplater
|
2
4
|
class Line
|
3
5
|
attr_reader :text
|
4
6
|
|
5
|
-
def initialize
|
7
|
+
def initialize(text)
|
6
8
|
@text = text
|
7
9
|
end
|
8
10
|
|
@@ -10,59 +12,52 @@ module OpenxmlDocxTemplater
|
|
10
12
|
@text
|
11
13
|
end
|
12
14
|
|
13
|
-
def self.text
|
15
|
+
def self.text(txt)
|
14
16
|
TextLine.new txt
|
15
17
|
end
|
16
18
|
|
17
|
-
def self.code
|
19
|
+
def self.code(txt)
|
18
20
|
CodeLine.new txt
|
19
21
|
end
|
20
22
|
|
21
|
-
def self.string
|
22
|
-
StringLine.new
|
23
|
+
def self.string(txt)
|
24
|
+
StringLine.new(txt)
|
23
25
|
end
|
24
26
|
|
25
|
-
def self.literal
|
27
|
+
def self.literal(txt)
|
26
28
|
LiteralLine.new txt
|
27
29
|
end
|
28
|
-
|
29
30
|
end
|
30
31
|
|
31
32
|
class TextLine < Line
|
32
33
|
def to_buf
|
33
|
-
" _buf << '
|
34
|
+
" _buf << '#{escape_text(@text)}';"
|
34
35
|
end
|
35
36
|
|
36
|
-
def escape_text
|
37
|
+
def escape_text(text)
|
37
38
|
text.gsub(/['\\]/, '\\\\\&')
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
42
|
class CodeLine < Line
|
42
43
|
def to_buf
|
43
|
-
escape_code(@text)
|
44
|
+
"#{escape_code(@text)};"
|
44
45
|
end
|
45
46
|
|
46
|
-
def escape_code
|
47
|
-
code.mgsub
|
47
|
+
def escape_code(code)
|
48
|
+
code.mgsub(/'/ => "'", />/ => '>', /</ => '<', /"/ => '"', /&/ => '&')
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
52
|
class StringLine < CodeLine
|
52
53
|
def to_buf
|
53
|
-
" _buf << (
|
54
|
-
end
|
55
|
-
|
56
|
-
def convert_newlines text
|
57
|
-
text.gsub("First line", '<w:br/>')
|
54
|
+
" _buf << (#{escape_code(@text)}).to_s.escape_xml.convert_newlines;"
|
58
55
|
end
|
59
56
|
end
|
60
57
|
|
61
58
|
class LiteralLine < CodeLine
|
62
59
|
def to_buf
|
63
|
-
" _buf << (
|
60
|
+
" _buf << (#{escape_code(@text)}).to_s;"
|
64
61
|
end
|
65
62
|
end
|
66
|
-
|
67
63
|
end
|
68
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'zip'
|
2
4
|
require 'fileutils'
|
3
5
|
|
@@ -10,16 +12,16 @@ module OpenxmlDocxTemplater
|
|
10
12
|
@template = output
|
11
13
|
end
|
12
14
|
|
13
|
-
def process
|
15
|
+
def process(context)
|
14
16
|
tmpfiles = []
|
15
17
|
Zip::File.open(@template) do |zipfile|
|
16
18
|
zipfile.entries.select { |entry| entry.name[/\.xml$/] }.each do |xml_file|
|
17
|
-
content = zipfile.read(xml_file).refact.force_encoding(
|
19
|
+
content = zipfile.read(xml_file).refact.force_encoding('utf-8')
|
18
20
|
|
19
21
|
docxeruby = DocxEruby.new(XmlReader.new(content))
|
20
22
|
out = docxeruby.evaluate(context)
|
21
23
|
|
22
|
-
tmpfiles << (file = Tempfile.new(
|
24
|
+
tmpfiles << (file = Tempfile.new('openxml_template'))
|
23
25
|
file << out
|
24
26
|
file.close
|
25
27
|
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OpenxmlDocxTemplater
|
2
4
|
class XmlReader
|
3
|
-
|
4
|
-
def initialize src
|
5
|
+
def initialize(src)
|
5
6
|
@src = src
|
6
7
|
end
|
7
8
|
|
@@ -20,12 +21,9 @@ module OpenxmlDocxTemplater
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
def node_type
|
24
|
-
if text
|
25
|
-
|
26
|
-
else
|
27
|
-
NodeType::TEMPLATE
|
28
|
-
end
|
24
|
+
def node_type(text)
|
25
|
+
return NodeType::CONTROL if text.match?(/\s*\{%[^=#].+?%\}\s*/)
|
26
|
+
NodeType::TEMPLATE
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
@@ -1,27 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# coding: utf-8
|
4
|
+
|
2
5
|
lib = File.expand_path('../lib', __FILE__)
|
3
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
7
|
require 'openxml_docx_templater/version'
|
5
8
|
|
6
9
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
10
|
+
spec.name = 'openxml_docx_templater'
|
8
11
|
spec.version = OpenxmlDocxTemplater::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
12
|
+
spec.authors = ['Andrew Ageev']
|
13
|
+
spec.email = ['ageev86@gmail.com']
|
11
14
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
15
|
+
spec.summary = 'Simple creation .docx files by templates'
|
16
|
+
spec.description = 'Simple creation .docx files by templates'
|
17
|
+
spec.homepage = 'https://github.com/AgeevAndrew/openxml_docx_templater'
|
18
|
+
spec.license = 'MIT'
|
16
19
|
|
17
20
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.bindir =
|
21
|
+
spec.bindir = 'exe'
|
19
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
-
spec.require_paths = [
|
23
|
+
spec.require_paths = ['lib']
|
21
24
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency 'bundler'
|
26
|
+
spec.add_development_dependency 'rake', '~> 12.1'
|
24
27
|
spec.add_dependency 'rubyzip'
|
25
28
|
|
26
|
-
spec.add_development_dependency
|
29
|
+
spec.add_development_dependency 'rspec'
|
27
30
|
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openxml_docx_templater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Ageev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '12.1'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '12.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rubyzip
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,13 +75,14 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
77
|
- ".rspec"
|
78
|
-
- ".
|
78
|
+
- ".rubocop.yml"
|
79
79
|
- Gemfile
|
80
80
|
- LICENSE.txt
|
81
81
|
- README.md
|
82
82
|
- Rakefile
|
83
83
|
- bin/console
|
84
84
|
- bin/setup
|
85
|
+
- circle.yml
|
85
86
|
- examples/example.rb
|
86
87
|
- examples/example_template.docx
|
87
88
|
- examples/example_template_output.docx
|
@@ -118,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
119
|
version: '0'
|
119
120
|
requirements: []
|
120
121
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.
|
122
|
+
rubygems_version: 2.6.11
|
122
123
|
signing_key:
|
123
124
|
specification_version: 4
|
124
125
|
summary: Simple creation .docx files by templates
|
data/.travis.yml
DELETED