glyph 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/Rakefile +19 -40
  2. data/benchmark.rb +1 -2
  3. data/book/config.yml +8 -8
  4. data/book/document.glyph +18 -19
  5. data/book/images/glyph/commands_tasks.png +0 -0
  6. data/book/lib/layouts/bookindex.glyph +113 -111
  7. data/book/lib/layouts/bookpage.glyph +112 -108
  8. data/book/lib/macros/reference.rb +2 -2
  9. data/book/lib/tasks/tasks.rake +1 -1
  10. data/book/text/acknowledgements.glyph +1 -0
  11. data/book/text/changelog.glyph +140 -112
  12. data/book/text/compiling/compiling.glyph +36 -24
  13. data/book/text/compiling/lite_mode.glyph +11 -11
  14. data/book/text/compiling/programmatic_usage.glyph +57 -57
  15. data/book/text/config/document.glyph +7 -1
  16. data/book/text/config/options.glyph +5 -3
  17. data/book/text/config/output.glyph +41 -8
  18. data/book/text/extending/bookmarks_headers.glyph +13 -11
  19. data/book/text/extending/command.glyph +1 -1
  20. data/book/text/extending/commands_tasks.glyph +2 -2
  21. data/book/text/extending/internals.glyph +29 -29
  22. data/book/text/extending/interpreting.glyph +48 -9
  23. data/book/text/extending/macro_def.glyph +80 -32
  24. data/book/text/extending/output_format.glyph +2 -2
  25. data/book/text/extending/placeholders.glyph +27 -15
  26. data/book/text/extending/validators.glyph +1 -1
  27. data/book/text/getting_started/configuration.glyph +1 -1
  28. data/book/text/getting_started/create_project.glyph +4 -5
  29. data/book/text/getting_started/structure.glyph +2 -2
  30. data/book/text/macros/macros_core.glyph +341 -199
  31. data/book/text/macros/macros_filters.glyph +1 -1
  32. data/book/text/macros/macros_inline.glyph +3 -3
  33. data/book/text/macros/macros_structure.glyph +1 -1
  34. data/book/text/ref_commands.glyph +98 -93
  35. data/book/text/snippets.glyph +18 -0
  36. data/book/text/stats/bookmarks.glyph +16 -16
  37. data/book/text/stats/links.glyph +23 -23
  38. data/book/text/stats/macros.glyph +14 -14
  39. data/book/text/stats/snippets.glyph +26 -26
  40. data/book/text/stats/stats.glyph +14 -15
  41. data/book/text/text_editing/attribute_intro.glyph +8 -8
  42. data/book/text/text_editing/code.glyph +16 -16
  43. data/book/text/text_editing/conditionals.glyph +12 -13
  44. data/book/text/text_editing/esc_quot.glyph +3 -3
  45. data/book/text/text_editing/evaluation.glyph +57 -3
  46. data/book/text/text_editing/inclusions.glyph +34 -25
  47. data/book/text/text_editing/macro_composition.glyph +28 -0
  48. data/book/text/text_editing/macro_intro.glyph +4 -4
  49. data/book/text/text_editing/section_aliases.glyph +23 -23
  50. data/book/text/text_editing/sections.glyph +22 -22
  51. data/book/text/text_editing/stylesheets.glyph +33 -33
  52. data/book/text/text_editing/topics.glyph +6 -6
  53. data/book/text/text_editing/xml_fallback.glyph +1 -1
  54. data/book/text/troubleshooting/errors_command.glyph +4 -4
  55. data/book/text/troubleshooting/errors_generic.glyph +16 -10
  56. data/book/text/troubleshooting/errors_macro.glyph +18 -21
  57. data/book/text/troubleshooting/errors_parser.glyph +7 -7
  58. data/config.yml +51 -29
  59. data/document.glyph +18 -18
  60. data/glyph.gemspec +39 -287
  61. data/layouts/web5/topic.glyph +1 -1
  62. data/lib/glyph.rb +42 -10
  63. data/lib/glyph/analyzer.rb +5 -2
  64. data/lib/glyph/bookmark.rb +3 -1
  65. data/lib/glyph/commands.rb +11 -9
  66. data/lib/glyph/commands/add.rb +3 -1
  67. data/lib/glyph/commands/compile.rb +10 -7
  68. data/lib/glyph/commands/config.rb +7 -5
  69. data/lib/glyph/commands/init.rb +2 -0
  70. data/lib/glyph/commands/outline.rb +2 -0
  71. data/lib/glyph/commands/stats.rb +3 -0
  72. data/lib/glyph/commands/todo.rb +2 -0
  73. data/lib/glyph/config.rb +2 -0
  74. data/lib/glyph/document.rb +34 -9
  75. data/lib/glyph/interpreter.rb +2 -0
  76. data/lib/glyph/macro.rb +97 -25
  77. data/lib/glyph/macro_validators.rb +9 -6
  78. data/lib/glyph/node.rb +3 -1
  79. data/lib/glyph/parser.rb +68 -33
  80. data/lib/glyph/reporter.rb +3 -1
  81. data/lib/glyph/syntax_node.rb +23 -28
  82. data/lib/glyph/system_extensions.rb +21 -0
  83. data/lib/glyph/utils.rb +24 -4
  84. data/macros/block.rb +111 -0
  85. data/macros/core.rb +163 -33
  86. data/macros/filters.rb +3 -2
  87. data/macros/inline.rb +97 -0
  88. data/macros/reps/html.rb +180 -0
  89. data/macros/reps/html5.rb +100 -0
  90. data/macros/reps/web.rb +4 -0
  91. data/macros/reps/web5.rb +4 -0
  92. data/macros/structure.rb +229 -0
  93. data/macros/xml.rb +29 -24
  94. data/spec/config.yml +7 -0
  95. data/spec/files/article.glyph +2 -2
  96. data/spec/files/web_doc.glyph +9 -5
  97. data/spec/lib/commands_spec.rb +13 -9
  98. data/spec/lib/config_spec.rb +2 -2
  99. data/spec/lib/document_spec.rb +10 -0
  100. data/spec/lib/glyph_spec.rb +30 -8
  101. data/spec/lib/macro_spec.rb +39 -4
  102. data/spec/lib/macro_validators_spec.rb +3 -4
  103. data/spec/lib/parser_spec.rb +7 -0
  104. data/spec/lib/reporter_spec.rb +1 -0
  105. data/spec/lib/syntax_node_spec.rb +40 -6
  106. data/spec/macros/core_spec.rb +154 -21
  107. data/spec/macros/filters_spec.rb +1 -1
  108. data/spec/macros/html5_spec.rb +4 -5
  109. data/spec/macros/macros_spec.rb +6 -7
  110. data/spec/macros/web5_spec.rb +3 -3
  111. data/spec/macros/web_spec.rb +10 -7
  112. data/spec/macros/xml_spec.rb +11 -2
  113. data/spec/spec_helper.rb +11 -5
  114. data/spec/tasks/generate_spec.rb +40 -5
  115. data/spec/tasks/load_spec.rb +1 -13
  116. data/styles/coderay.css +147 -38
  117. data/styles/default.css +19 -22
  118. data/styles/pagination.css +30 -30
  119. data/tasks/generate.rake +54 -18
  120. data/tasks/load.rake +9 -24
  121. data/tasks/project.rake +0 -2
  122. metadata +208 -207
  123. data/.gitignore +0 -7
  124. data/VERSION +0 -1
  125. data/book/snippets.yml +0 -18
  126. data/lib/glyph/macro_helpers.rb +0 -282
  127. data/macros/html/block.rb +0 -124
  128. data/macros/html/inline.rb +0 -42
  129. data/macros/html/structure.rb +0 -191
  130. data/macros/html5/block.rb +0 -69
  131. data/macros/html5/inline.rb +0 -24
  132. data/macros/html5/structure.rb +0 -140
