htot_conv 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +135 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +141 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/htot_conv +111 -0
- data/htot_conv.gemspec +36 -0
- data/lib/htot_conv/generator/base.rb +34 -0
- data/lib/htot_conv/generator/xlsx_type0.rb +23 -0
- data/lib/htot_conv/generator/xlsx_type1.rb +25 -0
- data/lib/htot_conv/generator/xlsx_type2.rb +37 -0
- data/lib/htot_conv/generator/xlsx_type4.rb +53 -0
- data/lib/htot_conv/generator/xlsx_type5.rb +45 -0
- data/lib/htot_conv/generator.rb +28 -0
- data/lib/htot_conv/outline.rb +157 -0
- data/lib/htot_conv/parser/base.rb +14 -0
- data/lib/htot_conv/parser/html_list.rb +60 -0
- data/lib/htot_conv/parser/simple_text.rb +52 -0
- data/lib/htot_conv/parser.rb +24 -0
- data/lib/htot_conv/util.rb +12 -0
- data/lib/htot_conv/version.rb +3 -0
- data/lib/htot_conv.rb +18 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: db822ef12503c3c67ad25292d6843071c98ace01
|
4
|
+
data.tar.gz: 8bf51fe9de74f2ab6d135dd7a65f212df9d3a4dc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d7e7917107721f317b69f02d18eacf268241e4fdee0bc601b927781fccd1e8cdf0faddb4dd99581bf75ed5e1e56ec744c58d2f7cad5ca601bb93d1cfa4db6e1
|
7
|
+
data.tar.gz: f3065da8d0f122319037639cc1934296a804d8080241bd5b611aa6f0372a2fbe7ff91e9c234e4f31a825c7f9c51a8ad8ce2684e20e6a31e2a27ae6386288b00e
|
data/.gitignore
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
|
2
|
+
# Created by https://www.gitignore.io/api/vim,emacs,ruby
|
3
|
+
|
4
|
+
### Emacs ###
|
5
|
+
# -*- mode: gitignore; -*-
|
6
|
+
*~
|
7
|
+
\#*\#
|
8
|
+
/.emacs.desktop
|
9
|
+
/.emacs.desktop.lock
|
10
|
+
*.elc
|
11
|
+
auto-save-list
|
12
|
+
tramp
|
13
|
+
.\#*
|
14
|
+
|
15
|
+
# Org-mode
|
16
|
+
.org-id-locations
|
17
|
+
*_archive
|
18
|
+
|
19
|
+
# flymake-mode
|
20
|
+
*_flymake.*
|
21
|
+
|
22
|
+
# eshell files
|
23
|
+
/eshell/history
|
24
|
+
/eshell/lastdir
|
25
|
+
|
26
|
+
# elpa packages
|
27
|
+
/elpa/
|
28
|
+
|
29
|
+
# reftex files
|
30
|
+
*.rel
|
31
|
+
|
32
|
+
# AUCTeX auto folder
|
33
|
+
/auto/
|
34
|
+
|
35
|
+
# cask packages
|
36
|
+
.cask/
|
37
|
+
dist/
|
38
|
+
|
39
|
+
# Flycheck
|
40
|
+
flycheck_*.el
|
41
|
+
|
42
|
+
# server auth directory
|
43
|
+
/server/
|
44
|
+
|
45
|
+
# projectiles files
|
46
|
+
.projectile
|
47
|
+
projectile-bookmarks.eld
|
48
|
+
|
49
|
+
# directory configuration
|
50
|
+
.dir-locals.el
|
51
|
+
|
52
|
+
# saveplace
|
53
|
+
places
|
54
|
+
|
55
|
+
# url cache
|
56
|
+
url/cache/
|
57
|
+
|
58
|
+
# cedet
|
59
|
+
ede-projects.el
|
60
|
+
|
61
|
+
# smex
|
62
|
+
smex-items
|
63
|
+
|
64
|
+
# company-statistics
|
65
|
+
company-statistics-cache.el
|
66
|
+
|
67
|
+
# anaconda-mode
|
68
|
+
anaconda-mode/
|
69
|
+
|
70
|
+
### Ruby ###
|
71
|
+
*.gem
|
72
|
+
*.rbc
|
73
|
+
/.config
|
74
|
+
/coverage/
|
75
|
+
/InstalledFiles
|
76
|
+
/pkg/
|
77
|
+
/spec/reports/
|
78
|
+
/spec/examples.txt
|
79
|
+
/test/tmp/
|
80
|
+
/test/version_tmp/
|
81
|
+
/tmp/
|
82
|
+
|
83
|
+
# Used by dotenv library to load environment variables.
|
84
|
+
# .env
|
85
|
+
|
86
|
+
## Specific to RubyMotion:
|
87
|
+
.dat*
|
88
|
+
.repl_history
|
89
|
+
build/
|
90
|
+
*.bridgesupport
|
91
|
+
build-iPhoneOS/
|
92
|
+
build-iPhoneSimulator/
|
93
|
+
|
94
|
+
## Specific to RubyMotion (use of CocoaPods):
|
95
|
+
#
|
96
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
97
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
98
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
99
|
+
#
|
100
|
+
# vendor/Pods/
|
101
|
+
|
102
|
+
## Documentation cache and generated files:
|
103
|
+
/.yardoc/
|
104
|
+
/_yardoc/
|
105
|
+
/doc/
|
106
|
+
/rdoc/
|
107
|
+
|
108
|
+
## Environment normalization:
|
109
|
+
/.bundle/
|
110
|
+
/vendor/bundle
|
111
|
+
/lib/bundler/man/
|
112
|
+
|
113
|
+
# for a library or gem, you might want to ignore these files since the code is
|
114
|
+
# intended to run in multiple environments; otherwise, check them in:
|
115
|
+
Gemfile.lock
|
116
|
+
# .ruby-version
|
117
|
+
# .ruby-gemset
|
118
|
+
|
119
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
120
|
+
.rvmrc
|
121
|
+
|
122
|
+
### Vim ###
|
123
|
+
# swap
|
124
|
+
[._]*.s[a-v][a-z]
|
125
|
+
[._]*.sw[a-p]
|
126
|
+
[._]s[a-v][a-z]
|
127
|
+
[._]sw[a-p]
|
128
|
+
# session
|
129
|
+
Session.vim
|
130
|
+
# temporary
|
131
|
+
.netrwhist
|
132
|
+
# auto-generated tag files
|
133
|
+
tags
|
134
|
+
|
135
|
+
# End of https://www.gitignore.io/api/vim,emacs,ruby
|
data/.travis.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
cache: bundler
|
4
|
+
rvm:
|
5
|
+
- 2.3.4
|
6
|
+
before_install: gem install bundler -v 1.12.5
|
7
|
+
notifications:
|
8
|
+
email: false
|
9
|
+
slack:
|
10
|
+
secure: "XBa7qrPhwAl3D8C2mnzHHPlFcWj/IDjQ2+ab1P+oaWSzUd6kzFaQeuuBp21omIozfZwZNOLKRLTquN7vrenBL5h9+wtJsIzx5VK9bwPQijm8MAPQ4tWuhYTJfRmEQxhxkT/TKj+OhHLEgf1ZybDdw4PIsSjQEbpGr2Ro6pT13SS6DcmWPBM7eRryd0CN9Y2/bml94nF48LsNh4u5duTDHuB1+CD0dsbN+jtaPb0+rl2VK8+NrEhi4ghr4HKLvNRVyRLfc53aLsJyv5Wehhv5/iAJIeTXV/ys1TLEpt75FIDTTmZDj3zslHCShOuer8O1wXpofOXNOdbHjQ7tGjcg8nit6FezbjBJxPW6ocI3cq7Tl3lVcQqS0Z1s4mtfqgVm6Fw+eRtbFcXVSOu+NyS1ArlEYp624DKsFAb2asELKBD64r18dRSTecdD6LpUe5Dremw5OP4UfVcekbtNs31X/G11WZE6LGidfJjr3Yk9Y16T05ZykGtZDttykhFbDt8dd/YGu5f3rsPsPLVcTYa3ciVk4+e+V8rwNjUZ81o30ChS1PEedUsq7ttZ2QJj4wC6awdaLp+ue+yn7cjJPPZY3cpcgiVTaWjDjqyeGPB/sf0cVhB1nAnkR0d+YIBa+01v7uerfKpZ/UvJSDXCYy1GOFpKuajGgtQ0qd8ceNgcsmE="
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# HTOTConv - Hierarchical-Tree Outline Text Converter
|
2
|
+
|
3
|
+
Convert from a simple hierarchical-tree outline text into ugly xlsx file
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install `htot_conv` via RubyGems. Simply run the following command to install:
|
8
|
+
|
9
|
+
$ gem install htot_conv
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
$ cat outline.txt
|
14
|
+
President
|
15
|
+
.VP Marketing
|
16
|
+
..Manager
|
17
|
+
..Manager
|
18
|
+
.VP Production
|
19
|
+
..Manager
|
20
|
+
..Manager
|
21
|
+
.VP Sales
|
22
|
+
..Manager
|
23
|
+
..Manager
|
24
|
+
$ htot_conv -f simple_text --from-indent=. -t xlsx_type2 outline.txt outline.xlsx
|
25
|
+
$ xdg-open outline.xlsx
|
26
|
+
|
27
|
+
### Types of input
|
28
|
+
|
29
|
+
#### `simple_text`
|
30
|
+
|
31
|
+
* A text file consisting of multiple lines where:
|
32
|
+
* `<line> ::= { <indent> } <key> { <delimiter> <value> }`
|
33
|
+
* `<key>` : a text that does not start with `<indent>` and does not contain `<delimiter>` (if `<delimiter>` specified).
|
34
|
+
* `<value>` : a text that does not contain `<delimiter>`.
|
35
|
+
* `<indent>` : specified by `--from-indent` option
|
36
|
+
* `<delimiter>` : specified by `--from-delimiter` option
|
37
|
+
|
38
|
+
#### `html_list`
|
39
|
+
|
40
|
+
* HTML `<ul><li>` and/or `<ol><li>` [nesting list](https://www.w3.org/wiki/HTML_lists#Nesting_lists).
|
41
|
+
* All text outside of `<li>` elements is ignored.
|
42
|
+
|
43
|
+
### Types of output
|
44
|
+
|
45
|
+
The sample input used in this section are as follows:
|
46
|
+
|
47
|
+
1,1(1),1(2)
|
48
|
+
1.1,1.1(1),1.1(2)
|
49
|
+
1.2,1.2(1),1.2(2)
|
50
|
+
1.2.1,1.2.1(1),1.2.1(2)
|
51
|
+
|
52
|
+
* key header: H1, H2, H3
|
53
|
+
* value header: H(1), H(2)
|
54
|
+
|
55
|
+
#### `xlsx_type0`
|
56
|
+
|
57
|
+
| H1 | Level | H(1) | H(2) |
|
58
|
+
|-------|-------|----------|----------|
|
59
|
+
| 1 | 1 | 1(1) | 1(2) |
|
60
|
+
| 1.1 | 2 | 1.1(1) | 1.1(2) |
|
61
|
+
| 1.2 | 2 | 1.2(1) | 1.2(2) |
|
62
|
+
| 1.2.1 | 3 | 1.2.1(1) | 1.2.1(2) |
|
63
|
+
|
64
|
+
#### `xlsx_type1`
|
65
|
+
|
66
|
+
| H1 | H(1) | H(2) |
|
67
|
+
|-------|----------|----------|
|
68
|
+
| 1 | 1(1) | 1(2) |
|
69
|
+
| 1.1 | 1.1(1) | 1.1(2) |
|
70
|
+
| 1.2 | 1.2(1) | 1.2(2) |
|
71
|
+
| 1.2.1 | 1.2.1(1) | 1.2.1(2) |
|
72
|
+
|
73
|
+
Not implemented (TODO):
|
74
|
+
|
75
|
+
* Fill with different background color for each level.
|
76
|
+
|
77
|
+
#### `xlsx_type2`
|
78
|
+
|
79
|
+
| H1 | H2 | H3 | H(1) | H(2) |
|
80
|
+
|----|-----|-------|----------|----------|
|
81
|
+
| 1 | | | 1(1) | 1(2) |
|
82
|
+
| | 1.1 | | 1.1(1) | 1.1(2) |
|
83
|
+
| | 1.2 | | 1.2(1) | 1.2(2) |
|
84
|
+
| | | 1.2.1 | 1.2.1(1) | 1.2.1(2) |
|
85
|
+
|
86
|
+
Not implemented (TODO):
|
87
|
+
|
88
|
+
* Cell integration over row.
|
89
|
+
|
90
|
+
#### `xlsx_type3`
|
91
|
+
|
92
|
+
Not supported (implemented) as of now.
|
93
|
+
|
94
|
+
| H1 | H(1) | | | H(2) |
|
95
|
+
|----|------|--------|----------|----------|
|
96
|
+
| 1 | 1(1) | | | 1(2) |
|
97
|
+
| | 1.1 | 1.1(1) | | 1.1(2) |
|
98
|
+
| | 1.2 | 1.2(1) | | 1.2(2) |
|
99
|
+
| | | 1.2.1 | 1.2.1(1) | 1.2.1(2) |
|
100
|
+
|
101
|
+
TODO: Github Flavored Markdown does not support for column span.
|
102
|
+
So, this document does not correctly represent type-3 xlsx spread sheet.
|
103
|
+
|
104
|
+
#### `xlsx_type4`
|
105
|
+
|
106
|
+
| H1 | H2 | H3 | H(1) | H(2) |
|
107
|
+
|----|-----|-------|----------|----------|
|
108
|
+
| 1 | 1.1 | | 1.1(1) | 1.1(2) |
|
109
|
+
| | 1.2 | 1.2.1 | 1.2.1(1) | 1.2.1(2) |
|
110
|
+
|
111
|
+
Not implemented (TODO):
|
112
|
+
|
113
|
+
* Cell integration over column.
|
114
|
+
|
115
|
+
#### `xlsx_type5`
|
116
|
+
|
117
|
+
| H1 | H2 | H3 | H(1) | H(2) |
|
118
|
+
|----|-----|-------|----------|----------|
|
119
|
+
| 1 | 1.1 | | 1.1(1) | 1.1(2) |
|
120
|
+
| 1 | 1.2 | 1.2.1 | 1.2.1(1) | 1.2.1(2) |
|
121
|
+
|
122
|
+
Not implemented (TODO):
|
123
|
+
|
124
|
+
* Cell integration over column.
|
125
|
+
* Apply auto filter to the first (header) row.
|
126
|
+
|
127
|
+
## Development
|
128
|
+
|
129
|
+
$ bundle install --path=vendor/bundle --with development test
|
130
|
+
$ bundle exec rake test
|
131
|
+
|
132
|
+
## Contributing
|
133
|
+
|
134
|
+
Bug reports and pull requests are welcome on GitHub at <https://github.com/cat-in-136/htot_conv>.
|
135
|
+
|
136
|
+
|
137
|
+
## License
|
138
|
+
|
139
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
140
|
+
See the `LICENSE.txt` file.
|
141
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "htot_conv"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/exe/htot_conv
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'rinne'
|
6
|
+
require 'htot_conv'
|
7
|
+
|
8
|
+
module HTOTConv
|
9
|
+
module CLI
|
10
|
+
class ScriptOptions
|
11
|
+
def initialize
|
12
|
+
@options = {
|
13
|
+
:from_type => :simple_text,
|
14
|
+
:to_type => :xlsx_type2,
|
15
|
+
}
|
16
|
+
@from_options = {}
|
17
|
+
@to_options = {}
|
18
|
+
end
|
19
|
+
attr_accessor :options, :from_options, :to_options
|
20
|
+
|
21
|
+
def define_options(opts)
|
22
|
+
opts.banner = %q{Hierarchical-Tree Outline Text Converter}
|
23
|
+
opts.define_head %q{Usage: htot_conv [options] [input] [output]}
|
24
|
+
opts.separator %q{}
|
25
|
+
opts.separator %q{Options:}
|
26
|
+
|
27
|
+
from_types = HTOTConv::Parser.types.map { |v| [v, v.to_s.tr("_", "-")] }.flatten
|
28
|
+
to_types = HTOTConv::Generator.types.map { |v| [v, v.to_s.tr("_", "-")] }.flatten
|
29
|
+
|
30
|
+
opts.on("-f", "--from-type=TYPE", from_types, "type of input (default: #{options[:from_type]})") do |v|
|
31
|
+
options[:from_type] = v.to_s.tr("-", "_")
|
32
|
+
end
|
33
|
+
opts.on("-t", "--to-type=TYPE", to_types, "type of output (default: #{options[:to_type]})") do |v|
|
34
|
+
options[:to_type] = v.to_s.tr("-", "_")
|
35
|
+
end
|
36
|
+
opts.on("-l", "--list-type", "list input/output type") do
|
37
|
+
$stdout << "type of input:\n"
|
38
|
+
$stdout << HTOTConv::Parser.types.join(" ") << "\n"
|
39
|
+
$stdout << "\n"
|
40
|
+
$stdout << "type of output:\n"
|
41
|
+
$stdout << HTOTConv::Generator.types.join(" ") << "\n"
|
42
|
+
$stdout << "\n"
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.separator ""
|
47
|
+
opts.on("-h", "-?", "--help", "Show this message") do
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
opts.on("--version", "Show version") do
|
52
|
+
$stdout << "htot_conv #{HTOTConv::VERSION}\n"
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.separator ""
|
57
|
+
opts.separator "I/O Options:"
|
58
|
+
define_sub_options(opts, HTOTConv::Parser, "from") do |key, v|
|
59
|
+
@from_options[key] = v
|
60
|
+
end
|
61
|
+
define_sub_options(opts, HTOTConv::Generator, "to") do |key, v|
|
62
|
+
@to_options[key] = v
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def define_sub_options(opts, klass, prefix) # :yields: key, v
|
68
|
+
klass.types.each do |type|
|
69
|
+
type_klass = klass.const_get(Rinne.camelize(type.to_s))
|
70
|
+
type_klass.option_help.each do |key,v|
|
71
|
+
long_option = "--#{prefix}-#{key.to_s.tr('_','-')}=VAL"
|
72
|
+
cmd_switch = opts.top.list.find { |v| v.kind_of?(OptionParser::Switch) && v.long.include?(long_option) }
|
73
|
+
if cmd_switch
|
74
|
+
cmd_switch.desc << "For #{type}, #{v[:desc]}"
|
75
|
+
else
|
76
|
+
opts.on(long_option, v[:pat], "For #{type}, #{v[:desc]}") do |v|
|
77
|
+
yield key, v
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def optparse(args)
|
86
|
+
script_opts = ScriptOptions.new
|
87
|
+
OptionParser.new do |opts|
|
88
|
+
script_opts.define_options(opts)
|
89
|
+
|
90
|
+
begin
|
91
|
+
opts.parse!(args)
|
92
|
+
rescue OptionParser::ParseError => ex
|
93
|
+
$stderr << ex.message << "\n"
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
script_opts
|
98
|
+
end
|
99
|
+
module_function :optparse
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
script_opts = HTOTConv::CLI.optparse(ARGV)
|
104
|
+
options = script_opts.options
|
105
|
+
from_options = script_opts.from_options
|
106
|
+
to_options = script_opts.to_options
|
107
|
+
|
108
|
+
inio = ((ARGV.length > 0) && (ARGV[0] != "-"))? File.open(ARGV[0], "rb") : $stdin
|
109
|
+
outio = ((ARGV.length > 1) && (ARGV[1] != "-"))? File.open(ARGV[1], "wb") : $stdout
|
110
|
+
|
111
|
+
HTOTConv.convert(inio, options[:from_type], outio, options[:to_type], from_options, to_options)
|
data/htot_conv.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'htot_conv/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "htot_conv"
|
8
|
+
spec.version = HTOTConv::VERSION
|
9
|
+
spec.authors = ["@cat_in_136"]
|
10
|
+
spec.email = ["cat.in.136+github@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Hierarchical-Tree Outline Text Converter}
|
13
|
+
spec.description = %q{Convert from a simple hierarchical-tree outline text into ugly xlsx file}
|
14
|
+
spec.homepage = "https://github.com/cat-in-136/htot_conv"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
#spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_dependency "axlsx", "~> 2.0.1"
|
31
|
+
spec.add_dependency "rinne", "~> 0.0.3"
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
34
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module HTOTConv
|
2
|
+
module Generator
|
3
|
+
class Base
|
4
|
+
def initialize(data, option={})
|
5
|
+
@data = data
|
6
|
+
@option = self.class.option_help.inject({}) { |h, pair| h[pair[0]] = pair[1][:default]; h}.merge(option)
|
7
|
+
raise ArgumentError, "data is invalid" unless data.valid?
|
8
|
+
end
|
9
|
+
def self.option_help
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
|
13
|
+
def output(outputfile)
|
14
|
+
raise NotImplementedError.new("#{self.class.name}.#{__method__} is an abstract method.")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class XlsxBase < Base
|
19
|
+
def output_to_worksheet(ws)
|
20
|
+
raise NotImplementedError.new("#{self.class.name}.#{__method__} is an abstract method.")
|
21
|
+
end
|
22
|
+
|
23
|
+
def output(outputfile)
|
24
|
+
p = Axlsx::Package.new
|
25
|
+
p.workbook do |wb|
|
26
|
+
wb.add_worksheet do |ws|
|
27
|
+
output_to_worksheet(ws)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
p.serialize(outputfile)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'axlsx'
|
2
|
+
|
3
|
+
require 'htot_conv/generator/base'
|
4
|
+
|
5
|
+
module HTOTConv
|
6
|
+
module Generator
|
7
|
+
class XlsxType0 < XlsxBase
|
8
|
+
def output_to_worksheet(ws)
|
9
|
+
max_value_length = @data.max_value_length
|
10
|
+
|
11
|
+
ws.add_row([@data.key_header[0], 'Level'].concat(
|
12
|
+
HTOTConv::Util.pad_array(@data.value_header, max_value_length)),
|
13
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
14
|
+
|
15
|
+
@data.item.each do |item|
|
16
|
+
ws.add_row([item.key, item.level.to_i].concat(
|
17
|
+
HTOTConv::Util.pad_array(item.value, max_value_length)),
|
18
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
require 'axlsx'
|
3
|
+
|
4
|
+
require 'htot_conv/generator/base'
|
5
|
+
|
6
|
+
module HTOTConv
|
7
|
+
module Generator
|
8
|
+
class XlsxType1 < XlsxBase
|
9
|
+
def output_to_worksheet(ws)
|
10
|
+
max_value_length = @data.max_value_length
|
11
|
+
|
12
|
+
ws.add_row([@data.key_header[0]].concat(
|
13
|
+
HTOTConv::Util.pad_array(@data.value_header, max_value_length)),
|
14
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
15
|
+
|
16
|
+
@data.item.each do |item|
|
17
|
+
ws.add_row([item.key].concat(
|
18
|
+
HTOTConv::Util.pad_array(item.value, max_value_length)),
|
19
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'axlsx'
|
2
|
+
|
3
|
+
require 'htot_conv/generator/base'
|
4
|
+
|
5
|
+
module HTOTConv
|
6
|
+
module Generator
|
7
|
+
class XlsxType2 < XlsxBase
|
8
|
+
def output_to_worksheet(ws)
|
9
|
+
max_level = @data.max_level
|
10
|
+
max_value_length = @data.max_value_length
|
11
|
+
|
12
|
+
ws.add_row(((1..max_level).map {|l| @data.key_header[l - 1] || nil }).concat(
|
13
|
+
HTOTConv::Util.pad_array(@data.value_header, max_value_length)),
|
14
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
15
|
+
|
16
|
+
@data.item.each_with_index do |item, item_index|
|
17
|
+
key_cell = Array.new(max_level, nil)
|
18
|
+
key_cell[item.level - 1] = item.key
|
19
|
+
value_cell = HTOTConv::Util.pad_array(item.value, max_value_length)
|
20
|
+
|
21
|
+
ws.add_row(key_cell.concat(value_cell),
|
22
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
23
|
+
|
24
|
+
(1..max_level).each do |level|
|
25
|
+
edges = []
|
26
|
+
edges << :left if (level <= item.level)
|
27
|
+
edges << :right if ((level < item.level) || (level == max_level))
|
28
|
+
edges << :top if ((level >= item.level) || (item_index == 0))
|
29
|
+
edges << :bottom if ((level > item.level) || (item_index == @data.item.length - 1))
|
30
|
+
ws.rows.last.cells[level - 1].style = ws.styles.add_style(
|
31
|
+
:border => { :style => :thin, :color => "00", :edges => edges })
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'axlsx'
|
2
|
+
|
3
|
+
require 'htot_conv/generator/base'
|
4
|
+
|
5
|
+
module HTOTConv
|
6
|
+
module Generator
|
7
|
+
class XlsxType4 < XlsxBase
|
8
|
+
def output_to_worksheet(ws)
|
9
|
+
max_level = @data.max_level
|
10
|
+
max_value_length = @data.max_value_length
|
11
|
+
|
12
|
+
ws.add_row(((1..max_level).map {|l| @data.key_header[l - 1] || nil }).concat(
|
13
|
+
HTOTConv::Util.pad_array(@data.value_header, max_value_length)),
|
14
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
15
|
+
|
16
|
+
@data.to_tree.descendants.each do |node|
|
17
|
+
if node.leaf?
|
18
|
+
item = node.item
|
19
|
+
|
20
|
+
key_cell = Array.new(max_level, nil)
|
21
|
+
key_cell[node.item.level - 1] = item.key
|
22
|
+
node.ancestors do |ancestor|
|
23
|
+
key_cell[ancestor.item.level - 1] = ancestor.item.key if ancestor.item
|
24
|
+
break if ancestor.prev
|
25
|
+
end
|
26
|
+
|
27
|
+
value_cell = HTOTConv::Util.pad_array(item.value, max_value_length)
|
28
|
+
|
29
|
+
ws.add_row(key_cell.concat(value_cell),
|
30
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
31
|
+
|
32
|
+
[node].concat(node.ancestors).each do |ancestor|
|
33
|
+
if (ancestor.parent && ancestor.parent.item && ancestor.parent.item.level)
|
34
|
+
edges = [:left, :right]
|
35
|
+
edges << :top unless ancestor.prev
|
36
|
+
edges << :bottom unless ancestor.next
|
37
|
+
ws.rows.last.cells[ancestor.parent.item.level - 1].style = ws.styles.add_style(
|
38
|
+
:border => { :style => :thin, :color => "00", :edges => edges })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
(item.level..max_level).each do |level|
|
42
|
+
edges = [:top, :bottom]
|
43
|
+
edges << :left if (level == item.level)
|
44
|
+
edges << :right if (level == max_level)
|
45
|
+
ws.rows.last.cells[level - 1].style = ws.styles.add_style(
|
46
|
+
:border => { :style => :thin, :color => "00", :edges => edges })
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'axlsx'
|
2
|
+
|
3
|
+
require 'htot_conv/generator/base'
|
4
|
+
|
5
|
+
module HTOTConv
|
6
|
+
module Generator
|
7
|
+
class XlsxType5 < XlsxBase
|
8
|
+
def output_to_worksheet(ws)
|
9
|
+
max_level = @data.max_level
|
10
|
+
max_value_length = @data.max_value_length
|
11
|
+
|
12
|
+
ws.add_row(((1..max_level).map {|l| @data.key_header[l - 1] || nil }).concat(
|
13
|
+
HTOTConv::Util.pad_array(@data.value_header, max_value_length)),
|
14
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
15
|
+
|
16
|
+
@data.to_tree.descendants.each do |node|
|
17
|
+
if node.leaf?
|
18
|
+
item = node.item
|
19
|
+
|
20
|
+
key_cell = Array.new(max_level, nil)
|
21
|
+
key_cell[node.item.level - 1] = item.key
|
22
|
+
node.ancestors do |ancestor|
|
23
|
+
key_cell[ancestor.item.level - 1] = ancestor.item.key if ancestor.item
|
24
|
+
end
|
25
|
+
|
26
|
+
value_cell = HTOTConv::Util.pad_array(item.value, max_value_length)
|
27
|
+
|
28
|
+
ws.add_row(key_cell.concat(value_cell),
|
29
|
+
:style => Axlsx::STYLE_THIN_BORDER)
|
30
|
+
|
31
|
+
(item.level..max_level).each do |level|
|
32
|
+
edges = [:top, :bottom]
|
33
|
+
edges << :left if (level == item.level)
|
34
|
+
edges << :right if (level == max_level)
|
35
|
+
ws.rows.last.cells[level - 1].style = ws.styles.add_style(
|
36
|
+
:border => { :style => :thin, :color => "00", :edges => edges })
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
ws.auto_filter = "A1:#{ws.rows.last.cells[max_level + max_value_length - 1].r}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'htot_conv/generator/xlsx_type0.rb'
|
2
|
+
require 'htot_conv/generator/xlsx_type1.rb'
|
3
|
+
require 'htot_conv/generator/xlsx_type2.rb'
|
4
|
+
require 'htot_conv/generator/xlsx_type4.rb'
|
5
|
+
require 'htot_conv/generator/xlsx_type5.rb'
|
6
|
+
|
7
|
+
require 'rinne'
|
8
|
+
|
9
|
+
module HTOTConv
|
10
|
+
module Generator
|
11
|
+
def create(type, *args)
|
12
|
+
klass = HTOTConv::Generator.const_get(Rinne.camelize(type.to_s))
|
13
|
+
klass.new(*args)
|
14
|
+
end
|
15
|
+
module_function :create
|
16
|
+
|
17
|
+
def types
|
18
|
+
HTOTConv::Generator.constants.reject { |klass|
|
19
|
+
klass =~ /Base$/
|
20
|
+
}.select { |klass|
|
21
|
+
HTOTConv::Generator.const_get(klass).kind_of?(Class)
|
22
|
+
}.map { |klass|
|
23
|
+
Rinne.to_snake(klass.to_s).to_sym
|
24
|
+
}
|
25
|
+
end
|
26
|
+
module_function :types
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module HTOTConv
|
2
|
+
class Outline
|
3
|
+
def initialize
|
4
|
+
@item = []
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_accessor :key_header
|
8
|
+
attr_accessor :value_header
|
9
|
+
attr_accessor :item
|
10
|
+
|
11
|
+
def add_item(*args)
|
12
|
+
@item << Item.new(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
@key_header.kind_of?(Array) &&
|
17
|
+
@key_header.all? { |v| v.nil? || v.kind_of?(String) } &&
|
18
|
+
@value_header.kind_of?(Array) &&
|
19
|
+
@value_header.all? { |v| v.nil? || v.kind_of?(String) } &&
|
20
|
+
@item.kind_of?(Array) &&
|
21
|
+
@item.all? { |item| item.valid? }
|
22
|
+
end
|
23
|
+
|
24
|
+
def max_level
|
25
|
+
[
|
26
|
+
@key_header.length,
|
27
|
+
*(@item.map { |v| v.level.to_i }),
|
28
|
+
].max
|
29
|
+
end
|
30
|
+
|
31
|
+
def max_value_length
|
32
|
+
[
|
33
|
+
@value_header.length,
|
34
|
+
*(@item.map { |v| (v.value)? v.value.length : 0 }),
|
35
|
+
].max
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(v)
|
39
|
+
(@key_header == v.key_header) &&
|
40
|
+
(@value_header == v.value_header) &&
|
41
|
+
(@item == v.item)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_tree
|
45
|
+
root = Tree.new
|
46
|
+
last_node = root
|
47
|
+
@item.each_with_index do |item,i|
|
48
|
+
parent_node = root
|
49
|
+
if ((item.level > 1) && !(last_node.root?))
|
50
|
+
if item.level > last_node.item.level
|
51
|
+
parent_node = last_node
|
52
|
+
else
|
53
|
+
parent_node = last_node.parent
|
54
|
+
parent_node = parent_node.parent until (parent_node.root? || parent_node.item.level < item.level)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
parent_node << item
|
59
|
+
last_node = parent_node.to_a.last
|
60
|
+
end
|
61
|
+
root
|
62
|
+
end
|
63
|
+
|
64
|
+
Item = Struct.new(:key, :level, :value) do
|
65
|
+
def valid?
|
66
|
+
self.level.kind_of?(Numeric) &&
|
67
|
+
(self.level > 0) &&
|
68
|
+
(self.level.to_i == self.level) &&
|
69
|
+
self.value.kind_of?(Array)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Tree
|
74
|
+
include Enumerable
|
75
|
+
|
76
|
+
def initialize(item=nil, parent=nil)
|
77
|
+
@item = item
|
78
|
+
@parent = parent
|
79
|
+
@children = []
|
80
|
+
end
|
81
|
+
attr_accessor :item
|
82
|
+
attr_reader :parent
|
83
|
+
|
84
|
+
def root?
|
85
|
+
@parent.nil?
|
86
|
+
end
|
87
|
+
|
88
|
+
def leaf?
|
89
|
+
@children.empty?
|
90
|
+
end
|
91
|
+
|
92
|
+
def add(item)
|
93
|
+
child = Tree.new(item, self)
|
94
|
+
@children << child
|
95
|
+
self
|
96
|
+
end
|
97
|
+
alias :<< :add
|
98
|
+
|
99
|
+
def each # :yields: child
|
100
|
+
@children.each do |v|
|
101
|
+
yield v if block_given?
|
102
|
+
end
|
103
|
+
@children.dup
|
104
|
+
end
|
105
|
+
|
106
|
+
def root
|
107
|
+
node = self
|
108
|
+
node = node.parent until node.root?
|
109
|
+
node
|
110
|
+
end
|
111
|
+
|
112
|
+
def next
|
113
|
+
if root?
|
114
|
+
nil
|
115
|
+
else
|
116
|
+
brothers = parent.to_a
|
117
|
+
index = brothers.index(self)
|
118
|
+
(index + 1 < brothers.length)? brothers[index + 1] : nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def prev
|
123
|
+
if root?
|
124
|
+
nil
|
125
|
+
else
|
126
|
+
brothers = parent.to_a
|
127
|
+
index = brothers.index(self)
|
128
|
+
(index - 1 >= 0)? brothers[index - 1] : nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def ancestors # :yields: ancestor
|
133
|
+
ancestors = []
|
134
|
+
node = self.parent
|
135
|
+
until (node.nil? || node.root?)
|
136
|
+
ancestors << node
|
137
|
+
yield node if block_given?
|
138
|
+
node = node.parent
|
139
|
+
end
|
140
|
+
ancestors
|
141
|
+
end
|
142
|
+
|
143
|
+
def descendants # :yields: descendant
|
144
|
+
descendants = []
|
145
|
+
@children.each do |child|
|
146
|
+
descendants << child
|
147
|
+
yield child if block_given?
|
148
|
+
child.descendants do |descendant|
|
149
|
+
descendants << descendant
|
150
|
+
yield descendant if block_given?
|
151
|
+
end
|
152
|
+
end
|
153
|
+
descendants
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module HTOTConv
|
2
|
+
module Parser
|
3
|
+
class Base
|
4
|
+
def initialize(option={})
|
5
|
+
@option = self.class.option_help.inject({}) { |h, pair| h[pair[0]] = pair[1][:default]; h}.merge(option)
|
6
|
+
end
|
7
|
+
attr_accessor :option
|
8
|
+
|
9
|
+
def self.option_help
|
10
|
+
{}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'htot_conv/parser/base'
|
2
|
+
|
3
|
+
module HTOTConv
|
4
|
+
module Parser
|
5
|
+
class HtmlList < Base
|
6
|
+
def parse(input)
|
7
|
+
outline = HTOTConv::Outline.new
|
8
|
+
outline.key_header = []
|
9
|
+
outline.value_header = []
|
10
|
+
|
11
|
+
parser = Nokogiri::HTML::SAX::Parser.new(ListDoc.new(outline))
|
12
|
+
parser.parse(input)
|
13
|
+
|
14
|
+
outline
|
15
|
+
end
|
16
|
+
|
17
|
+
class ListDoc < Nokogiri::XML::SAX::Document
|
18
|
+
def initialize(outline)
|
19
|
+
@outline = outline
|
20
|
+
@breadcrumb = []
|
21
|
+
@li_text = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_element(name, attrs=[])
|
25
|
+
if ((name == "ul") || (name == "ol"))
|
26
|
+
generate_outline_item unless @li_text.nil?
|
27
|
+
@breadcrumb << name
|
28
|
+
elsif name == "li"
|
29
|
+
@li_text = "".dup if @breadcrumb.length > 0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def end_element(name)
|
34
|
+
if ((name == "ul") || (name == "ol"))
|
35
|
+
generate_outline_item unless @li_text.nil?
|
36
|
+
@breadcrumb.pop
|
37
|
+
elsif name == "li"
|
38
|
+
generate_outline_item unless @li_text.nil?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def characters(string)
|
43
|
+
@li_text << string unless @li_text.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def cdata_block(string)
|
47
|
+
@li_text << string unless @li_text.nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def generate_outline_item
|
52
|
+
level = @breadcrumb.length
|
53
|
+
@outline.add_item(@li_text.strip, level, [])
|
54
|
+
@li_text = nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'htot_conv/parser/base'
|
2
|
+
|
3
|
+
module HTOTConv
|
4
|
+
module Parser
|
5
|
+
class SimpleText < Base
|
6
|
+
def self.option_help
|
7
|
+
{
|
8
|
+
:indent => {
|
9
|
+
:default => "\t",
|
10
|
+
:pat => String,
|
11
|
+
:desc => "indent character (default: TAB)",
|
12
|
+
},
|
13
|
+
:delimiter => {
|
14
|
+
:default => nil,
|
15
|
+
:pat => String,
|
16
|
+
:desc => "separator character of additional data"
|
17
|
+
},
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(input)
|
22
|
+
indent_regexp = Regexp.new("^(?<indents>(#{Regexp.escape(option[:indent])})*)")
|
23
|
+
delimiter_regexp = (option[:delimiter].kind_of?(String))? Regexp.new(Regexp.escape(option[:delimiter])) : option[:delimiter]
|
24
|
+
outline = HTOTConv::Outline.new
|
25
|
+
outline.key_header = []
|
26
|
+
outline.value_header = []
|
27
|
+
|
28
|
+
input.each_line do |line|
|
29
|
+
level = 1
|
30
|
+
value = []
|
31
|
+
if (option[:indent] || '').length > 0
|
32
|
+
indents = indent_regexp.match(line)[:indents]
|
33
|
+
level = 1 + indents.length / option[:indent].length
|
34
|
+
line = line.sub(indent_regexp, "")
|
35
|
+
end
|
36
|
+
|
37
|
+
line = line.strip
|
38
|
+
if delimiter_regexp
|
39
|
+
key = line.split(delimiter_regexp)[0]
|
40
|
+
value = line.split(delimiter_regexp)[1..-1] || []
|
41
|
+
else
|
42
|
+
key = line
|
43
|
+
end
|
44
|
+
|
45
|
+
outline.add_item(key, level, value)
|
46
|
+
end
|
47
|
+
|
48
|
+
outline
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'htot_conv/parser/base.rb'
|
2
|
+
require 'htot_conv/parser/simple_text.rb'
|
3
|
+
require 'htot_conv/parser/html_list.rb'
|
4
|
+
|
5
|
+
module HTOTConv
|
6
|
+
module Parser
|
7
|
+
def create(type, *args)
|
8
|
+
klass = HTOTConv::Parser.const_get(Rinne.camelize(type.to_s))
|
9
|
+
klass.new(*args)
|
10
|
+
end
|
11
|
+
module_function :create
|
12
|
+
|
13
|
+
def types
|
14
|
+
HTOTConv::Parser.constants.reject { |klass|
|
15
|
+
klass =~ /Base$/
|
16
|
+
}.select { |klass|
|
17
|
+
HTOTConv::Parser.const_get(klass).kind_of?(Class)
|
18
|
+
}.map { |klass|
|
19
|
+
Rinne.to_snake(klass.to_s).to_sym
|
20
|
+
}
|
21
|
+
end
|
22
|
+
module_function :types
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
module HTOTConv
|
3
|
+
module Util
|
4
|
+
def pad_array(array, length, pad=nil)
|
5
|
+
raise ArgumentError, "array is not an array" unless array.kind_of?(Array)
|
6
|
+
raise ArgumentError, "array length #{array.length} is larger than #{length}" if array.length > length
|
7
|
+
|
8
|
+
array.concat(Array.new(length - array.length, pad))
|
9
|
+
end
|
10
|
+
module_function :pad_array
|
11
|
+
end
|
12
|
+
end
|
data/lib/htot_conv.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'htot_conv/version'
|
2
|
+
|
3
|
+
require 'htot_conv/util'
|
4
|
+
require 'htot_conv/outline'
|
5
|
+
require 'htot_conv/generator'
|
6
|
+
require 'htot_conv/parser'
|
7
|
+
|
8
|
+
module HTOTConv
|
9
|
+
|
10
|
+
def convert(input, input_type, output, output_type, input_option={}, output_option={})
|
11
|
+
parser = HTOTConv::Parser.create(input_type, input_option)
|
12
|
+
outline = parser.parse(input)
|
13
|
+
generator = HTOTConv::Generator.create(output_type, outline, output_option)
|
14
|
+
generator.output(output)
|
15
|
+
end
|
16
|
+
module_function :convert
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: htot_conv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "@cat_in_136"
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: axlsx
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rinne
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.12'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.12'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.0'
|
83
|
+
description: Convert from a simple hierarchical-tree outline text into ugly xlsx file
|
84
|
+
email:
|
85
|
+
- cat.in.136+github@gmail.com
|
86
|
+
executables:
|
87
|
+
- htot_conv
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".travis.yml"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/console
|
98
|
+
- bin/setup
|
99
|
+
- exe/htot_conv
|
100
|
+
- htot_conv.gemspec
|
101
|
+
- lib/htot_conv.rb
|
102
|
+
- lib/htot_conv/generator.rb
|
103
|
+
- lib/htot_conv/generator/base.rb
|
104
|
+
- lib/htot_conv/generator/xlsx_type0.rb
|
105
|
+
- lib/htot_conv/generator/xlsx_type1.rb
|
106
|
+
- lib/htot_conv/generator/xlsx_type2.rb
|
107
|
+
- lib/htot_conv/generator/xlsx_type4.rb
|
108
|
+
- lib/htot_conv/generator/xlsx_type5.rb
|
109
|
+
- lib/htot_conv/outline.rb
|
110
|
+
- lib/htot_conv/parser.rb
|
111
|
+
- lib/htot_conv/parser/base.rb
|
112
|
+
- lib/htot_conv/parser/html_list.rb
|
113
|
+
- lib/htot_conv/parser/simple_text.rb
|
114
|
+
- lib/htot_conv/util.rb
|
115
|
+
- lib/htot_conv/version.rb
|
116
|
+
homepage: https://github.com/cat-in-136/htot_conv
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.5.2.1
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Hierarchical-Tree Outline Text Converter
|
140
|
+
test_files: []
|