epuber 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +46 -0
- data/bin/epuber +10 -0
- data/epuber.gemspec +51 -0
- data/lib/epuber.rb +14 -0
- data/lib/epuber/book.rb +267 -0
- data/lib/epuber/book/contributor.rb +90 -0
- data/lib/epuber/book/file_request.rb +68 -0
- data/lib/epuber/book/target.rb +284 -0
- data/lib/epuber/book/toc_item.rb +130 -0
- data/lib/epuber/checker.rb +19 -0
- data/lib/epuber/checker/text_checker.rb +129 -0
- data/lib/epuber/checker_transformer_base.rb +71 -0
- data/lib/epuber/command.rb +65 -0
- data/lib/epuber/command/compile.rb +142 -0
- data/lib/epuber/command/init.rb +145 -0
- data/lib/epuber/command/server.rb +59 -0
- data/lib/epuber/compiler.rb +255 -0
- data/lib/epuber/compiler/compilation_context.rb +86 -0
- data/lib/epuber/compiler/file_finders/abstract.rb +270 -0
- data/lib/epuber/compiler/file_finders/imaginary.rb +167 -0
- data/lib/epuber/compiler/file_finders/normal.rb +22 -0
- data/lib/epuber/compiler/file_resolver.rb +316 -0
- data/lib/epuber/compiler/file_types/abstract_file.rb +119 -0
- data/lib/epuber/compiler/file_types/bade_file.rb +39 -0
- data/lib/epuber/compiler/file_types/container_xml_file.rb +26 -0
- data/lib/epuber/compiler/file_types/generated_file.rb +29 -0
- data/lib/epuber/compiler/file_types/ibooks_display_options_file.rb +31 -0
- data/lib/epuber/compiler/file_types/image_file.rb +42 -0
- data/lib/epuber/compiler/file_types/mime_type_file.rb +20 -0
- data/lib/epuber/compiler/file_types/nav_file.rb +42 -0
- data/lib/epuber/compiler/file_types/opf_file.rb +27 -0
- data/lib/epuber/compiler/file_types/source_file.rb +52 -0
- data/lib/epuber/compiler/file_types/static_file.rb +18 -0
- data/lib/epuber/compiler/file_types/stylus_file.rb +20 -0
- data/lib/epuber/compiler/file_types/xhtml_file.rb +102 -0
- data/lib/epuber/compiler/generator.rb +67 -0
- data/lib/epuber/compiler/meta_inf_generator.rb +41 -0
- data/lib/epuber/compiler/nav_generator.rb +201 -0
- data/lib/epuber/compiler/opf_generator.rb +284 -0
- data/lib/epuber/compiler/xhtml_processor.rb +254 -0
- data/lib/epuber/config.rb +133 -0
- data/lib/epuber/dsl/attribute.rb +248 -0
- data/lib/epuber/dsl/attribute_support.rb +130 -0
- data/lib/epuber/dsl/object.rb +145 -0
- data/lib/epuber/dsl/tree_object.rb +101 -0
- data/lib/epuber/helper.rb +19 -0
- data/lib/epuber/lockfile.rb +55 -0
- data/lib/epuber/plugin.rb +108 -0
- data/lib/epuber/ruby_extensions/match_data.rb +40 -0
- data/lib/epuber/ruby_extensions/thread.rb +13 -0
- data/lib/epuber/server.rb +614 -0
- data/lib/epuber/server/auto_refresh/auto_refresh.coffee +97 -0
- data/lib/epuber/server/auto_refresh/connector.coffee +125 -0
- data/lib/epuber/server/auto_refresh/protocol.coffee +41 -0
- data/lib/epuber/server/auto_refresh/reloader.coffee +261 -0
- data/lib/epuber/server/base.styl +3 -0
- data/lib/epuber/server/basic.styl +211 -0
- data/lib/epuber/server/book_content.styl +39 -0
- data/lib/epuber/server/default_cover.png +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Bold.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-BoldItalic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Italic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Regular.ttf +0 -0
- data/lib/epuber/server/handlers.rb +67 -0
- data/lib/epuber/server/keyboard_control.coffee +6 -0
- data/lib/epuber/server/pages/book.bade +75 -0
- data/lib/epuber/server/pages/common.bade +59 -0
- data/lib/epuber/server/pages/files.bade +17 -0
- data/lib/epuber/server/pages/toc.bade +29 -0
- data/lib/epuber/server/support.coffee +10 -0
- data/lib/epuber/templates/template.bookspec +143 -0
- data/lib/epuber/third_party/bower.rb +22 -0
- data/lib/epuber/third_party/bower/bower.json +10 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/bower.json +10 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.d.ts +33 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.js +173 -0
- data/lib/epuber/third_party/bower/bower_components/cookies-js/dist/cookies.min.js +6 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/MIT-LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/bower.json +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.js +9210 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.min.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/dist/jquery.min.map +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax.js +786 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/jsonp.js +89 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/load.js +75 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/parseJSON.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/parseXML.js +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/script.js +64 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/var/nonce.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/var/rquery.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/ajax/xhr.js +136 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes.js +11 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/attr.js +141 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/classes.js +158 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/prop.js +94 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/support.js +35 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/attributes/val.js +161 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/callbacks.js +205 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core.js +502 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/access.js +60 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/init.js +123 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/parseHTML.js +39 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/ready.js +97 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css.js +450 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/addGetHookIf.js +22 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/curCSS.js +57 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/defaultDisplay.js +70 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/support.js +96 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/swap.js +28 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/cssExpand.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/getStyles.js +12 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/isHidden.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/rmargin.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data.js +178 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/Data.js +181 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/accepts.js +20 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/var/data_priv.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/data/var/data_user.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/deferred.js +149 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/deprecated.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/dimensions.js +50 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects.js +648 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects/Tween.js +114 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/effects/animatedSelector.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event.js +868 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/ajax.js +13 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/alias.js +39 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/event/support.js +9 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/exports/amd.js +24 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/exports/global.js +32 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/intro.js +44 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/jquery.js +37 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation.js +580 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/support.js +32 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/offset.js +207 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/outro.js +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/queue.js +142 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/queue/delay.js +22 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector-native.js +172 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector-sizzle.js +14 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/selector.js +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/serialize.js +111 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.js +2067 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing.js +199 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing/findFilter.js +100 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/arr.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/class2type.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/concat.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/hasOwn.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/indexOf.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/pnum.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/push.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/rnotwhite.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/slice.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/strundefined.js +3 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/support.js +4 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/var/toString.js +5 -0
- data/lib/epuber/third_party/bower/bower_components/jquery/src/wrap.js +79 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/MIT-LICENSE +20 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/Makefile +4 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/README.markdown +212 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/bower.json +27 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/keymaster.js +296 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/package.json +11 -0
- data/lib/epuber/third_party/bower/bower_components/keymaster/test.html +93 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/README.md +21 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/bower.json +18 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/jquery.spin.js +80 -0
- data/lib/epuber/third_party/bower/bower_components/spin.js/spin.js +337 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/LICENSE.txt +21 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/README.md +534 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/bower.json +16 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/contributing.md +19 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/IPv6.js +188 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/SecondLevelDomains.js +241 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.fragmentQuery.js +104 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.fragmentURI.js +97 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.js +2115 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URI.min.js +86 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/URITemplate.js +499 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/jquery.URI.js +235 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/jquery.URI.min.js +7 -0
- data/lib/epuber/third_party/bower/bower_components/uri.js/src/punycode.js +508 -0
- data/lib/epuber/transformer.rb +19 -0
- data/lib/epuber/transformer/text_transformer.rb +60 -0
- data/lib/epuber/user_interface.rb +186 -0
- data/lib/epuber/vendor/globals_context.rb +26 -0
- data/lib/epuber/vendor/hash_binding.rb +26 -0
- data/lib/epuber/vendor/nokogiri_extensions.rb +30 -0
- data/lib/epuber/vendor/ruby_templater.rb +71 -0
- data/lib/epuber/vendor/size.rb +20 -0
- data/lib/epuber/vendor/version.rb +83 -0
- data/lib/epuber/version.rb +4 -0
- metadata +556 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'checker_transformer_base'
|
4
|
+
|
5
|
+
|
6
|
+
module Epuber
|
7
|
+
class Checker < CheckerTransformerBase
|
8
|
+
require_relative 'checker/text_checker'
|
9
|
+
|
10
|
+
# @return [Hash<Symbol, Class>]
|
11
|
+
#
|
12
|
+
def self.map_source_type__class
|
13
|
+
{
|
14
|
+
:result_text_xhtml_string => TextChecker,
|
15
|
+
:source_text_file => TextChecker,
|
16
|
+
}.merge(super)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string/access'
|
4
|
+
|
5
|
+
require_relative '../ruby_extensions/match_data'
|
6
|
+
require_relative '../checker'
|
7
|
+
|
8
|
+
|
9
|
+
module Epuber
|
10
|
+
class Checker
|
11
|
+
class TextChecker < Checker
|
12
|
+
class MatchProblem
|
13
|
+
# @param message [String]
|
14
|
+
# @param file_path [String]
|
15
|
+
# @param match [MatchData]
|
16
|
+
#
|
17
|
+
def initialize(match, message, file_path)
|
18
|
+
@match = match
|
19
|
+
@message = message
|
20
|
+
@file_path = file_path
|
21
|
+
end
|
22
|
+
|
23
|
+
# Formats caret symbol with space indent
|
24
|
+
#
|
25
|
+
# @param [Fixnum] indent
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
#
|
29
|
+
def caret_symbol(indent)
|
30
|
+
' ' * indent + '^'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Formats caret symbols for indent and length
|
34
|
+
#
|
35
|
+
# @param [Fixnum] length
|
36
|
+
# @param [Fixnum] indent
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
#
|
40
|
+
def caret_symbols(indent, length)
|
41
|
+
start_sign = caret_symbol(indent)
|
42
|
+
end_sign = if length > 1
|
43
|
+
caret_symbol(length-2)
|
44
|
+
else
|
45
|
+
''
|
46
|
+
end
|
47
|
+
|
48
|
+
"#{start_sign}#{end_sign}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def formatted_match_line
|
52
|
+
match_line = @match.matched_string
|
53
|
+
pre_line = @match.pre_match_lines.last || ''
|
54
|
+
|
55
|
+
pre = match_pre_line = pre_line
|
56
|
+
if remove_tabs(match_pre_line).length > 100
|
57
|
+
pre = "#{match_pre_line.first(20)}...#{match_pre_line.last(30)}"
|
58
|
+
end
|
59
|
+
|
60
|
+
pre = remove_tabs(pre)
|
61
|
+
|
62
|
+
post_line = @match.post_match_lines.first || ''
|
63
|
+
|
64
|
+
post = if post_line.length > 50
|
65
|
+
"#{post_line.first(50)}..."
|
66
|
+
else
|
67
|
+
post_line
|
68
|
+
end
|
69
|
+
|
70
|
+
[pre, match_line, post]
|
71
|
+
end
|
72
|
+
|
73
|
+
def remove_tabs(text)
|
74
|
+
text.gsub("\t", ' ' * 4)
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s
|
78
|
+
pre_original = @match.pre_match_lines.last || ''
|
79
|
+
pre, match_text, post = formatted_match_line
|
80
|
+
|
81
|
+
pointers = caret_symbols(pre.length, match_text.length)
|
82
|
+
|
83
|
+
%{#{@file_path}:#{@match.line_number} column: #{pre_original.length} --- #{@message}
|
84
|
+
#{pre + match_text.ansi.red + post}
|
85
|
+
#{pointers}}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String]
|
90
|
+
#
|
91
|
+
attr_accessor :text
|
92
|
+
|
93
|
+
# @return [String]
|
94
|
+
#
|
95
|
+
attr_accessor :file_path
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
# @param file_path [String]
|
100
|
+
# @param text [String]
|
101
|
+
# @param [CompilationContext] compilation_context
|
102
|
+
#
|
103
|
+
# @return nil
|
104
|
+
#
|
105
|
+
def call(file_path, text, compilation_context)
|
106
|
+
@file_path = file_path
|
107
|
+
@text = text
|
108
|
+
|
109
|
+
@block.call(self, text, compilation_context)
|
110
|
+
|
111
|
+
@text = nil
|
112
|
+
@file_path = nil
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param regexp [Regexp]
|
116
|
+
# @param [String] message message to display, when the regexp found something
|
117
|
+
#
|
118
|
+
def should_not_contain(regexp, message)
|
119
|
+
# find all matches
|
120
|
+
# taken from http://stackoverflow.com/questions/6804557/how-do-i-get-the-match-data-for-all-occurrences-of-a-ruby-regular-expression-in
|
121
|
+
matches = text.to_enum(:scan, regexp).map { Regexp.last_match }
|
122
|
+
matches.each do |match|
|
123
|
+
# @type match [MatchData]
|
124
|
+
UI.print_processing_problem MatchProblem.new(match, message, Config.instance.pretty_path_from_project(file_path))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
module Epuber
|
3
|
+
class CheckerTransformerBase
|
4
|
+
|
5
|
+
# Type of source value for this checker, valid values are:
|
6
|
+
# :result_text_xhtml_string just before writing result xhtml to build folder
|
7
|
+
#
|
8
|
+
# @return [Symbol]
|
9
|
+
#
|
10
|
+
attr_reader :source_type
|
11
|
+
|
12
|
+
# List of options/flags passed in from plugin instance
|
13
|
+
#
|
14
|
+
# @return [Array<Symbol>]
|
15
|
+
#
|
16
|
+
attr_reader :options
|
17
|
+
|
18
|
+
# @return [Proc]
|
19
|
+
#
|
20
|
+
attr_reader :block
|
21
|
+
|
22
|
+
|
23
|
+
# @param [Symbol] type type of checker, see #type
|
24
|
+
# @param [Array<Symbol>] options list of other arguments, usually flags
|
25
|
+
#
|
26
|
+
def initialize(type, *options, &block)
|
27
|
+
@source_type = type
|
28
|
+
@block = block
|
29
|
+
|
30
|
+
valid_options_inst = valid_options
|
31
|
+
options.each do |opt|
|
32
|
+
raise "Unknown option #{opt.inspect}" unless valid_options_inst.include?(opt)
|
33
|
+
end
|
34
|
+
@options = options
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [Array<Symbol>]
|
38
|
+
#
|
39
|
+
def valid_options
|
40
|
+
[:run_only_before_release]
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
def call(*args)
|
46
|
+
raise NotImplementedError, 'You should override this method'
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
# ------------------------------------------------------------------ #
|
52
|
+
# @group Registration
|
53
|
+
|
54
|
+
# @return [Hash<Symbol, Class>]
|
55
|
+
#
|
56
|
+
def self.map_source_type__class
|
57
|
+
{}
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# @param type [Symbol]
|
62
|
+
#
|
63
|
+
# @return [Class]
|
64
|
+
#
|
65
|
+
def self.class_for_source_type(type)
|
66
|
+
checker_class = self.map_source_type__class[type]
|
67
|
+
raise "#{self} class not found for type: #{type.inspect}" if checker_class.nil?
|
68
|
+
checker_class
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'claide'
|
4
|
+
|
5
|
+
module Epuber
|
6
|
+
class PlainInformative < StandardError
|
7
|
+
include CLAide::InformativeError
|
8
|
+
|
9
|
+
def message
|
10
|
+
"[!] #{super}".ansi.red
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Command < CLAide::Command
|
15
|
+
require_relative 'command/compile'
|
16
|
+
require_relative 'command/init'
|
17
|
+
require_relative 'command/server'
|
18
|
+
|
19
|
+
self.abstract_command = true
|
20
|
+
self.command = 'epuber'
|
21
|
+
self.version = VERSION
|
22
|
+
self.description = 'Epuber, easy creating and maintaining e-book.'
|
23
|
+
self.plugin_prefixes = plugin_prefixes + %w(epuber)
|
24
|
+
|
25
|
+
def self.run(argv = [])
|
26
|
+
begin
|
27
|
+
UI.current_command = self
|
28
|
+
super
|
29
|
+
UI.current_command = nil
|
30
|
+
|
31
|
+
rescue => e
|
32
|
+
UI.error!(e)
|
33
|
+
|
34
|
+
UI.current_command = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate!
|
39
|
+
super
|
40
|
+
UI.current_command = self
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
UI.current_command = self
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# @return [Epuber::Book::Book]
|
50
|
+
#
|
51
|
+
def book
|
52
|
+
Config.instance.bookspec
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [void]
|
56
|
+
#
|
57
|
+
# @raise PlainInformative if no .bookspec file don't exists or there are too many
|
58
|
+
#
|
59
|
+
def verify_one_bookspec_exists!
|
60
|
+
bookspec_files = Config.instance.find_all_bookspecs
|
61
|
+
raise PlainInformative, "No `.bookspec' found in the project directory." if bookspec_files.empty?
|
62
|
+
raise PlainInformative, "Multiple `.bookspec' found in current directory" if bookspec_files.count > 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'os'
|
5
|
+
|
6
|
+
require_relative '../command'
|
7
|
+
|
8
|
+
|
9
|
+
module Epuber
|
10
|
+
class Command
|
11
|
+
class Compile < Command
|
12
|
+
self.summary = 'Compile targets into multiple EPUB files.'
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('TARGETS', false, true),
|
15
|
+
]
|
16
|
+
|
17
|
+
def self.options
|
18
|
+
[
|
19
|
+
['--check', 'Performs additional validation on sources + checks result epub with epubcheck.'],
|
20
|
+
['--write', 'Performs additional transformations which writes to source files.'],
|
21
|
+
['--release', 'Create release version of the book, no caching, everything creates from scratch.'],
|
22
|
+
].concat(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param argv [CLAide::ARGV]
|
26
|
+
#
|
27
|
+
def initialize(argv)
|
28
|
+
@targets_names = argv.arguments!
|
29
|
+
@should_check = argv.flag?('check', false)
|
30
|
+
@should_write = argv.flag?('write', false)
|
31
|
+
@release_version = argv.flag?('release', false)
|
32
|
+
|
33
|
+
super(argv)
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate!
|
37
|
+
super
|
38
|
+
verify_one_bookspec_exists!
|
39
|
+
verify_all_targets_exists!
|
40
|
+
end
|
41
|
+
|
42
|
+
def run
|
43
|
+
super
|
44
|
+
|
45
|
+
puts "compiling book `#{Config.instance.pretty_path_from_project(book.file_path)}`"
|
46
|
+
|
47
|
+
if @release_version
|
48
|
+
# Remove all previous versions of compiled files
|
49
|
+
targets.each do |target|
|
50
|
+
build_path = Epuber::Config.instance.release_build_path(target)
|
51
|
+
|
52
|
+
if ::File.directory?(build_path)
|
53
|
+
FileUtils.remove_dir(build_path, true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Build all targets to always clean directory
|
58
|
+
targets.each do |target|
|
59
|
+
compiler = Epuber::Compiler.new(book, target)
|
60
|
+
compiler.compile(Epuber::Config.instance.release_build_path(target), check: true, write: @should_write, release: true, verbose: verbose?)
|
61
|
+
|
62
|
+
archive_name = compiler.epub_name
|
63
|
+
|
64
|
+
if ::File.exists?(archive_name)
|
65
|
+
FileUtils.remove_file(archive_name)
|
66
|
+
end
|
67
|
+
|
68
|
+
archive_path = compiler.archive(archive_name)
|
69
|
+
|
70
|
+
system(%(epubcheck "#{archive_path}"))
|
71
|
+
|
72
|
+
convert_epub_to_mobi(archive_path, ::File.basename(archive_path, '.epub') + '.mobi') if target.create_mobi
|
73
|
+
end
|
74
|
+
else
|
75
|
+
targets.each do |target|
|
76
|
+
compiler = Epuber::Compiler.new(book, target)
|
77
|
+
compiler.compile(Epuber::Config.instance.build_path(target), check: @should_check, write: @should_write, verbose: verbose?)
|
78
|
+
archive_path = compiler.archive(configuration_suffix: 'debug')
|
79
|
+
|
80
|
+
system(%(epubcheck "#{archive_path}")) if @should_check
|
81
|
+
|
82
|
+
convert_epub_to_mobi(archive_path, ::File.basename(archive_path, '.epub') + '.mobi') if target.create_mobi
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# @return [Array<Epuber::Book::Target>]
|
90
|
+
#
|
91
|
+
def targets
|
92
|
+
@targets ||= (
|
93
|
+
targets = @targets_names
|
94
|
+
|
95
|
+
# when the list of targets is nil pick all available targets
|
96
|
+
if targets.empty?
|
97
|
+
book.targets
|
98
|
+
else
|
99
|
+
targets.map { |target_name| book.target_named(target_name) }
|
100
|
+
end
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
def verify_all_targets_exists!
|
105
|
+
index = targets.index(&:nil?)
|
106
|
+
help! "Not found target `#{@targets_names[index]}' in bookspec `#{book.file_path}'" unless index.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_dir(path)
|
110
|
+
if ::File.directory?(path)
|
111
|
+
path
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def find_calibre_app
|
116
|
+
locations = `mdfind "kMDItemCFBundleIdentifier == net.kovidgoyal.calibre"`.split("\n")
|
117
|
+
UI.error!("Can't find location of calibre.app to convert EPUB to MOBI.") if locations.empty?
|
118
|
+
|
119
|
+
selected = locations.first
|
120
|
+
UI.warn("Using calibre.app at location #{selected}") if locations.count > 1
|
121
|
+
|
122
|
+
selected
|
123
|
+
end
|
124
|
+
|
125
|
+
def find_calibre_convert_file
|
126
|
+
if OS.osx?
|
127
|
+
::File.join(find_calibre_app, 'Contents/MacOS/ebook-convert')
|
128
|
+
elsif OS.linux?
|
129
|
+
script_path = '/usr/bin/ebook-convert'
|
130
|
+
UI.error!("Can't find ebook-convert in folder /usr/bin to convert EPUB to MOBI.") unless ::File.executable?(script_path)
|
131
|
+
script_path
|
132
|
+
else
|
133
|
+
UI.error!('Unsupported OS to convert EPUB to MOBI.')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def convert_epub_to_mobi(epub_path, mobi_path)
|
138
|
+
system(find_calibre_convert_file, epub_path, mobi_path)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require_relative '../command'
|
6
|
+
require_relative '../vendor/ruby_templater'
|
7
|
+
|
8
|
+
|
9
|
+
module Epuber
|
10
|
+
class Command
|
11
|
+
class Init < Command
|
12
|
+
self.summary = 'Initialize current folder to use it as Epuber project'
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('PROJECT_NAME', false, true),
|
15
|
+
]
|
16
|
+
|
17
|
+
# @param argv [CLAide::ARGV]
|
18
|
+
#
|
19
|
+
def initialize(argv)
|
20
|
+
@book_name = argv.arguments!.first
|
21
|
+
|
22
|
+
super(argv)
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate!
|
26
|
+
help! 'You must specify identifier-like name of the book as first argument' if @book_name.nil?
|
27
|
+
|
28
|
+
existing = Dir.glob('*.bookspec')
|
29
|
+
help! "Can't reinit this folder, #{existing.first} already exists." unless existing.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
super
|
34
|
+
|
35
|
+
write_gitignore
|
36
|
+
write_bookspec(@book_name)
|
37
|
+
write_sublime_project(@book_name)
|
38
|
+
|
39
|
+
FileUtils.mkdir_p('images')
|
40
|
+
FileUtils.mkdir_p('fonts')
|
41
|
+
FileUtils.mkdir_p('styles')
|
42
|
+
write_default_style(@book_name)
|
43
|
+
|
44
|
+
FileUtils.mkdir_p('text')
|
45
|
+
|
46
|
+
print_good_bye(@book_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def print_good_bye(book_id)
|
53
|
+
puts <<-END.ansi.green
|
54
|
+
Project initialized, please review #{book_id}.bookspec file, remove comments.
|
55
|
+
END
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates <book-id>.bookspec file from template
|
59
|
+
#
|
60
|
+
# @param book_id [String]
|
61
|
+
#
|
62
|
+
# @return [void]
|
63
|
+
#
|
64
|
+
def write_bookspec(book_id)
|
65
|
+
template_path = File.expand_path(File.join('..', 'templates', 'template.bookspec'), File.dirname(__FILE__))
|
66
|
+
rendered = Epuber::RubyTemplater.from_file(template_path)
|
67
|
+
.with_locals(book_id: book_id)
|
68
|
+
.render
|
69
|
+
|
70
|
+
write("#{book_id}.bookspec", rendered)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Creates <book-id>.sublime-project
|
74
|
+
#
|
75
|
+
# @param book_id [String]
|
76
|
+
#
|
77
|
+
# @return [void]
|
78
|
+
#
|
79
|
+
def write_sublime_project(book_id)
|
80
|
+
text = '{
|
81
|
+
"folders": [
|
82
|
+
{
|
83
|
+
"follow_symlinks": true,
|
84
|
+
"path": ".",
|
85
|
+
"folder_exclude_patterns": [".epuber"],
|
86
|
+
"file_exclude_patterns": ["*.epub"]
|
87
|
+
}
|
88
|
+
]
|
89
|
+
}'
|
90
|
+
|
91
|
+
write("#{book_id}.sublime-project", text)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Creates .gitignore file
|
95
|
+
#
|
96
|
+
# @return [void]
|
97
|
+
#
|
98
|
+
def write_gitignore
|
99
|
+
write('.gitignore', <<-END
|
100
|
+
# This is generated with `epuber init`
|
101
|
+
*.epub
|
102
|
+
*.mobi
|
103
|
+
!.epuber/
|
104
|
+
.epuber/build
|
105
|
+
.epuber/release_build
|
106
|
+
|
107
|
+
END
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def write_default_style(book_id)
|
112
|
+
write("styles/#{book_id}.styl", <<-END
|
113
|
+
// This is generated with `epuber init` script.
|
114
|
+
END
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param string [String] text to file
|
119
|
+
# @param file_path [String] path to file
|
120
|
+
#
|
121
|
+
# @return [void]
|
122
|
+
#
|
123
|
+
def write(file_path, string)
|
124
|
+
File.write(file_path, string)
|
125
|
+
end
|
126
|
+
|
127
|
+
# @param text [String]
|
128
|
+
#
|
129
|
+
# @return [String] returned text without new line
|
130
|
+
#
|
131
|
+
def ask(text)
|
132
|
+
print text
|
133
|
+
result = $stdin.gets.chomp
|
134
|
+
|
135
|
+
while result.empty?
|
136
|
+
puts 'Value cannot be empty, please fill it!'.ansi.red
|
137
|
+
print text
|
138
|
+
result = $stdin.gets.chomp
|
139
|
+
end
|
140
|
+
|
141
|
+
result
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|