@@ -3,6 +3,9 @@ The following configuration settings are related to the current Glyph document.
3
3
  config_table[
4
4
  ref_config[document.author|
5
5
  The author of the document.
6
+ ]
7
+ ref_config[document.cover|
8
+ The image used as the document cover (used only for e-book generation).
6
9
  ]
7
10
  ref_config[document.draft|
8
11
  If set to @true@, the document is considered a draft, so =>[#m_draftcomment|draft comments] and =>[#m_todo|todo items] will be displayed.
@@ -24,7 +27,7 @@ The main source file to compile. It can be also be overridden by calling the #>[
24
27
  How to process stylesheets. It can be set to one of the following values:
25
28
  * @embed@ -- Embed stylesheets within the document.
26
29
  * @link@ -- Link stylesheets.
27
- * @import@ -- Import stylesheets using the code[@import] CSS directive.
30
+ * @import@ -- Import stylesheets using the code[@import] CSS directive.
28
31
  ]
29
32
  ref_config[document.subtitle|
30
33
  The subtitle of the document, displayed using the %>[subtitle].
@@ -32,4 +35,7 @@ The subtitle of the document, displayed using the %>[subtitle].
32
35
  ref_config[document.title|
33
36
  The title of the document, displayed using the %>[title].
34
37
  ]
38
+ ref_config[document.isbn|
39
+ The ISBN of the document, for e-book generation.
40
+ ]
35
41
  ]
@@ -2,7 +2,7 @@ The following configuration settings are used to enable or disable specific Glyp
2
2
 
3
3
  config_table[
4
4
  ref_config[options.filters_by_file_extension|
5
- If set to @true@, a filter macro is applied to included files, based on their extensions (\.fmi[including files|#incl]).
5
+ If set to @true@, a filter macro is applied to included files, based on their extensions (\/fmi[including files|#incl]).
6
6
  ]
7
7
  ref_config[options.macro_set|
8
8
  Determines which macro set will be loaded. It can be set to:
@@ -11,10 +11,10 @@ Determines which macro set will be loaded. It can be set to:
11
11
  * core -- Loads core macros only.
12
12
  ]
13
13
  ref_config[options.safe_mode|
14
- Enables Safe Mode (\.fmi[Glyph modes|#modes]).
14
+ Enables Safe Mode (\/fmi[Glyph modes|#modes]).
15
15
  ]
16
16
  ref_config[options.url_validation|
17
- If set to _true_, every external link will be validated (see =>[#links]).
17
+ If set to _true_, every external link will be validated (see =>[#links]).
18
18
  ]
19
19
  ref_config[options.xml_blacklist|
20
20
  The XML tags listed here cannot be generated using Glyph code.
@@ -22,4 +22,6 @@ The XML tags listed here cannot be generated using Glyph code.
22
22
  ref_config[options.xml_fallback|
23
23
  If set to true, any unknown macro name will considered an XML element (see =>[#other_elements]).
24
24
  ]
25
+ ref_config[options.ebook.converter|
26
+ The full path name of the ebook-convert command. Defaults to /usr/bin/ebook-convert.]
25
27
  ]
@@ -5,10 +5,13 @@ If set to _true_, the document will be rendered in multiple files, according to
5
5
  The extension to use for the output file(s).
6
6
  ]
7
7
  &:[o_filter_target|
8
- The output target for filters. It can be set to @html@ (for RedCloth and MarkDown) or @latex@ (RedCloth-only).
8
+ The output target for filters. It can be set to @html@ (for RedCloth and MarkDown) or @latex@ (RedCloth-only).
9
9
  ]
10
- &:[o_macro_dirs|
11
- The directories from which macros will be loaded (both in Glyph's home and the current project directory).
10
+ &:[o_through|
11
+ The intermediate format from which a PDF file is generated. It can be set to @html@ or @html5@.
12
+ ]
13
+ &:[o_macro_reps|
14
+ The name of the representation file from which macro representation will be loaded.
12
15
  ]
13
16
  &:[o_layout_dirs|
14
17
  The directories from which layout macros will be loaded (both in Glyph's home and the current project directory).
@@ -22,18 +25,48 @@ The name of the layout to use to render the document index file.
22
25
  &:[o_base|
23
26
  The directory to use as root for all link paths.
24
27
  ]
28
+ &:[o_calibre|
29
+ An array of options to configure Calibre. See the =>[http://calibre-ebook.com/user_manual/cli/ebook-convert-3.html|full list].
30
+ ]
25
31
  These settings are used to configure output-specific options.
26
32
 
27
33
 
34
+ section[
35
+ @title[output.epub.*]
36
+ config_table[
37
+ out_cfg[epub.extension]
38
+ out_cfg[epub.filter_target]
39
+ ref_config[output.epub.generator|
40
+ The external program used to generate EPUB files. It must be set to @calibre@.
41
+ ]
42
+ out_cfg[epub.calibre]
43
+ out_cfg[epub.macro_reps]
44
+ out_cfg[epub.multifile]
45
+ ]
46
+ ]
47
+ section[
48
+ @title[output.mobi.*]
49
+ config_table[
50
+ out_cfg[mobi.extension]
51
+ out_cfg[mobi.filter_target]
52
+ ref_config[output.mobi.generator|
53
+ The external program used to generate MOBI files. It must be set to @calibre@.
54
+ ]
55
+ out_cfg[mobi.calibre]
56
+ out_cfg[mobi.macro_reps]
57
+ out_cfg[mobi.multifile]
58
+ ]
59
+ ]
28
60
  section[
29
61
  @title[output.pdf.*]
30
62
  config_table[
31
63
  out_cfg[pdf.extension]
32
64
  out_cfg[pdf.filter_target]
65
+ out_cfg[pdf.through]
33
66
  ref_config[output.pdf.generator|
34
67
  The external program used to generate PDF files. It can be set to @prince@ or @wkhtmltopdf@.
35
68
  ]
36
- out_cfg[pdf.macro_dirs]
69
+ out_cfg[pdf.macro_reps]
37
70
  out_cfg[pdf.multifile]
38
71
  ]
39
72
  ]
@@ -42,7 +75,7 @@ section[
42
75
  config_table[
43
76
  out_cfg[html.extension]
44
77
  out_cfg[html.filter_target]
45
- out_cfg[html.macro_dirs]
78
+ out_cfg[html.macro_reps]
46
79
  out_cfg[html.multifile]
47
80
  ]
48
81
  ]
@@ -51,7 +84,7 @@ section[
51
84
  config_table[
52
85
  out_cfg[html5.extension]
53
86
  out_cfg[html5.filter_target]
54
- out_cfg[html5.macro_dirs]
87
+ out_cfg[html5.macro_reps]
55
88
  out_cfg[html5.multifile]
56
89
  ]
57
90
  ]
@@ -64,7 +97,7 @@ section[
64
97
  out_cfg[web.layout_dirs]
65
98
  out_cfg[web.layouts.index]
66
99
  out_cfg[web.layouts.topic]
67
- out_cfg[web.macro_dirs]
100
+ out_cfg[web.macro_reps]
68
101
  out_cfg[web.multifile]
69
102
  ]
70
103
  ]
@@ -77,7 +110,7 @@ section[
77
110
  out_cfg[web5.layout_dirs]
78
111
  out_cfg[web5.layouts.index]
79
112
  out_cfg[web5.layouts.topic]
80
- out_cfg[web5.macro_dirs]
113
+ out_cfg[web5.macro_reps]
81
114
  out_cfg[web5.multifile]
82
115
  ]
83
116
  ]
@@ -1,16 +1,18 @@
1
- txt[
2
- The =>[&[yardoc]/Macro|@Glyph::Macro@] class also includes a few methods to check and store bookmarks and headers. Consider for example the following source code for the %>[anchor]:
3
- ]
1
+ txt[
2
+ The =>[&[rubydoc]/Macro|@Glyph::Macro@] class also includes a few methods to check and store bookmarks and headers. Consider for example the following source code for the %>[anchor]:
3
+ ]
4
4
 
5
- highlight[=ruby|
5
+ highlight[=ruby|
6
6
  macro :anchor do
7
- ident, title = @params
8
- macro_error "Bookmark '#{ident}' already exists" if bookmark? ident
9
- bookmark :id => ident, :title => title
10
- %{<a id="#{ident}">#{title}</a>}
7
+ min_parameters 1
8
+ max_parameters 2
9
+ bookmark :id => param(0), :title => param(1), :file => @source_file
10
+ @data[:id] = param 0
11
+ @data[:title] = param 1
12
+ render
11
13
  end
12
- =]
14
+ =]
13
15
 
14
- txt[
16
+ txt[
15
17
  The @bookmark?@ method can be used to check the existance of a particular ID within the whole document, while the @bookmark@ method is used to store bookmark IDs and titles. In a similar way, you can use @header?@ and @header@ methods to check the existance of headers within the documents or store new ones.
16
- ]
18
+ ]
@@ -29,7 +29,7 @@ That's it. If you try to run @glyph help@ within your project directory, notice
29
29
  highlight[html|
30
30
  $ glyph help
31
31
  =====================================
32
- Glyph v\.%[Glyph::VERSION]
32
+ Glyph v\/%[Glyph::VERSION]
33
33
  =====================================
34
34
  usage: glyph command \[options\]
35
35
 
@@ -9,9 +9,9 @@ section[
9
9
  txt[
10
10
  Before creating custom Glyph commands and tasks, you should have a basic understanding on how they work, and which commands -- or better, which tasks -- are already available.
11
11
 
12
- The following diagram outlines the relationships between commands and tasks:
12
+ The following diagram outlines the relationships between the default commands and some tasks:
13
13
  ]
14
- figure[glyph/commands_tasks.png|Glyph default commands and tasks]
14
+ figure[glyph/commands_tasks.png|Some of Glyph default commands and tasks]
15
15
  txt[
16
16
  As you can see:
17
17
  * All commands call at at least one task.
@@ -1,15 +1,15 @@
1
- p[If you plan on extending Glyph, knowing how it works inside helps. It is not mandatory by any means, but it definitely helps, especially when creating complex macros.]
2
- p[What happens behind the scenes when you call code[glyph compile]? Glyph's code is parsed, analyzed and then translated into text, and here's how:]
3
- figure[glyph/document_generation.png|A sequence diagram for document generation]
4
- txt[From the diagram, it is possible to divide the document generation process into three phases:
1
+ p[If you plan on extending Glyph, knowing how it works inside helps. It is not mandatory by any means, but it definitely helps, especially when creating complex macros.]
2
+ p[What happens behind the scenes when you call code[glyph compile]? Glyph's code is parsed, analyzed and then translated into text, and here's how:]
3
+ figure[glyph/document_generation.png|A sequence diagram for document generation]
4
+ txt[From the diagram, it is possible to divide the document generation process into three phases:
5
5
  * The _Parsing Phase_ starts when a chunk of Glyph code is passed (by the code[generate:document] Rake task, for example) to a class[Glyph::Interpreter]. The interpreter initializes a class[Glyph::Parser] that parses the code and returns an _Abstract Syntax Tree_ (AST) of class[Glyph::SyntaxNode] objects.
6
6
  * The _Analysis Phase_ (Processing) starts when the interpreter method calls the @analyze@ method, instantiating a new class[Glyph::Document]. The @Glyph::Document@ object evaluates the AST expanding all macro nodesth (that's when macros are executed) and generates string.
7
7
  * The _Finalization Phase_ (Post-Processing) starts when the interpreter calls the @finalyze@ method, causing the @Glyph::Document@ object to perform a series of finalizations on the string obtained after analysis, i.e. it replaces escape sequences and placeholders.
8
- ]
9
- section[
10
- @title[Example: A short note]
11
- p[As an example, consider the following Glyph code:]
12
- highlight[=html|
8
+ ]
9
+ section[
10
+ @title[Example: A short note]
11
+ p[As an example, consider the following Glyph code:]
12
+ highlight[=html|
13
13
  fmi[something\|#test]
14
14
  ...
15
15
  section[
@@ -17,9 +17,9 @@ section[
17
17
  @id[test]
18
18
  ...
19
19
  ]
20
- =]
21
- p[This simple snippet uses the %>[fmi] to link to a section later on in the document. When parsed, the produced AST is the following:]
22
- highlight[=ruby|
20
+ =]
21
+ p[This simple snippet uses the %>[fmi] to link to a section later on in the document. When parsed, the produced AST is the following:]
22
+ highlight[=ruby|
23
23
  {:name=>:"--"}
24
24
  {:name=>:fmi, :escape=>false}
25
25
  {:name=>:"0"}
@@ -44,27 +44,27 @@ section[
44
44
  {:value=>"Test Section"}
45
45
  {:name=>:id, :escape=>false}
46
46
  {:value=>"test"}
47
- =]
48
- p[This output is produced by calling the code[inspect] method on the AST. Each class[Glyph::SyntaxNode] object in the tree is basically an ordinary Glyph Hash with a parent and 0 or more chidren, so the code snippets above shows how the syntax nodes are nested.]
49
- p[The AST contains information about macro, parameter and attribute names, and escaping, and raw text values (the nodes without a code[:name] key), but nothing more.]
50
- p[When the AST is analyzed, the resulting textual output is the following:]
51
- highlight[=html|
47
+ =]
48
+ p[This output is produced by calling the code[inspect] method on the AST. Each class[Glyph::SyntaxNode] object in the tree is basically an ordinary Glyph Hash with a parent and 0 or more chidren, so the code snippets above shows how the syntax nodes are nested.]
49
+ p[The AST contains information about macro, parameter and attribute names, and escaping, and raw text values (the nodes without a code[:name] key), but nothing more.]
50
+ p[When the AST is analyzed, the resulting textual output is the following:]
51
+ highlight[=html|
52
52
  <span class="fmi">for more information on something, see ‡‡‡‡‡PLACEHOLDER ¤ 1‡‡‡‡‡
53
53
  </span>
54
- \\\\\.[...\\\\\.]
54
+ \\\\\/[...\\\\\/]
55
55
  <div class="section">
56
56
  <h2 id="test">Test Section</h2>
57
- \\\\\.[...\\\\\.]
57
+ \\\\\/[...\\\\\/]
58
58
 
59
59
  </div>
60
- =]
61
- p[This looks almost perfect, except that:]
62
- ul[
63
- li[There's a nasty placeholder instead of a link: this is due to the fact that when the link is processed, there is no code[#text] anchor in the document, but there may be one afterwards (and there will be).]
64
- li[There are some escaped brackets.]
65
- ]
66
- p[Finally, when the document is finalized, placeholders and escape sequences are removed and the final result is the following:]
67
- highlight[=html|
60
+ =]
61
+ p[This looks almost perfect, except that:]
62
+ ul[
63
+ li[There's a nasty placeholder instead of a link: this is due to the fact that when the link is processed, there is no code[#text] anchor in the document, but there may be one afterwards (and there will be).]
64
+ li[There are some escaped brackets.]
65
+ ]
66
+ p[Finally, when the document is finalized, placeholders and escape sequences are removed and the final result is the following:]
67
+ highlight[=html|
68
68
  <span class="fmi">for more information on something,
69
69
  see <a href="#test">Test Section</a></span>
70
70
  [...]
@@ -73,5 +73,5 @@ section[
73
73
  [...]
74
74
 
75
75
  </div>
76
- =]
77
- ]
76
+ =]
77
+ ]
@@ -14,34 +14,73 @@ end
14
14
  txt[
15
15
  When the @interpret@ method is called, the following happens:
16
16
  # A new Glyph document is created from the @String@ passed to the method.
17
- # The bookmarks, headers and placeholders are passed from the main document to the new one. Because they are stored in arrays and hashes, they are passed by reference, so for example any new bookmark stored in the new document will also become available in the main document.
17
+ # Document-specific objects (bookmarks, headers, snippet, fragments, placeholders, etc.) are passed from the main document to the new one. Because they are stored in arrays and hashes, they are passed by reference, so for example any new bookmark stored in the new document will also become available in the main document.
18
18
  # Any macro included in the @String@ is evaluated, and the resulting text is returned by the method. Note that this new document does not get finalized: in other words, placeholders will be left as they are, and they'll eventually be replaced when _the main document_ is finalized.
19
19
  ]
20
20
 
21
- section[
22
- @title[Rewriting]
21
+ §[
22
+ @title[Dispatching]
23
+ txt[
24
+ =>[#composition] can be useful to remove nesting, but you can also use it to create your own macro _dispatchers_. What is a macro dispatcher? The easies way to understand this is by looking at the source code of one of them, the %>[s]:
25
+ ]
26
+ highlight[=ruby|
27
+ macro :s do
28
+ dispatch do \|node\|
29
+ forbidden = [:each, :each_line, :each_byte, :upto, :intern, :to_sym, :to_f]
30
+ meth = node[:name]
31
+ infer_type = lambda do \|str\|
32
+ # Code omitted...
33
+ end
34
+ macro_error "Macro 's/#{meth}' takes at least one parameter" unless node.params.length > 0
35
+ macro_error "String method '#{meth}' is not supported" if meth.in?(forbidden) \|\| meth.to_s.match(/\!$/)
36
+ str = node.param(0).evaluate(node, :params => true)
37
+ begin
38
+ if node.param(1) then
39
+ meth_params = node.params[1..node.params.length-1].map do \|p\|
40
+ infer_type.call(p.evaluate(node, :params => true))
41
+ end
42
+ str.send(meth, *meth_params).to_s
43
+ else
44
+ str.send(meth).to_s
45
+ end
46
+ rescue Exception => e
47
+ # Code omittted
48
+ end
49
+ end
50
+ end
51
+ =]
52
+ txt[
53
+ See the @dispatch@ method at the very beginning? This method takes a block with a @node@ parameter, corresponding to the MacroNode of the macro which is being composed with @s@. So, for example, if you write code[=s/sub[my string\|/my/\|your]=] the node of a macro called @sub@ will be passed to the block. Of course there's no @sub@ macro defined in Glyph, but it doesn't matter: its name will be interpreted as the name of a method of the Ruby String class in this case, so no worries.
54
+
55
+ Got it? Tricky, but damn useful to create your own "dynamic" macros.
56
+ ]
57
+
58
+ ]
59
+
60
+ §[
61
+ @title[Defining macros using Glyph]
23
62
  @id[rewriting]
24
- p[While the code[interpret] method is useful to evaluate Glyph code in a macro while performing other actions (storing a bookmark, checking for the presence of an anchor, etc.), in some cases it may not be necessary. If you simply want your macro to be converted into existing Glyph macro without performing any action excepting parameter substitution, you can just use the %>[rewrite:] within youy Glyph document]
63
+ p[While the code[interpret] method is useful to evaluate Glyph code in a macro while performing other actions (storing a bookmark, checking for the presence of an anchor, etc.), in some cases it may not be necessary. If you simply want your macro to be converted into existing Glyph macro without performing any action excepting parameter substitution, you can just use the %>[define:] within your Glyph document]
25
64
  p[Consider the following macro definition:]
26
65
  highlight[=ruby|
27
66
  macro :issue do
28
67
  interpret %{
29
68
  tr[
30
- td[\.=>[http://github.com/h3rald/glyph/issues/closed#issue/#{param[0]}\|##{param(0)}]]
69
+ td[\/=>[http://github.com/h3rald/glyph/issues/closed#issue/#{param[0]}\|##{param(0)}]]
31
70
  td[txt[#{param(1)}]]
32
71
  ]
33
72
  }
34
73
  end
35
74
  =]
36
- p[The code[issue] macro is only rewriting existing Glyph code around the two parameters provided. In this case, it is possible to do exactly the same thing using the %>[rewrite:]:]
75
+ p[The code[issue] macro is only rewriting existing Glyph code around the two parameters provided. In this case, it is possible to do exactly the same thing using the %>[define:] (aliased by @def:@):]
37
76
  highlight[=html|
38
- rewrite:[issue\|
77
+ define:[issue\|
39
78
  tr[
40
- td[\.=>[http://github.com/h3rald/glyph/issues/closed#issue/{{0}}\|#{{0}}]]
79
+ td[\/=>[http://github.com/h3rald/glyph/issues/closed#issue/{{0}}\|#{{0}}]]
41
80
  td[txt[{{1}}]]
42
81
  ]
43
82
  ]
44
83
  =]
45
- p[Within the %>[rewrite:], it is possible to use a special syntax to call the code[raw_attr] or code[raw_param] methods: br[]
84
+ p[Within the %>[define:], it is possible to use a special syntax to call the code[raw_attr] or code[raw_param] methods: br[]
46
85
  code[{{]em[parameter_number] or em[attribute_name]code[}}]]
47
86
  ]
@@ -1,42 +1,42 @@
1
- txt[
1
+ txt[
2
2
  Glyph was created wih extensibility in mind. You can freely extend &[glang] by creating or overriding macros, to do whatever you like. Macro definitions are written in pure Ruby code and placed in @.rb@ files within the @lib/macros/@ folder of your project.
3
3
 
4
- box[Alternative Ways to Define Macros|
4
+ box[Alternative Ways to Define Macros|
5
5
  You can also define macros:
6
6
  * inside your document, using the %>[macro:].
7
7
  * Using the %>[include] specifying the path to an @.rb@ file containing macro definitions stored in the @lib/@ directory (useful especially when =>[#lite_mode|compiling single Glyph files]).
8
- ]
8
+ ]
9
9
 
10
10
  This is the source code of a fairly simple macro used to format a note:
11
- ]
12
- highlight[=ruby|
11
+ ]
12
+ highlight[=ruby|
13
13
  macro :note do
14
14
  %{<div class="#{@name}"><span class="note-title">#{@name.to_s.capitalize}</span>
15
- #{@value}
15
+ #{@value}
16
16
 
17
17
  </div>}
18
18
  end
19
- =]
20
- txt[
19
+ =]
20
+ txt[
21
21
  The @macro@ method takes a single @Symbol@ or @String@ parameter, corresponding to the name of the macro. In this case, the entire block (or _body_ of the macro) is a @String@ corresponding to what we want the macro to evaluate to: a @<div>@ tag containing a note.
22
22
 
23
23
  The body of the macro is evaluated in the context of the class[Glyph::Macro] class, therefore its instance variables (like code[@name] or code[@value]) can be used directly.
24
24
 
25
- box[Why using code[@name] instead of just "note"?|
25
+ box[Why using code[@name] instead of just "note"?|
26
26
  For the @note@ macro, it absolutely makes no difference. However, by using code[@name] it is possible to re-use the same code for the @tip@, @important@ and @caution@ macros as well, which are in fact only aliases of the @note@ macro.
27
- ]
27
+ ]
28
28
 
29
29
  The following table lists all the instance variables that can be used inside macros:
30
- ]
31
- table[
32
- tr[
33
- th[Variable]
34
- th[Description]
35
- ]
36
- tr[
37
- td[code[@node]]
38
- td[
39
- txt[
30
+ ]
31
+ table[
32
+ tr[
33
+ th[Variable]
34
+ th[Description]
35
+ ]
36
+ tr[
37
+ td[code[@node]]
38
+ td[
39
+ txt[
40
40
  A class[Glyph::MacroNode] containing information about the macro. Useful for accessing parent and child macros, and the current class[Glyph::Document]. Normally, instances of the code[MacroNode] class contain the following keys:
41
41
  * @:name@, the name of the macro.
42
42
  * @:source@, a @String@ identifying the source of the macro (a file, a snippet, etc.)
@@ -45,15 +45,63 @@ A class[Glyph::MacroNode] containing information about the macro. Useful for acc
45
45
  * @:document@, the instance of code[Document] the macro is contained in (populated after the document has been parsed and analyzed).
46
46
 
47
47
  Note that the first two keys can also be accessed via instance variables.
48
- ]
49
- ]
50
- ]
51
- tr[
52
- td[code[@name]]
53
- td[The name of the macro.]
54
- ]
55
- tr[
56
- td[code[@source]]
57
- td[A code[String] identifying the source of the macro (a file, a snippet, etc.).]
58
- ]
59
- ]
48
+ ]
49
+ ]
50
+ ]
51
+ tr[
52
+ td[code[@name]]
53
+ td[The name of the macro.]
54
+ ]
55
+ tr[
56
+ td[code[@source_name]]
57
+ td[A code[String] identifying the source of the macro (a file, a snippet, etc.).]
58
+ ]
59
+ tr[
60
+ td[code[@source_topic]]
61
+ td[A code[String] identifying the source topic of the macro.]
62
+ ]
63
+ tr[
64
+ td[code[@source_file]]
65
+ td[A code[String] identifying the source file of the macro.]
66
+ ]
67
+ ]
68
+ §[
69
+ @title[Representations]
70
+ txt[
71
+ There's a small problem with the code used to define the @note@ macro in the previous section: what if I want to format notes using HTML5 instead of HTML, or another output format?
72
+
73
+ Glyph supports different output formats, therefore macros must be format-independent! In fact, this is the actual source of the @note@ macro:
74
+ ]
75
+ highlight[=ruby|
76
+ macro :note do
77
+ @data[:name] = @name
78
+ @data[:text] = value
79
+ render
80
+ end
81
+ =]
82
+ txt[
83
+ The HTML representation of the note macro is defined in the @macros/reps/html.rb@ file as follows:
84
+ ]
85
+ highlight[=ruby|
86
+ rep :note do \|data\|
87
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "note"
88
+ %{<div class="#{css_class}">
89
+ <span class="note-title">#{data[:name].to_s.capitalize}</span>#{data[:text]}
90
+
91
+ </div>}
92
+ end
93
+ =]
94
+ txt[
95
+ The HTML5 representation of the note macro, on the other hand, is defined in the @macros/reps/html5.rb@ file as follows:
96
+ ]
97
+ highlight[=ruby|
98
+ rep :note do \|data\|
99
+ css_class = data[:name].to_s.match(/[a-z0-9_-]/i) ? data[:name] : "note"
100
+ %{<aside class="#{css_class}">
101
+ <span class="note-title">#{data[:name].to_s.capitalize}</span>#{data[:text]}
102
+
103
+ </aside>}
104
+ end
105
+ =]
106
+ Note the different tags used to render the note.
107
+ ]