glyph 0.3.0 → 0.4.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.
- data/.gitignore +7 -0
- data/AUTHORS.textile +8 -7
- data/CHANGELOG.textile +89 -8
- data/LICENSE.textile +1 -2
- data/README.textile +89 -61
- data/Rakefile +12 -10
- data/VERSION +1 -1
- data/benchmark.rb +1 -1
- data/book/config.yml +18 -4
- data/book/document.glyph +269 -45
- data/book/images/glyph/commands_tasks.png +0 -0
- data/book/images/{document_generation.png → glyph/document_generation.png} +0 -0
- data/book/images/glyph/glyph.eps +123 -0
- data/book/images/glyph/glyph.png +0 -0
- data/book/images/glyph/glyph.svg +29 -0
- data/book/lib/commands/commands.rb +11 -0
- data/book/lib/layouts/bookindex.glyph +127 -0
- data/book/lib/layouts/bookpage.glyph +129 -0
- data/book/lib/layouts/project.glyph +26 -0
- data/book/lib/macros/reference.rb +27 -7
- data/book/lib/tasks/tasks.rake +52 -0
- data/book/snippets.yml +1 -1
- data/book/text/{acknowledgement.glyph → acknowledgements.glyph} +4 -2
- data/book/text/changelog.glyph +29 -3
- data/book/text/compiling/compiling.glyph +44 -20
- data/book/text/compiling/lite_mode.glyph +0 -4
- data/book/text/compiling/programmatic_usage.glyph +1 -5
- data/book/text/config/document.glyph +35 -0
- data/book/text/config/filters.glyph +28 -0
- data/book/text/config/options.glyph +25 -0
- data/book/text/config/output.glyph +83 -0
- data/book/text/extending/bookmarks_headers.glyph +0 -5
- data/book/text/extending/command.glyph +56 -0
- data/book/text/extending/commands_tasks.glyph +39 -0
- data/book/text/extending/further_reading.glyph +0 -3
- data/book/text/extending/internals.glyph +3 -5
- data/book/text/extending/interpreting.glyph +0 -4
- data/book/text/extending/layouts.glyph +68 -0
- data/book/text/extending/macro_def.glyph +0 -5
- data/book/text/extending/output_format.glyph +78 -0
- data/book/text/extending/params_attrs.glyph +0 -3
- data/book/text/extending/placeholders.glyph +0 -4
- data/book/text/extending/task.glyph +46 -0
- data/book/text/extending/validators.glyph +5 -6
- data/book/text/getting_started/configuration.glyph +1 -5
- data/book/text/getting_started/create_project.glyph +1 -5
- data/book/text/getting_started/structure.glyph +0 -4
- data/book/text/introduction.glyph +100 -75
- data/book/text/license.glyph +1 -2
- data/book/text/macros/macros_block.glyph +8 -4
- data/book/text/macros/macros_core.glyph +0 -3
- data/book/text/macros/macros_filters.glyph +2 -7
- data/book/text/macros/macros_inline.glyph +0 -4
- data/book/text/macros/macros_structure.glyph +0 -4
- data/book/text/ref_commands.glyph +29 -7
- data/book/text/stats/bookmarks.glyph +49 -0
- data/book/text/stats/links.glyph +90 -0
- data/book/text/stats/macros.glyph +73 -0
- data/book/text/stats/snippets.glyph +50 -0
- data/book/text/stats/stats.glyph +79 -0
- data/book/text/text_editing/attribute_intro.glyph +22 -0
- data/book/text/text_editing/code.glyph +0 -5
- data/book/text/text_editing/conditionals.glyph +0 -4
- data/book/text/text_editing/esc_quot.glyph +64 -0
- data/book/text/text_editing/evaluation.glyph +0 -3
- data/book/text/text_editing/glyph_files.glyph +0 -3
- data/book/text/text_editing/images.glyph +0 -5
- data/book/text/text_editing/inclusions.glyph +0 -4
- data/book/text/text_editing/links.glyph +2 -7
- data/book/text/text_editing/macro_intro.glyph +1 -98
- data/book/text/text_editing/raw_html.glyph +0 -87
- data/book/text/text_editing/section_aliases.glyph +28 -0
- data/book/text/text_editing/sections.glyph +1 -32
- data/book/text/text_editing/stylesheets.glyph +3 -5
- data/book/text/text_editing/topics.glyph +33 -0
- data/book/text/text_editing/xml_fallback.glyph +73 -0
- data/book/text/troubleshooting/errors_command.glyph +0 -3
- data/book/text/troubleshooting/errors_generic.glyph +21 -6
- data/book/text/troubleshooting/errors_macro.glyph +11 -8
- data/book/text/troubleshooting/errors_parser.glyph +0 -3
- data/config.yml +60 -25
- data/glyph.gemspec +90 -36
- data/layouts/web/index.glyph +16 -0
- data/layouts/web/topic.glyph +15 -0
- data/layouts/web5/index.glyph +16 -0
- data/layouts/web5/topic.glyph +17 -0
- data/lib/glyph.rb +36 -49
- data/lib/glyph/analyzer.rb +253 -0
- data/lib/glyph/bookmark.rb +92 -0
- data/lib/glyph/commands.rb +9 -221
- data/lib/glyph/commands/add.rb +8 -0
- data/lib/glyph/commands/compile.rb +93 -0
- data/lib/glyph/commands/config.rb +38 -0
- data/lib/glyph/commands/init.rb +6 -0
- data/lib/glyph/commands/outline.rb +45 -0
- data/lib/glyph/commands/stats.rb +48 -0
- data/lib/glyph/commands/todo.rb +29 -0
- data/lib/glyph/config.rb +2 -0
- data/lib/glyph/document.rb +61 -30
- data/lib/glyph/interpreter.rb +2 -2
- data/lib/glyph/macro.rb +14 -5
- data/lib/glyph/macro_helpers.rb +280 -0
- data/lib/glyph/macro_validators.rb +37 -2
- data/lib/glyph/reporter.rb +182 -0
- data/lib/glyph/syntax_node.rb +37 -10
- data/lib/glyph/system_extensions.rb +8 -45
- data/lib/glyph/utils.rb +148 -0
- data/macros/core.rb +10 -15
- data/macros/filters.rb +4 -5
- data/macros/html/block.rb +46 -30
- data/macros/html/inline.rb +9 -35
- data/macros/html/structure.rb +59 -72
- data/macros/html5/block.rb +69 -0
- data/macros/html5/inline.rb +24 -0
- data/macros/html5/structure.rb +139 -0
- data/macros/xml.rb +1 -1
- data/spec/files/custom_command.rb +6 -0
- data/spec/files/custom_tasks.rake +6 -0
- data/spec/files/document_for_stats.glyph +12 -0
- data/spec/files/references.glyph +4 -0
- data/spec/files/web1.glyph +11 -0
- data/spec/files/web2.glyph +10 -0
- data/spec/files/web_doc.glyph +23 -0
- data/spec/lib/analyzer_spec.rb +137 -0
- data/spec/lib/bookmark_spec.rb +64 -0
- data/spec/lib/commands_spec.rb +30 -5
- data/spec/lib/document_spec.rb +49 -9
- data/spec/lib/glyph_spec.rb +21 -1
- data/spec/lib/macro_spec.rb +6 -6
- data/spec/lib/macro_validators_spec.rb +24 -0
- data/spec/lib/reporter_spec.rb +132 -0
- data/spec/macros/core_spec.rb +2 -3
- data/spec/macros/filters_spec.rb +2 -2
- data/spec/macros/html5_spec.rb +101 -0
- data/spec/macros/macros_spec.rb +16 -6
- data/spec/macros/web5_spec.rb +32 -0
- data/spec/macros/web_spec.rb +59 -0
- data/spec/macros/xml_spec.rb +1 -1
- data/spec/spec_helper.rb +24 -4
- data/spec/tasks/generate_spec.rb +54 -0
- data/spec/tasks/load_spec.rb +29 -3
- data/spec/tasks/project_spec.rb +21 -3
- data/styles/default.css +40 -4
- data/styles/pagination.css +59 -41
- data/tasks/generate.rake +110 -31
- data/tasks/load.rake +39 -7
- data/tasks/project.rake +9 -7
- metadata +115 -34
- data/book/images/glyph.png +0 -0
- data/book/images/glyph.svg +0 -351
- data/book/output/html/glyph.html +0 -4482
- data/book/output/html/images/document_generation.png +0 -0
- data/book/output/html/images/glyph.png +0 -0
- data/book/output/html/images/glyph.svg +0 -351
- data/book/output/pdf/glyph.pdf +4 -10254
- data/book/script/authors +0 -1
- data/book/script/changelog +0 -1
- data/book/script/license +0 -1
- data/book/script/readme +0 -1
- data/book/text/ref_config.glyph +0 -100
- data/book/text/ref_macros.glyph +0 -6
- data/book/text/troubleshooting/errors_intro.glyph +0 -3
@@ -0,0 +1,45 @@
|
|
1
|
+
GLI.desc 'Display the document outline'
|
2
|
+
command :outline do |c|
|
3
|
+
c.desc "Limit to level N"
|
4
|
+
c.flag :l, :level
|
5
|
+
c.desc "Show file names"
|
6
|
+
c.switch :f, :files
|
7
|
+
c.desc "Show titles"
|
8
|
+
c.switch :t, :titles
|
9
|
+
c.desc "Show IDs"
|
10
|
+
c.switch :i, :ids
|
11
|
+
c.action do |global_options, options, args|
|
12
|
+
levels = options[:l]
|
13
|
+
ids = options[:i]
|
14
|
+
files = options[:f]
|
15
|
+
titles = options[:t]
|
16
|
+
titles = true if !ids && !levels && !files || levels && !ids
|
17
|
+
Glyph['system.quiet'] = true
|
18
|
+
Glyph.run "generate:document"
|
19
|
+
Glyph['system.quiet'] = false
|
20
|
+
puts "====================================="
|
21
|
+
puts "#{Glyph['document.title']} - Outline"
|
22
|
+
puts "====================================="
|
23
|
+
Glyph.document.structure.descend do |n, level|
|
24
|
+
if n.is_a?(Glyph::MacroNode) then
|
25
|
+
case
|
26
|
+
when n[:name].in?(Glyph['system.structure.headers']) then
|
27
|
+
header = Glyph.document.header?(n[:header].code) rescue nil
|
28
|
+
next if !header || levels && header.level-1 > levels.to_i
|
29
|
+
last_level = header.level
|
30
|
+
h_id = ids ? "[##{header.code}]" : ""
|
31
|
+
h_title = titles ? "#{header.title} " : ""
|
32
|
+
text = (" "*(header.level-1))+"- "+h_title+h_id
|
33
|
+
puts text unless text.blank?
|
34
|
+
when n[:name] == :include then
|
35
|
+
if files && n.find_parent{|p| p[:name] == :document && p.is_a?(Glyph::MacroNode)} then
|
36
|
+
# When using the book or article macros, includes appear twice:
|
37
|
+
# * in the macro parameters
|
38
|
+
# * as children of the document macro
|
39
|
+
puts "=== #{n.param(0)}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
GLI.desc 'Display statistics'
|
2
|
+
command :stats do |c|
|
3
|
+
c.desc "Display stats about macros"
|
4
|
+
c.switch [:m, :macros]
|
5
|
+
c.desc "Display stats about snippets"
|
6
|
+
c.switch [:s, :snippets]
|
7
|
+
c.desc "Display stats about bookmarks"
|
8
|
+
c.switch [:b, :bookmarks]
|
9
|
+
c.desc "Display stats about links"
|
10
|
+
c.switch [:l, :links]
|
11
|
+
c.desc "Display stats about project files"
|
12
|
+
c.switch [:f, :files]
|
13
|
+
c.desc "Display stats about a single macro"
|
14
|
+
c.flag :macro
|
15
|
+
c.desc "Display stats about a single bookmark"
|
16
|
+
c.flag :bookmark
|
17
|
+
c.desc "Display stats about links matching a regular expression"
|
18
|
+
c.flag :link
|
19
|
+
c.desc "Display stats about a single snippet"
|
20
|
+
c.flag :snippet
|
21
|
+
c.action do |global_options, options, args|
|
22
|
+
Glyph.info "Collecting stats..."
|
23
|
+
Glyph.run 'generate:document'
|
24
|
+
analyzer = Glyph::Analyzer.new
|
25
|
+
no_switches = true
|
26
|
+
[[:m, :macros], [:s, :snippets], [:b, :bookmarks], [:l, :links], [:f, :files]].each do |s|
|
27
|
+
if options[s[0]] then
|
28
|
+
analyzer.stats_for s[1]
|
29
|
+
no_switches = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
no_flags = true
|
33
|
+
[:macro, :bookmark, :link, :snippet].each do |f|
|
34
|
+
if options[f] then
|
35
|
+
analyzer.stats_for f, options[f]
|
36
|
+
no_flags = false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
analyzer.stats_for :global if no_switches && no_flags
|
40
|
+
puts "====================================="
|
41
|
+
puts "#{Glyph['document.title']} - Statistics"
|
42
|
+
puts "====================================="
|
43
|
+
puts
|
44
|
+
reporter = Glyph::Reporter.new(analyzer.stats)
|
45
|
+
reporter.detailed = false if no_switches && no_flags
|
46
|
+
reporter.display
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
GLI.desc 'Display all project TODO items'
|
2
|
+
command :todo do |c|
|
3
|
+
c.action do |global_options, options, args|
|
4
|
+
Glyph['system.quiet'] = true
|
5
|
+
Glyph.run "generate:document"
|
6
|
+
Glyph['system.quiet'] = false
|
7
|
+
unless Glyph.document.todos.blank?
|
8
|
+
puts "====================================="
|
9
|
+
puts "#{Glyph['document.title']} - TODOs"
|
10
|
+
puts "====================================="
|
11
|
+
# Group items
|
12
|
+
if Glyph.document.todos.respond_to? :group_by then
|
13
|
+
Glyph.document.todos.group_by{|e| e[:source]}.each_pair do |k, v|
|
14
|
+
puts
|
15
|
+
puts "=== #{k} "
|
16
|
+
v.each do |i|
|
17
|
+
puts " * #{i[:text]}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
Glyph.document.todos.each do |t|
|
22
|
+
Glyph.info t
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
Glyph.info "Nothing left to do."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/glyph/config.rb
CHANGED
@@ -4,6 +4,8 @@ module Glyph
|
|
4
4
|
# and provides some useful methods to access keys and subkeys.
|
5
5
|
class Config
|
6
6
|
|
7
|
+
include Glyph::Utils
|
8
|
+
|
7
9
|
# Initializes the configuration with a hash of options:
|
8
10
|
# * :file (default: nil) - A YAML file to read data from
|
9
11
|
# * :data (default: {})- The initial contents
|
data/lib/glyph/document.rb
CHANGED
@@ -18,24 +18,28 @@ module Glyph
|
|
18
18
|
['\\|', '|']
|
19
19
|
]
|
20
20
|
|
21
|
-
attr_reader :bookmarks, :placeholders, :headers, :context, :errors, :todos
|
21
|
+
attr_reader :bookmarks, :placeholders, :headers, :styles, :context, :errors, :todos, :topics, :links, :toc
|
22
22
|
|
23
23
|
# Creates a new document
|
24
24
|
# @param [GlyphSyntaxNode] tree the syntax tree to be evaluate
|
25
25
|
# @param [Glyph::Node] context the context associated with the tree
|
26
26
|
# @raise [RuntimeError] unless tree responds to :evaluate
|
27
|
-
def initialize(tree, context)
|
27
|
+
def initialize(tree, context={})
|
28
28
|
@tree = tree
|
29
29
|
@context = context
|
30
|
-
@
|
30
|
+
@context[:source] ||= {:file => nil, :name => '--', :topic => nil}
|
31
31
|
@placeholders = {}
|
32
|
-
@
|
32
|
+
@bookmarks = {}
|
33
|
+
@headers = {}
|
34
|
+
@styles = []
|
33
35
|
@errors = []
|
34
36
|
@todos = []
|
37
|
+
@topics = []
|
38
|
+
@links = []
|
39
|
+
@toc = {}
|
35
40
|
@state = :new
|
36
41
|
end
|
37
42
|
|
38
|
-
|
39
43
|
# Returns a tree of Glyph::Node objects corresponding to the analyzed document
|
40
44
|
# @raise [RuntimeError] unless the document has been analized
|
41
45
|
def structure
|
@@ -43,13 +47,18 @@ module Glyph
|
|
43
47
|
@tree
|
44
48
|
end
|
45
49
|
|
46
|
-
# Copies bookmarks, headers, todos and placeholders from another Glyph::Document
|
50
|
+
# Copies bookmarks, headers, todos, styles and placeholders from another Glyph::Document
|
47
51
|
# @param [Glyph::Document] document a valid Glyph::Document
|
48
52
|
def inherit_from(document)
|
49
53
|
@bookmarks = document.bookmarks
|
50
54
|
@headers = document.headers
|
51
55
|
@todos = document.todos
|
56
|
+
@styles = document.styles
|
57
|
+
@topics = document.topics
|
52
58
|
@placeholders = document.placeholders
|
59
|
+
@toc = document.toc
|
60
|
+
@links = document.links
|
61
|
+
self
|
53
62
|
end
|
54
63
|
|
55
64
|
# Defines a placeholder block that will be evaluated after the whole document has been analyzed
|
@@ -63,34 +72,51 @@ module Glyph
|
|
63
72
|
|
64
73
|
# Returns a stored bookmark or nil
|
65
74
|
# @param [#to_sym] key the bookmark identifier
|
66
|
-
# @return [
|
75
|
+
# @return [Glyph::Bookmark, nil] the bookmark or nil if no bookmark is found
|
67
76
|
def bookmark?(key)
|
68
77
|
@bookmarks[key.to_sym]
|
69
78
|
end
|
70
79
|
|
71
80
|
# Stores a new bookmark
|
72
|
-
# @param [Hash] hash the bookmark hash: {:id => "
|
73
|
-
# @return [
|
81
|
+
# @param [Hash] hash the bookmark hash: {:id => "BookmarkID", :title => "Bookmark Title", :file => "dir/preface.glyph"}
|
82
|
+
# @return [Glyph::Bookmark] the stored bookmark
|
83
|
+
# @raise [RuntimeError] if the bookmark is already defined.
|
74
84
|
def bookmark(hash)
|
75
|
-
|
76
|
-
|
77
|
-
@bookmarks[
|
78
|
-
|
85
|
+
b = Glyph::Bookmark.new(hash)
|
86
|
+
raise RuntimeError, "Bookmark '#{b.code}' already exists" if @bookmarks.has_key? b.code
|
87
|
+
@bookmarks[b.code] = b
|
88
|
+
b
|
79
89
|
end
|
80
90
|
|
81
91
|
# Stores a new header
|
82
|
-
# @param [Hash] hash the header hash: {:id => "
|
83
|
-
# @return [
|
92
|
+
# @param [Hash] hash the header hash: {:id => "Bookmark_ID", :title => "Bookmark Title", :level => 3}
|
93
|
+
# @return [Glyph::Header] the stored header
|
94
|
+
# @raise [RuntimeError] if the bookmark is already defined.
|
84
95
|
def header(hash)
|
85
|
-
|
86
|
-
|
96
|
+
b = Glyph::Header.new(hash)
|
97
|
+
raise RuntimeError, "Bookmark '#{b.code}' already exists" if @bookmarks.has_key? b.code
|
98
|
+
@bookmarks[b.code] = b
|
99
|
+
@headers[b.code] = b
|
100
|
+
b
|
87
101
|
end
|
88
102
|
|
89
103
|
# Returns a stored header or nil
|
90
|
-
# @param [String] key the header identifier
|
91
|
-
# @return [
|
104
|
+
# @param [String, Symbol] key the header identifier
|
105
|
+
# @return [Glyph::Header, nil] the header or nil if no header is found
|
92
106
|
def header?(key)
|
93
|
-
@headers
|
107
|
+
@headers[key.to_sym]
|
108
|
+
end
|
109
|
+
|
110
|
+
# @since 0.4.0
|
111
|
+
# Stores a stylesheet
|
112
|
+
# @param [String] file the stylesheet file
|
113
|
+
# @raises [RuntimeError] if the stylesheet is already specified for the document (unless the output has more than one file)
|
114
|
+
def style(file)
|
115
|
+
f = Pathname.new file
|
116
|
+
if @styles.include?(f) && !Glyph.multiple_output_files? then
|
117
|
+
raise RuntimeError, "Stylesheet '#{f}' already specified for the current document"
|
118
|
+
end
|
119
|
+
@styles << f
|
94
120
|
end
|
95
121
|
|
96
122
|
# Analyzes the document by evaluating its @tree
|
@@ -114,18 +140,23 @@ module Glyph
|
|
114
140
|
raise RuntimeError, "Document cannot be finalized due to previous errors" unless @context[:document].errors.blank?
|
115
141
|
# Substitute placeholders
|
116
142
|
ESCAPES.each{|e| @output.gsub! e[0], e[1]}
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
143
|
+
@placeholders.each_pair do |key, value|
|
144
|
+
begin
|
145
|
+
key_s = key.to_s
|
146
|
+
value_s = value.call(self).to_s
|
147
|
+
toc[:contents].gsub! key_s, value_s if toc[:contents].to_s.match key_s
|
148
|
+
if Glyph.multiple_output_files? then
|
149
|
+
@topics.each do |t|
|
150
|
+
ESCAPES.each{|e| t[:contents].gsub! e[0], e[1]}
|
151
|
+
t[:contents].gsub! key_s, value_s
|
152
|
+
end
|
126
153
|
end
|
154
|
+
@output.gsub! key_s, value_s
|
155
|
+
rescue Glyph::MacroError => e
|
156
|
+
e.macro.macro_warning e.message, e
|
157
|
+
rescue Exception => e
|
158
|
+
Glyph.warning e.message
|
127
159
|
end
|
128
|
-
rescue Exception => e
|
129
160
|
end
|
130
161
|
@state = :finalized
|
131
162
|
end
|
data/lib/glyph/interpreter.rb
CHANGED
@@ -11,7 +11,7 @@ module Glyph
|
|
11
11
|
# @param [Hash] context the context to pass along when expanding macros
|
12
12
|
def initialize(text, context={})
|
13
13
|
@context = context
|
14
|
-
@context[:source] ||= {:name => "--"}
|
14
|
+
@context[:source] ||= {:name => "--", :file => nil, :topic => nil}
|
15
15
|
@text = text
|
16
16
|
@parser = Glyph::Parser.new text, @context[:source][:name]
|
17
17
|
end
|
@@ -47,7 +47,7 @@ module Glyph
|
|
47
47
|
@document.inherit_from @context[:document] if @context[:document]
|
48
48
|
@tree
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
data/lib/glyph/macro.rb
CHANGED
@@ -8,8 +8,10 @@ module Glyph
|
|
8
8
|
class Macro
|
9
9
|
|
10
10
|
include Validators
|
11
|
+
include Helpers
|
12
|
+
include Utils
|
11
13
|
|
12
|
-
attr_reader :node, :
|
14
|
+
attr_reader :node, :source_name, :source_file, :source_topic
|
13
15
|
|
14
16
|
# Creates a new macro instance from a Node
|
15
17
|
# @param [Node] node a node populated with macro data
|
@@ -17,14 +19,20 @@ module Glyph
|
|
17
19
|
@node = node
|
18
20
|
@name = @node[:name]
|
19
21
|
@updated_source = nil
|
20
|
-
@
|
22
|
+
@source_name = @node[:source][:name] || nil rescue "--"
|
23
|
+
@source_topic = @node[:source][:topic] || nil rescue "--"
|
24
|
+
@source_file = @node[:source][:file] rescue nil
|
21
25
|
end
|
22
26
|
|
23
27
|
# Resets the name of the updated source (call before calling
|
24
28
|
# Macro#interpret)
|
25
29
|
# @param [String] name the source name
|
26
|
-
|
27
|
-
|
30
|
+
# @param [String] file the source file
|
31
|
+
# @param [String] topic the topic file
|
32
|
+
# @since 0.3.0
|
33
|
+
def update_source(name, file=nil, topic=nil)
|
34
|
+
file ||= @node[:source][:file] rescue nil
|
35
|
+
@updated_source = {:name => name, :file => file, :topic => topic}
|
28
36
|
end
|
29
37
|
|
30
38
|
# Returns a Glyph code representation of the specified parameter
|
@@ -180,7 +188,7 @@ module Glyph
|
|
180
188
|
if e.is_a?(Glyph::MacroError) then
|
181
189
|
e.display
|
182
190
|
else
|
183
|
-
message = "#{msg}\n source: #{@
|
191
|
+
message = "#{msg}\n source: #{@source_name}\n path: #{path}"
|
184
192
|
if Glyph.debug? then
|
185
193
|
message << %{\n#{"-"*54}\n#{@node.to_s.gsub(/\t/, ' ')}\n#{"-"*54}}
|
186
194
|
if e then
|
@@ -206,6 +214,7 @@ module Glyph
|
|
206
214
|
context[:document] = @node[:document]
|
207
215
|
interpreter = Glyph::Interpreter.new string, context
|
208
216
|
subtree = interpreter.parse
|
217
|
+
subtree[:source] = context[:source]
|
209
218
|
@node << subtree
|
210
219
|
result = interpreter.document.output
|
211
220
|
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
module Glyph
|
2
|
+
class Macro
|
3
|
+
|
4
|
+
# This module includes some output-agnostic methods used by the most common Glyph macros.
|
5
|
+
# @since 0.4.0
|
6
|
+
module Helpers
|
7
|
+
|
8
|
+
# Renders a link
|
9
|
+
# @param [String] target the target of the link
|
10
|
+
# @param[String] title the title of the link
|
11
|
+
# @yield [link_path, link_title] the block to call to render the link
|
12
|
+
# @yieldparam [String] link_path the path to the link target
|
13
|
+
# @yieldparam [String] link_title the title of the link
|
14
|
+
def link_element_for(target, title, &block)
|
15
|
+
if target.match /^#/ then
|
16
|
+
@node[:document].links << target
|
17
|
+
anchor = target.gsub /^#/, ''
|
18
|
+
bmk = bookmark? anchor
|
19
|
+
if !bmk then
|
20
|
+
placeholder do |document|
|
21
|
+
bmk = document.bookmark?(anchor)
|
22
|
+
macro_error "Bookmark '#{anchor}' does not exist" unless bmk
|
23
|
+
bmk_title = title
|
24
|
+
bmk_title = bmk.title if bmk_title.blank?
|
25
|
+
block.call bmk.link(@source_file), bmk_title
|
26
|
+
end
|
27
|
+
else
|
28
|
+
bmk_title = title
|
29
|
+
bmk_title = bmk.title if bmk_title.blank?
|
30
|
+
block.call bmk.link(@source_file), bmk_title
|
31
|
+
end
|
32
|
+
else
|
33
|
+
if Glyph['options.url_validation'] && !@node[:document].links.include?(target) then
|
34
|
+
begin
|
35
|
+
url = URI.parse(target.gsub(/\\\./, ''))
|
36
|
+
rescue Exception => e
|
37
|
+
macro_warning "Invalid URL: #{url||target}", e
|
38
|
+
end
|
39
|
+
response = Net::HTTP.get_response(url)
|
40
|
+
debug "Checking link URL: #{url} (#{response.code})"
|
41
|
+
if response.code.to_i > 302 then
|
42
|
+
macro_warning "Linked URL '#{url}' returned status #{response.code} (#{response.message})"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@node[:document].links << target
|
46
|
+
title ||= target
|
47
|
+
block.call target, title
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Renders a For More Information note
|
52
|
+
# @param [String] topic the topic of the note
|
53
|
+
# @param [String] href the reference to link to
|
54
|
+
# @yield [topic, link] the block used to render the FMI note
|
55
|
+
def fmi_element_for(topic, href, &block)
|
56
|
+
link = placeholder do |document|
|
57
|
+
interpret "link[#{href}]"
|
58
|
+
end
|
59
|
+
block.call topic, link
|
60
|
+
end
|
61
|
+
|
62
|
+
# Renders a draft comment element
|
63
|
+
# @yield [value] the block used to render the comment
|
64
|
+
# @yieldparam [String] value the comment text
|
65
|
+
def draftcomment_element(&block)
|
66
|
+
if Glyph['document.draft'] then
|
67
|
+
block.call value
|
68
|
+
else
|
69
|
+
""
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Renders a todo element
|
74
|
+
# @yield [value] the block used to render the todo element
|
75
|
+
# @yieldparam [String] value the todo text
|
76
|
+
def todo_element(&block)
|
77
|
+
todo = {:source => @source_name, :text => value}
|
78
|
+
@node[:document].todos << todo unless @node[:document].todos.include? todo
|
79
|
+
if Glyph['document.draft'] then
|
80
|
+
block.call value
|
81
|
+
else
|
82
|
+
""
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Renders an image element
|
87
|
+
# @param [String] image the image to render
|
88
|
+
# @param [String] alt the value of the image's ALT tag
|
89
|
+
# @yield [alt, dest_file] the block used to render the image
|
90
|
+
def image_element_for(image, alt, &block)
|
91
|
+
src_file = Glyph.lite? ? image : Glyph::PROJECT/"images/#{image}"
|
92
|
+
dest_file = Glyph.lite? ? image : "images/#{image}"
|
93
|
+
warning "Image '#{image}' not found" unless Pathname.new(src_file).exist?
|
94
|
+
block.call alt, dest_file
|
95
|
+
end
|
96
|
+
|
97
|
+
# Renders a figure element
|
98
|
+
# @param [String] image the image to render
|
99
|
+
# @param [String] alt the value of the image's ALT tag
|
100
|
+
# @param [String] caption
|
101
|
+
# @yield alt, dest_file, caption] the block used to render the figure
|
102
|
+
def figure_element_for(image, alt, caption, &block)
|
103
|
+
src_file = Glyph.lite? ? image : Glyph::PROJECT/"images/#{image}"
|
104
|
+
dest_file = Glyph.lite? ? image : "images/#{image}"
|
105
|
+
warning "Figure '#{image}' not found" unless Pathname.new(src_file).exist?
|
106
|
+
block.call alt, dest_file, caption
|
107
|
+
end
|
108
|
+
|
109
|
+
# Renders a title element
|
110
|
+
def title_element(&block)
|
111
|
+
unless Glyph["document.title"].blank? then
|
112
|
+
block.call
|
113
|
+
else
|
114
|
+
""
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Renders a subtitle element
|
119
|
+
def subtitle_element(&block)
|
120
|
+
unless Glyph["document.subtitle"].blank? then
|
121
|
+
block.call
|
122
|
+
else
|
123
|
+
""
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Renders an author element
|
128
|
+
def author_element(&block)
|
129
|
+
unless Glyph['document.author'].blank? then
|
130
|
+
block.call
|
131
|
+
else
|
132
|
+
""
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Renders a revision element
|
137
|
+
def revision_element(&block)
|
138
|
+
unless Glyph["document.revision"].blank? then
|
139
|
+
block.call
|
140
|
+
else
|
141
|
+
""
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Renders a Table of Contents
|
146
|
+
# @param [Integer] depth the maximum header level
|
147
|
+
# @param [String] title the title of the TOC
|
148
|
+
# @param [Hash] procs the Proc objects used to render the TOC
|
149
|
+
# @option procs [Proc] :link used to render TOC header links (parameters: Glyph::Header).
|
150
|
+
# @option procs [Proc] :toc_list used to render the TOC list (parameters: a Proc used to traverse the document tree, the Glyph::Bookmark used for the TOC header, a Glyph::Document)
|
151
|
+
# @option procs [Proc] :toc_item used to render a TOC item (parameters: an Array of header classes, a String used for the header link)
|
152
|
+
# @option procs [Proc] :toc_sublist used to render a TOC sublist (parameters: a String containing the contents of the list)
|
153
|
+
def toc_element_for(depth, title, procs={})
|
154
|
+
return @node[:document].toc[:contents] if @node[:document].toc[:contents]
|
155
|
+
link_header = procs[:link]
|
156
|
+
toc = placeholder do |document|
|
157
|
+
descend_section = lambda do |n1, added_headers|
|
158
|
+
list = ""
|
159
|
+
added_headers ||= []
|
160
|
+
n1.descend do |n2, level|
|
161
|
+
if n2.is_a?(Glyph::MacroNode) && Glyph['system.structure.headers'].include?(n2[:name]) then
|
162
|
+
if Glyph.multiple_output_files? then
|
163
|
+
# Only consider topics/booklets when building TOC for web/web5
|
164
|
+
next if !n2.attribute(:src) && n2.child_macros.select{|child| child.attribute(:src)}.blank?
|
165
|
+
end
|
166
|
+
next if n2.find_parent{|node| Glyph['system.structure.special'].include? node[:name] }
|
167
|
+
header_hash = n2[:header]
|
168
|
+
next if depth && header_hash && (header_hash.level-1 > depth.to_i) || header_hash && !header_hash.toc?
|
169
|
+
next if added_headers.include? header_hash
|
170
|
+
added_headers << header_hash
|
171
|
+
# Check if part of frontmatter, bodymatter or backmatter
|
172
|
+
container = n2.find_parent do |node|
|
173
|
+
node.is_a?(Glyph::MacroNode) &&
|
174
|
+
node[:name].in?([:frontmatter, :bodymatter, :appendix, :backmatter])
|
175
|
+
end[:name] rescue nil
|
176
|
+
list << procs[:toc_item].call([container, n2[:name]], link_header.call(header_hash)) if header_hash
|
177
|
+
child_list = ""
|
178
|
+
n2.children.each do |c|
|
179
|
+
child_list << descend_section.call(c, added_headers)
|
180
|
+
end
|
181
|
+
list << procs[:toc_sublist].call(child_list) unless child_list.blank?
|
182
|
+
end
|
183
|
+
end
|
184
|
+
list
|
185
|
+
end
|
186
|
+
title ||= "Table of Contents"
|
187
|
+
bmk = @node[:document].bookmark?(:toc) || bookmark(:id => :toc, :file => @source_file, :title => title)
|
188
|
+
procs[:toc_list].call descend_section, bmk, document
|
189
|
+
end
|
190
|
+
@node[:document].toc[:contents] = toc.to_s
|
191
|
+
toc
|
192
|
+
end
|
193
|
+
|
194
|
+
# Renders a section element
|
195
|
+
# @param [Hash] procs the Proc objects used to render the section
|
196
|
+
# @option procs [Proc] :title used to render the section header (parameters: the header level, the section ID, the section title)
|
197
|
+
# @option procs [Proc] :body used to render the section body (parameters: the section title, the section body)
|
198
|
+
def section_element_for(procs={})
|
199
|
+
h = ""
|
200
|
+
if attr(:title) then
|
201
|
+
level = 1
|
202
|
+
@node.ascend do |n|
|
203
|
+
break if n.respond_to?(:attribute) && n.attribute(:class) && n.attribute(:class).children.join.strip == "topic"
|
204
|
+
if n.is_a?(Glyph::MacroNode) && Glyph["system.structure.headers"].include?(n[:name]) then
|
205
|
+
level+=1
|
206
|
+
end
|
207
|
+
end
|
208
|
+
ident = (attr(:id) || "h_#{@node[:document].headers.length+1}").to_sym
|
209
|
+
# The bookmark is added when the section is first processed; therefore it will exist already when a topic layout is processed
|
210
|
+
bmk = @node[:document].bookmark?(ident)
|
211
|
+
bmk ||= header :title => attr(:title),
|
212
|
+
:level => level,
|
213
|
+
:id => ident,
|
214
|
+
:toc => !attr(:notoc),
|
215
|
+
:definition => @source_file,
|
216
|
+
:file => (attr(:src) || @source_file)
|
217
|
+
@node[:header] = bmk
|
218
|
+
h = procs[:title].call level, bmk, attr(:title)
|
219
|
+
end
|
220
|
+
if attr(:src) then
|
221
|
+
# Create topic
|
222
|
+
if Glyph.multiple_output_files?
|
223
|
+
topic_id = (attr(:id) || "t_#{@node[:document].topics.length}").to_sym
|
224
|
+
layout = attr(:layout) || Glyph["output.#{Glyph['document.output']}.layouts.topic"] || :topic
|
225
|
+
layout_name = "layout:#{layout}".to_sym
|
226
|
+
macro_error "Layout '#{layout}' not found" unless Glyph::MACROS[layout_name]
|
227
|
+
result = interpret %{#{layout_name}[
|
228
|
+
@title[#{attr(:title)}]
|
229
|
+
@id[#{topic_id}]
|
230
|
+
@contents[include[@topic[true]#{attr(:src)}]]
|
231
|
+
]}
|
232
|
+
bmk = @node[:document].bookmark? topic_id
|
233
|
+
if bmk then
|
234
|
+
# Fix file for topic bookmark
|
235
|
+
@node[:document].bookmark?(topic_id).file = attr(:src)
|
236
|
+
else
|
237
|
+
bookmark :title => attr(:title), :id => topic_id, :file => attr(:src), :definition => @source_file
|
238
|
+
end
|
239
|
+
topic_src = attr(:src)
|
240
|
+
topic_src += ".glyph" unless topic_src.match /\..+$/
|
241
|
+
@node[:document].topics << {:src => topic_src, :title => attr(:title), :id => topic_id, :contents => result}
|
242
|
+
# Process section contents
|
243
|
+
procs[:body].call h, value
|
244
|
+
# Return nothing
|
245
|
+
nil
|
246
|
+
else
|
247
|
+
v = raw_value
|
248
|
+
@node.children.delete_if{|c| !c.is_a?(Glyph::AttributeNode)}
|
249
|
+
body = interpret "include[#{attr(:src)}]#{v}"
|
250
|
+
procs[:body].call h, body
|
251
|
+
end
|
252
|
+
else
|
253
|
+
procs[:body].call h, value
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Renders a navigation element
|
258
|
+
# @param [String] topic_id the ID of the current topic
|
259
|
+
# @param [Hash] procs the Proc objects used to render the navigation element
|
260
|
+
# @option procs [Proc] :previous the link to the previous topic
|
261
|
+
# @option procs [Proc] :next the link to the next topic
|
262
|
+
# @option procs [Proc] :contents the link to the document contents
|
263
|
+
def navigation_element_for(topic_id, procs={})
|
264
|
+
# Get the previous topic
|
265
|
+
previous_topic = @node[:document].topics.last
|
266
|
+
previous_link = procs[:previous].call previous_topic
|
267
|
+
# The next topic is not going to be available yet, use a placeholder
|
268
|
+
next_link = placeholder do |document|
|
269
|
+
current_topic = document.topics.select{|t| t[:id] == topic_id}[0] rescue nil
|
270
|
+
next_topic = document.topics[document.topics.index(current_topic)+1] rescue nil
|
271
|
+
procs[:next].call next_topic
|
272
|
+
end
|
273
|
+
contents_link = procs[:contents].call
|
274
|
+
procs[:navigation].call contents_link, previous_link, next_link
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|