metanorma-cli 1.1.6 → 1.1.7

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.
@@ -0,0 +1,56 @@
1
+ module Metanorma
2
+ module Cli
3
+ class Compiler
4
+ def initialize(file, options)
5
+ @file = file
6
+ @options = options
7
+ @extract = (options.delete(:extract) || "").split(",")
8
+ @extensions = (options.delete(:extensions) || "").split(",")
9
+ end
10
+
11
+ def compile
12
+ compile_file
13
+ end
14
+
15
+ def self.compile(file, options)
16
+ new(file, options).compile
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :file, :options, :extract, :extensions
22
+
23
+ def compile_file
24
+ Compile.new.compile( file, serialize_options)
25
+ end
26
+
27
+ def serialize_options
28
+ serialize(options.merge(customize_options))
29
+ end
30
+
31
+ def customize_options
32
+ extract_option.merge(extension_option)
33
+ end
34
+
35
+ def extract_option
36
+ Hash.new.tap do |hash|
37
+ hash[:extract] = extract[0]
38
+ hash[:extract_type] =
39
+ extract.size > 0 ? extract[0..-1].map(&:to_sym) : []
40
+ end
41
+ end
42
+
43
+ def extension_option
44
+ !extensions.empty? ? { extension_keys: extensions.map(&:to_sym) } : {}
45
+ end
46
+
47
+ def serialize(options)
48
+ Hash.new.tap do |hash|
49
+ options.each do |key, value|
50
+ hash[key.to_sym] = value unless value.nil?
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,124 @@
1
+ require "pathname"
2
+ require "fileutils"
3
+ require "metanorma/cli/ui"
4
+
5
+ module Metanorma
6
+ module Cli
7
+ class Generator
8
+ def initialize(name, type:, doctype:, **options)
9
+ @name = name
10
+ @type = type
11
+ @doctype = doctype
12
+ @options = options
13
+ end
14
+
15
+ def run
16
+ if name && document_path.exist?
17
+ return unless overwrite?(document_path)
18
+ document_path.rmtree
19
+ end
20
+
21
+ create_metanorma_document
22
+ end
23
+
24
+ # Generator.run
25
+ #
26
+ # This interface find / downloads the specified template
27
+ # and then run the generator to create a new metanorma
28
+ # document.
29
+ #
30
+ # By default it usages the default templates but user can
31
+ # also provide a remote git teplate repo using --template
32
+ # ooption, and in that case it will use that template.
33
+ #
34
+ def self.run(name, type:, doctype:, **options)
35
+ new(name, options.merge(type: type, doctype: doctype)).run
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :name, :type, :doctype, :options
41
+
42
+ def document_path
43
+ @document_path ||= Pathname.pwd.join(name)
44
+ end
45
+
46
+ def create_metanorma_document
47
+ type_template = type_specific_template
48
+
49
+ unless type_template.empty?
50
+ templates = base_templates.merge(type_template)
51
+ templates.each { |source, dest| create_file(source, dest) }
52
+ else
53
+ UI.say(
54
+ "Sorry, could not generate the document!\n" \
55
+ "Template's are missing, please provide valid template URL"
56
+ )
57
+ end
58
+ end
59
+
60
+ def find_template(type)
61
+ Cli::GitTemplate.find_or_download_by(type)
62
+ end
63
+
64
+ def overwrite?(document_path)
65
+ options[:overwrite] == true || ask_to_confirm(document_path) === "yes"
66
+ end
67
+
68
+ def base_templates
69
+ base_template_root = Cli.templates_path.join("base")
70
+ build_template_hash(dir_files(base_template_root), base_template_root)
71
+ end
72
+
73
+ def type_specific_template
74
+ type_template_path = custom_template || find_template(type)
75
+ doctype_templates = dir_files(type_template_path, doctype)
76
+ build_template_hash(doctype_templates, type_template_path, doctype)
77
+ end
78
+
79
+ def custom_template
80
+ if options[:template]
81
+ Cli::GitTemplate.download(type, repo: options[:template])
82
+ end
83
+ end
84
+
85
+ def build_template_hash(elements, source_root, type = nil)
86
+ type_template_path = [source_root, type].join("/")
87
+
88
+ Hash.new.tap do |hash|
89
+ elements.each do |element|
90
+ hash[element] = element.gsub(type_template_path, "")
91
+ end
92
+ end
93
+ end
94
+
95
+ def create_file(source, destination)
96
+ target_path = [document_path, destination].join("/")
97
+ target_path = Pathname.new(target_path)
98
+
99
+ unless target_path.dirname.exist?
100
+ FileUtils.mkdir_p(target_path.dirname)
101
+ end
102
+
103
+ file_creation_message(name, destination)
104
+ FileUtils.copy_entry(source, target_path)
105
+ end
106
+
107
+ def dir_files(*arguments)
108
+ paths = [*arguments, "**", "**"].join("/")
109
+ Pathname.glob(paths).reject(&:directory?).map(&:to_s)
110
+ end
111
+
112
+ def ask_to_confirm(document)
113
+ UI.ask(
114
+ "You've an existing document with the #{document.to_s}\n" \
115
+ "Still want to continue, and overwrite the existing one? (yes/no):",
116
+ ).downcase
117
+ end
118
+
119
+ def file_creation_message(document, destination)
120
+ UI.say("Creating #{[document, destination].join("/").gsub("//", "/")}")
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,104 @@
1
+ require "git"
2
+
3
+ module Metanorma
4
+ module Cli
5
+ class GitTemplate
6
+ def initialize(name, options = {})
7
+ @name = name
8
+ @options = options
9
+ end
10
+
11
+ def remove!
12
+ remove_template
13
+ return true
14
+ end
15
+
16
+ def download
17
+ remove!
18
+ clone_git_template(options[:repo])
19
+
20
+ rescue Git::GitExecuteError
21
+ UI.say("Invalid template reoository!")
22
+ return nil
23
+ end
24
+
25
+ def find_or_download
26
+ find_template || download_template
27
+ end
28
+
29
+ # Find or Download
30
+ #
31
+ # This interface expects a name / type, and then it will
32
+ # find that template, or if non exist then it will download
33
+ # and return the downloaded path.
34
+ #
35
+ def self.find_or_download_by(name)
36
+ new(name).find_or_download
37
+ end
38
+
39
+ # Download a template
40
+ #
41
+ # This interface expects a name, and remote repository link
42
+ # for a template, then it will download that template and it
43
+ # will return the downloaded path.
44
+ #
45
+ # By default, downloaded tempaltes will be stored in a sub
46
+ # directoy inside metanorma's tempaltes directory, but if
47
+ # you don't want then you can set the `remote` to false.
48
+ #
49
+ def self.download(name, repo:, remote: true)
50
+ new(name, repo: repo, remote: remote).download
51
+ end
52
+
53
+ private
54
+
55
+ attr_reader :name, :options
56
+
57
+ def find_template
58
+ if template_path.exist?
59
+ template_path
60
+ end
61
+ end
62
+
63
+ def download_template
64
+ template_repo = git_repos[name.to_sym]
65
+
66
+ if template_repo
67
+ clone_git_template(template_repo)
68
+ end
69
+ end
70
+
71
+ def remove_template
72
+ if template_path.exist?
73
+ template_path.rmtree
74
+ end
75
+ end
76
+
77
+ def clone_git_template(repo)
78
+ clone = Git.clone(repo, name, path: templates_path)
79
+ template_path unless clone.nil?
80
+ end
81
+
82
+ def git_repos
83
+ @git_repos ||= {
84
+ csd: "https://github.com/metanorma/mn-templates-csd",
85
+ ogc: "https://github.com/metanorma/mn-templates-ogc",
86
+ iso: "https://github.com/metanorma/mn-templates-iso",
87
+ }
88
+ end
89
+
90
+ def templates_path
91
+ @templates_path ||= build_templates_path
92
+ end
93
+
94
+ def build_templates_path
95
+ sub_directory = options[:remote] == true ? "git" : nil
96
+ Metanorma::Cli.templates_path.join(sub_directory.to_s)
97
+ end
98
+
99
+ def template_path
100
+ @template_path ||= templates_path.join(name.to_s.downcase)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,20 @@
1
+ require "thor"
2
+
3
+ module Metanorma
4
+ module Cli
5
+ class UI < Thor
6
+ def self.ask(message)
7
+ new.ask(message)
8
+ end
9
+
10
+ def self.say(message)
11
+ new.say(message)
12
+ end
13
+
14
+ def self.run(command)
15
+ require "open3"
16
+ Open3.capture3(command)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module Cli
3
- VERSION = "1.1.6"
3
+ VERSION = "1.1.7"
4
4
  end
5
5
  end
@@ -30,10 +30,10 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "byebug", "~> 10.0"
31
31
  spec.add_development_dependency "rspec-command", "~> 1.0.3"
32
32
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
33
- spec.add_development_dependency 'rspec-core', "~> 3.4"
33
+ spec.add_development_dependency "rspec-core", "~> 3.4"
34
34
 
35
-
36
- spec.add_runtime_dependency 'metanorma-iso', "~> 1.1.0"
35
+ spec.add_runtime_dependency "thor", "~> 0.20.3"
36
+ spec.add_runtime_dependency "metanorma-iso", "~> 1.1.0"
37
37
  spec.add_runtime_dependency 'metanorma-ietf', "~> 1.0.1"
38
38
  spec.add_runtime_dependency 'metanorma-gb', "~> 1.1.0"
39
39
  spec.add_runtime_dependency 'metanorma-csd', "~> 1.1.0"
@@ -49,4 +49,5 @@ Gem::Specification.new do |spec|
49
49
  spec.add_runtime_dependency 'isodoc', "~> 0.9.0"
50
50
  spec.add_runtime_dependency 'metanorma', "~> 0.3.9"
51
51
  spec.add_runtime_dependency 'nokogiri', ">= 1"
52
+ spec.add_runtime_dependency "git", "~> 1.5"
52
53
  end
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "metanorma-cli"
4
+ gem "relaton-cli"
@@ -0,0 +1,126 @@
1
+ #!make
2
+ SHELL := /bin/bash
3
+
4
+ FORMAT_MARKER := mn-output-
5
+ FORMATS := $(shell grep "$(FORMAT_MARKER)" *.adoc | cut -f 2 -d ' ' | tr ',' '\n' | sort | uniq | tr '\n' ' ')
6
+
7
+ SRC := $(filter-out README.adoc, $(wildcard *.adoc))
8
+ XML := $(patsubst %.adoc,%.xml,$(SRC))
9
+ HTML := $(patsubst %.adoc,%.html,$(SRC))
10
+ DOC := $(patsubst %.adoc,%.doc,$(SRC))
11
+ PDF := $(patsubst %.adoc,%.pdf,$(SRC))
12
+ WSD := $(wildcard models/*.wsd)
13
+ XMI := $(patsubst models/%,xmi/%,$(patsubst %.wsd,%.xmi,$(WSD)))
14
+ PNG := $(patsubst models/%,images/%,$(patsubst %.wsd,%.png,$(WSD)))
15
+
16
+ COMPILE_CMD_LOCAL := bundle exec metanorma $$FILENAME
17
+ COMPILE_CMD_DOCKER := docker run -v "$$(pwd)":/metanorma/ ribose/metanorma "metanorma $$FILENAME"
18
+
19
+ ifdef METANORMA_DOCKER
20
+ COMPILE_CMD := echo "Compiling via docker..."; $(COMPILE_CMD_DOCKER)
21
+ else
22
+ COMPILE_CMD := echo "Compiling locally..."; $(COMPILE_CMD_LOCAL)
23
+ endif
24
+
25
+ _OUT_FILES := $(foreach FORMAT,$(FORMATS),$(shell echo $(FORMAT) | tr '[:lower:]' '[:upper:]'))
26
+ OUT_FILES := $(foreach F,$(_OUT_FILES),$($F))
27
+
28
+ all: images $(OUT_FILES)
29
+
30
+ %.xml %.html %.doc %.pdf: %.adoc | bundle
31
+ FILENAME=$^; \
32
+ ${COMPILE_CMD}
33
+
34
+ images: $(PNG)
35
+
36
+ images/%.png: models/%.wsd
37
+ plantuml -tpng -o ../images/ $<
38
+
39
+ xmi: $(XMI)
40
+
41
+ xmi/%.xmi: models/%.wsd
42
+ plantuml -xmi:star -o ../xmi/ $<
43
+
44
+ define FORMAT_TASKS
45
+ OUT_FILES-$(FORMAT) := $($(shell echo $(FORMAT) | tr '[:lower:]' '[:upper:]'))
46
+
47
+ open-$(FORMAT):
48
+ open $$(OUT_FILES-$(FORMAT))
49
+
50
+ clean-$(FORMAT):
51
+ rm -f $$(OUT_FILES-$(FORMAT))
52
+
53
+ $(FORMAT): clean-$(FORMAT) $$(OUT_FILES-$(FORMAT))
54
+
55
+ .PHONY: clean-$(FORMAT)
56
+
57
+ endef
58
+
59
+ $(foreach FORMAT,$(FORMATS),$(eval $(FORMAT_TASKS)))
60
+
61
+ open: open-html
62
+
63
+ clean:
64
+ rm -f $(OUT_FILES)
65
+
66
+ bundle:
67
+ if [ "x" == "${METANORMA_DOCKER}x" ]; then bundle; fi
68
+
69
+ .PHONY: bundle all open clean
70
+
71
+ #
72
+ # Watch-related jobs
73
+ #
74
+
75
+ .PHONY: watch serve watch-serve
76
+
77
+ NODE_BINS := onchange live-serve run-p
78
+ NODE_BIN_DIR := node_modules/.bin
79
+ NODE_PACKAGE_PATHS := $(foreach PACKAGE_NAME,$(NODE_BINS),$(NODE_BIN_DIR)/$(PACKAGE_NAME))
80
+
81
+ $(NODE_PACKAGE_PATHS): package.json
82
+ npm i
83
+
84
+ watch: $(NODE_BIN_DIR)/onchange
85
+ make all
86
+ $< $(ALL_SRC) -- make all
87
+
88
+ define WATCH_TASKS
89
+ watch-$(FORMAT): $(NODE_BIN_DIR)/onchange
90
+ make $(FORMAT)
91
+ $$< $$(SRC_$(FORMAT)) -- make $(FORMAT)
92
+
93
+ .PHONY: watch-$(FORMAT)
94
+ endef
95
+
96
+ $(foreach FORMAT,$(FORMATS),$(eval $(WATCH_TASKS)))
97
+
98
+ serve: $(NODE_BIN_DIR)/live-server revealjs-css reveal.js images
99
+ export PORT=$${PORT:-8123} ; \
100
+ port=$${PORT} ; \
101
+ for html in $(HTML); do \
102
+ $< --entry-file=$$html --port=$${port} --ignore="*.html,*.xml,Makefile,Gemfile.*,package.*.json" --wait=1000 & \
103
+ port=$$(( port++ )) ;\
104
+ done
105
+
106
+ watch-serve: $(NODE_BIN_DIR)/run-p
107
+ $< watch serve
108
+
109
+ #
110
+ # Deploy jobs
111
+ #
112
+
113
+ publish:
114
+ mkdir -p published && \
115
+ cp -a $(basename $(SRC)).* published/ && \
116
+ cp $(firstword $(HTML)) published/index.html; \
117
+ if [ -d "images" ]; then cp -a images published; fi
118
+
119
+ deploy_key:
120
+ openssl aes-256-cbc -K $(encrypted_$(ENCRYPTION_LABEL)_key) \
121
+ -iv $(encrypted_$(ENCRYPTION_LABEL)_iv) -in $@.enc -out $@ -d && \
122
+ chmod 600 $@
123
+
124
+ deploy: deploy_key
125
+ export COMMIT_AUTHOR_EMAIL=$(COMMIT_AUTHOR_EMAIL); \
126
+ ./deploy.sh