gettalong-webgen 0.5.5.20081001 → 0.5.5.20081010
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/extensions.page +1 -1
- data/doc/reference_configuration.page +85 -0
- data/doc/tag/tikz.page +158 -0
- data/lib/webgen/common/sitemap.rb +2 -3
- data/lib/webgen/contentprocessor/blocks.rb +0 -2
- data/lib/webgen/contentprocessor/context.rb +0 -3
- data/lib/webgen/contentprocessor/erubis.rb +0 -2
- data/lib/webgen/default_config.rb +8 -1
- data/lib/webgen/node.rb +49 -24
- data/lib/webgen/page.rb +25 -15
- data/lib/webgen/path.rb +20 -10
- data/lib/webgen/sourcehandler/base.rb +36 -14
- data/lib/webgen/sourcehandler/copy.rb +2 -2
- data/lib/webgen/sourcehandler/directory.rb +16 -13
- data/lib/webgen/sourcehandler/feed.rb +3 -6
- data/lib/webgen/sourcehandler/fragment.rb +6 -11
- data/lib/webgen/sourcehandler/memory.rb +41 -0
- data/lib/webgen/sourcehandler/metainfo.rb +21 -21
- data/lib/webgen/sourcehandler/page.rb +8 -12
- data/lib/webgen/sourcehandler/sitemap.rb +0 -2
- data/lib/webgen/sourcehandler/template.rb +0 -4
- data/lib/webgen/sourcehandler/virtual.rb +18 -18
- data/lib/webgen/sourcehandler.rb +83 -70
- data/lib/webgen/tag/breadcrumbtrail.rb +1 -4
- data/lib/webgen/tag/coderay.rb +0 -3
- data/lib/webgen/tag/date.rb +0 -2
- data/lib/webgen/tag/executecommand.rb +1 -2
- data/lib/webgen/tag/includefile.rb +1 -3
- data/lib/webgen/tag/langbar.rb +1 -4
- data/lib/webgen/tag/menu.rb +1 -4
- data/lib/webgen/tag/metainfo.rb +0 -2
- data/lib/webgen/tag/relocatable.rb +2 -3
- data/lib/webgen/tag/sitemap.rb +0 -3
- data/lib/webgen/tag/tikz.rb +117 -0
- data/lib/webgen/tag.rb +1 -0
- data/lib/webgen/tree.rb +9 -5
- data/test/test_common_sitemap.rb +4 -4
- data/test/test_contentprocessor_context.rb +1 -1
- data/test/test_contentprocessor_redcloth.rb +1 -0
- data/test/test_contentprocessor_tags.rb +1 -1
- data/test/test_node.rb +33 -13
- data/test/test_output_filesystem.rb +1 -1
- data/test/test_page.rb +13 -4
- data/test/test_path.rb +37 -5
- data/test/test_source_filesystem.rb +1 -1
- data/test/test_source_stacked.rb +1 -1
- data/test/test_sourcehandler_base.rb +30 -1
- data/test/test_sourcehandler_copy.rb +1 -1
- data/test/test_sourcehandler_directory.rb +16 -1
- data/test/test_sourcehandler_feed.rb +6 -7
- data/test/test_sourcehandler_fragment.rb +1 -1
- data/test/test_sourcehandler_memory.rb +42 -0
- data/test/test_sourcehandler_metainfo.rb +23 -21
- data/test/test_sourcehandler_page.rb +5 -7
- data/test/test_sourcehandler_template.rb +1 -1
- data/test/test_sourcehandler_virtual.rb +2 -2
- data/test/test_tag_base.rb +0 -1
- data/test/test_tag_breadcrumbtrail.rb +4 -4
- data/test/test_tag_includefile.rb +3 -3
- data/test/test_tag_langbar.rb +5 -6
- data/test/test_tag_menu.rb +7 -7
- data/test/test_tag_metainfo.rb +1 -1
- data/test/test_tag_relocatable.rb +1 -1
- data/test/test_tag_tikz.rb +66 -0
- data/test/test_tree.rb +2 -7
- metadata +7 -2
data/doc/extensions.page
CHANGED
@@ -6,7 +6,7 @@ title: Extensions
|
|
6
6
|
Following is a listing of all available extensions:
|
7
7
|
|
8
8
|
<%
|
9
|
-
pattern = /#{File.join(node.parent.absolute_lcn, '/')}(contentprocessor|output|source|sourcehandler|tag|)
|
9
|
+
pattern = /#{File.join(node.parent.absolute_lcn, '/')}(contentprocessor|output|source|sourcehandler|tag|)\/.*html$/
|
10
10
|
context.content_node.tree.node_access[:alcn].select {|alcn, n| alcn =~ pattern}.sort.each do |alcn, n|
|
11
11
|
next if n.is_fragment?
|
12
12
|
%>
|
@@ -659,6 +659,91 @@ files in Webgen Page Format.
|
|
659
659
|
<a href="\{relocatable: ../features.html}">Some Path</a>
|
660
660
|
|
661
661
|
|
662
|
+
* ### tag.tikz.path
|
663
|
+
|
664
|
+
The default mandatory configuration option for Tag::TikZ that specifies the (naturally
|
665
|
+
non-existing) source path that should be used for creating the TikZ image. The output path is
|
666
|
+
derived from this path the usual way. You shouldn't use a path that does already exist!
|
667
|
+
|
668
|
+
* Syntax: `PATH` where `PATH` is a relative or absolute source path.
|
669
|
+
|
670
|
+
* Examples:
|
671
|
+
|
672
|
+
\{tikz:: images/tikz.png}\tikz \draw (0,0) -- (0,2);{tikz}
|
673
|
+
|
674
|
+
|
675
|
+
* ### tag.tikz.libraries
|
676
|
+
|
677
|
+
Specifies the names of additional TikZ library names that should be used when creating the
|
678
|
+
image.
|
679
|
+
|
680
|
+
* Syntax: `[NAME, ...]` where `NAME` is the name of a TikZ library.
|
681
|
+
|
682
|
+
* Examples:
|
683
|
+
|
684
|
+
\{tikz:: {path: images/tikz.png, libraries: [mindmap, arrows]}}
|
685
|
+
\tikz \draw (0,0) -- (0,2) -- (2,2);
|
686
|
+
{tikz}
|
687
|
+
|
688
|
+
|
689
|
+
* ### tag.tikz.opts
|
690
|
+
|
691
|
+
Specifies additional global options for the `tikzpicture` environment.
|
692
|
+
|
693
|
+
* Syntax: `OPTS` where `OPTS` is the string with the global options.
|
694
|
+
|
695
|
+
* Examples:
|
696
|
+
|
697
|
+
\{tikz:: {path: images/tikz.png, opts: 'scale=3, line cap=round'}}
|
698
|
+
\tikz \draw (0,0) -- (0,2) -- (2,2);
|
699
|
+
{tikz}
|
700
|
+
|
701
|
+
|
702
|
+
* ### tag.tikz.resolution
|
703
|
+
|
704
|
+
Specifies the render and output resolutions that should be used to convert the TikZ image in PDF
|
705
|
+
format to the chosen image format. The first number specifies the render resolution and the
|
706
|
+
second one the output resolution. If the render resolution is higher than the output resolution,
|
707
|
+
the final image quality is better but the image needs to scaled down to the output resolution.
|
708
|
+
|
709
|
+
* Syntax: `RENDER_RES OUTPUT_RES` where `RENDER_RES` is the integer specifying the render
|
710
|
+
resolution and `OUTPUT_RES` is the integer specifying the output resolution.
|
711
|
+
|
712
|
+
* Examples:
|
713
|
+
|
714
|
+
\{tikz:: {path: images/tikz.png, resolution: 300 72}}
|
715
|
+
\tikz \draw (0,0) -- (0,2) -- (2,2);
|
716
|
+
{tikz}
|
717
|
+
|
718
|
+
|
719
|
+
* ### tag.tikz.transparent
|
720
|
+
|
721
|
+
Specifies whether the generated image should be transparent. This only works when the path
|
722
|
+
specified by `tag.tikz.path` option has the extension `.png`! You should probably also set the
|
723
|
+
background of the generated image tag to transparent.
|
724
|
+
|
725
|
+
* Syntax: `BOOLEAN` where `BOOLEAN` is either `true` or `false`.
|
726
|
+
|
727
|
+
* Examples:
|
728
|
+
|
729
|
+
\{tikz:: {path: images/tikz.png, transparent: true}}
|
730
|
+
\tikz \draw (0,0) -- (0,2) -- (2,2);
|
731
|
+
{tikz}
|
732
|
+
|
733
|
+
|
734
|
+
* ### tag.tikz.img\_attr
|
735
|
+
|
736
|
+
Specifies additional HTML attributes that should be set on the generated `img` tag.
|
737
|
+
|
738
|
+
* Syntax: `\{KEY:VALUE, ...}` where `KEY` is a valid HTML `img` tag attribute name and `VALUE`
|
739
|
+
the to-be-set value.
|
740
|
+
|
741
|
+
* Examples:
|
742
|
+
|
743
|
+
\{tikz:: {path: images/tikz.png, img_attr: {alt: Some TikZ picture}}}
|
744
|
+
\tikz \draw (0,0) -- (0,2) -- (2,2);
|
745
|
+
{tikz}
|
746
|
+
|
662
747
|
---
|
663
748
|
|
664
749
|
## Miscelleanous Configuration Options
|
data/doc/tag/tikz.page
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
---
|
2
|
+
title: Webgen::Tag::TikZ
|
3
|
+
used_options:
|
4
|
+
- tag.tikz.path
|
5
|
+
- tag.tikz.libraries
|
6
|
+
- tag.tikz.opts
|
7
|
+
- tag.tikz.resolution
|
8
|
+
- tag.tikz.transparent
|
9
|
+
- tag.tikz.img_attr
|
10
|
+
---
|
11
|
+
## Description
|
12
|
+
|
13
|
+
This tag provides support for automatically generating graphics with the fantastic PGF/TikZ library
|
14
|
+
for LaTeX. You will need to have a current LaTeX distribution with the PGF/TikZ library installed
|
15
|
+
and ImageMagick for this to work. You will also need Ghostscript if you want support for transparent
|
16
|
+
PNG images. More exactly, you will need to have the programs `pdflatex` (usually included in the
|
17
|
+
LaTeX distribution - for generating a PDF from the LaTeX document that describes the PGF/TikZ
|
18
|
+
graphic), `pdfcrop` (usually included in the LaTeX distribution - to crop the generated PDF and
|
19
|
+
throw away useless borders), `convert` (provided by ImageMagick - to convert the generated PDF
|
20
|
+
document to an image file format and to optionally resize them) and `gs` (provided by the
|
21
|
+
Ghostscript package - to generate transparent PNG images).
|
22
|
+
|
23
|
+
When using this tag, you need to set at least the default mandatory parameter `tag.tikz.path`. This
|
24
|
+
path specifies the source path that should be used for generating the image and should not
|
25
|
+
exist. The output path is dervied from this path the usual way. The extension used for this
|
26
|
+
parameter specifies the final image format that is used (a good choice is PNG). All other parameters
|
27
|
+
are optional. The commands for creating the PGF/TikZ picture are specified in the body of the
|
28
|
+
tag. Have a look at some of the examples below to set the power of PGF/TikZ.
|
29
|
+
|
30
|
+
If you want to generate transparent images, you will need to set `tag.tikz.transparent` to `true`
|
31
|
+
and specify a `tag.tikz.path` with a `.png` extension.
|
32
|
+
|
33
|
+
## Examples
|
34
|
+
|
35
|
+
These examples are taken (sometimes a little bit altered) from the great PGF Manual included in the
|
36
|
+
PGF/TikZ distribution.
|
37
|
+
|
38
|
+
<table class="examples">
|
39
|
+
<tr>
|
40
|
+
<th>Usage</th><th>Output</th>
|
41
|
+
</tr>
|
42
|
+
|
43
|
+
<tr>
|
44
|
+
<td>
|
45
|
+
<pre>
|
46
|
+
\{tikz:: house.png}
|
47
|
+
\tikz \draw[thick,rounded corners=8pt]
|
48
|
+
(0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
|
49
|
+
{tikz}
|
50
|
+
</pre>
|
51
|
+
</td>
|
52
|
+
<td>
|
53
|
+
{tikz:: house.png}
|
54
|
+
\tikz \draw[thick,rounded corners=8pt]
|
55
|
+
(0,0) -- (0,2) -- (1,3.25) -- (2,2) -- (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
|
56
|
+
{tikz}
|
57
|
+
</td>
|
58
|
+
</tr>
|
59
|
+
|
60
|
+
<tr>
|
61
|
+
<td>
|
62
|
+
<pre>
|
63
|
+
\{tikz:: {path: chain.png, libraries: [arrows,automata,shadows,positioning],
|
64
|
+
opts: "->,>=stealth,shorten >=1pt,auto,node distance=2.8cm,on grid,semithick,
|
65
|
+
every state/.style={fill=red,draw=none,circular drop shadow,text=white}",
|
66
|
+
resolution: 300 72}}
|
67
|
+
\node[initial,state] (A) {$q_a$};
|
68
|
+
\node[state] (B) [above right=of A] {$q_b$};
|
69
|
+
\node[state] (D) [below right=of A] {$q_d$};
|
70
|
+
\node[state] (C) [below right=of B] {$q_c$};
|
71
|
+
\node[state] (E) [below=of D] {$q_e$};
|
72
|
+
\path (A) edge node {0,1,L} (B)
|
73
|
+
edge node {1,1,R} (C)
|
74
|
+
(B) edge [loop above] node {1,1,L} (B)
|
75
|
+
edge node {0,1,L} (C)
|
76
|
+
(C) edge node {0,1,L} (D)
|
77
|
+
edge [bend left] node {1,0,R} (E)
|
78
|
+
(D) edge [loop below] node {1,1,R} (D)
|
79
|
+
edge node {0,1,R} (A)
|
80
|
+
(E) edge [bend left] node {1,0,R} (A);
|
81
|
+
{tikz}
|
82
|
+
</pre>
|
83
|
+
</td>
|
84
|
+
<td>
|
85
|
+
{tikz:: {path: chain.png, libraries: [arrows,automata,shadows,positioning],
|
86
|
+
opts: "->,>=stealth,shorten >=1pt,auto,node distance=2.8cm,on grid,semithick,
|
87
|
+
every state/.style={fill=red,draw=none,circular drop shadow,text=white}"}}
|
88
|
+
\node[initial,state] (A) {$q_a$};
|
89
|
+
\node[state] (B) [above right=of A] {$q_b$};
|
90
|
+
\node[state] (D) [below right=of A] {$q_d$};
|
91
|
+
\node[state] (C) [below right=of B] {$q_c$};
|
92
|
+
\node[state] (E) [below=of D] {$q_e$};
|
93
|
+
\path (A) edge node {0,1,L} (B)
|
94
|
+
edge node {1,1,R} (C)
|
95
|
+
(B) edge [loop above] node {1,1,L} (B)
|
96
|
+
edge node {0,1,L} (C)
|
97
|
+
(C) edge node {0,1,L} (D)
|
98
|
+
edge [bend left] node {1,0,R} (E)
|
99
|
+
(D) edge [loop below] node {1,1,R} (D)
|
100
|
+
edge node {0,1,R} (A)
|
101
|
+
(E) edge [bend left] node {1,0,R} (A);
|
102
|
+
{tikz}
|
103
|
+
</td>
|
104
|
+
</tr>
|
105
|
+
|
106
|
+
<tr>
|
107
|
+
<td>
|
108
|
+
Not transparent and standard res
|
109
|
+
<pre>
|
110
|
+
\{tikz:: {path: mindmap.png, libraries: [mindmap]}}
|
111
|
+
\path[mindmap,concept color=black,text=white]
|
112
|
+
node[concept] {Computer Science}
|
113
|
+
[clockwise from=0]
|
114
|
+
child[concept color=red] { node[concept] {technical} }
|
115
|
+
child[concept color=orange] { node[concept] {theoretical} };
|
116
|
+
{tikz}
|
117
|
+
</pre>
|
118
|
+
</td>
|
119
|
+
<td>
|
120
|
+
{tikz:: {path: mindmap.png, libraries: [mindmap]}}
|
121
|
+
\path[mindmap,concept color=black,text=white]
|
122
|
+
node[concept] {Computer Science}
|
123
|
+
[clockwise from=0]
|
124
|
+
child[concept color=red] { node[concept] {technical} }
|
125
|
+
child[concept color=orange] { node[concept] {theoretical} };
|
126
|
+
{tikz}
|
127
|
+
</td>
|
128
|
+
</tr>
|
129
|
+
|
130
|
+
<tr>
|
131
|
+
<td>
|
132
|
+
Transparent and high res
|
133
|
+
<pre>
|
134
|
+
\{tikz:: {path: mindmap-low.png, libraries: [mindmap],
|
135
|
+
img_attr: {style: 'background:transparent'},
|
136
|
+
transparent: true, resolution: 300 72}}
|
137
|
+
\path[mindmap,concept color=black,text=white]
|
138
|
+
node[concept] {Computer Science}
|
139
|
+
[clockwise from=0]
|
140
|
+
child[concept color=red] { node[concept] {technical} }
|
141
|
+
child[concept color=orange] { node[concept] {theoretical} };
|
142
|
+
{tikz}
|
143
|
+
</pre>
|
144
|
+
</td>
|
145
|
+
<td>
|
146
|
+
{tikz:: {path: mindmap-high.png, libraries: [mindmap],
|
147
|
+
img_attr: {style: 'background:transparent'},
|
148
|
+
transparent: true, resolution: 300 72}}
|
149
|
+
\path[mindmap,concept color=black,text=white]
|
150
|
+
node[concept] {Computer Science}
|
151
|
+
[clockwise from=0]
|
152
|
+
child[concept color=red] { node[concept] {technical} }
|
153
|
+
child[concept color=orange] { node[concept] {theoretical} };
|
154
|
+
{tikz}
|
155
|
+
</td>
|
156
|
+
</tr>
|
157
|
+
|
158
|
+
</table>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'webgen/tag
|
1
|
+
require 'webgen/tag'
|
2
2
|
require 'webgen/websiteaccess'
|
3
3
|
|
4
4
|
module Webgen::Common
|
@@ -64,13 +64,12 @@ module Webgen::Common
|
|
64
64
|
(tree.flatten.any? do |alcn|
|
65
65
|
(n = node.tree[alcn]) && (r = n.routing_node(lang)) && r.meta_info_changed?
|
66
66
|
end)
|
67
|
-
node.dirty
|
67
|
+
node.flag(:dirty)
|
68
68
|
break
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
73
|
end
|
75
74
|
|
76
75
|
end
|
@@ -54,7 +54,7 @@ config.sourcehandler.patterns({
|
|
54
54
|
'Webgen::SourceHandler::Sitemap' => ['**/*.sitemap']
|
55
55
|
}, :doc => 'Source handler to path pattern map')
|
56
56
|
config.sourcehandler.invoke({
|
57
|
-
1 => ['Webgen::SourceHandler::Directory', 'Webgen::SourceHandler::Metainfo'
|
57
|
+
1 => ['Webgen::SourceHandler::Directory', 'Webgen::SourceHandler::Metainfo'],
|
58
58
|
5 => ['Webgen::SourceHandler::Copy', 'Webgen::SourceHandler::Template',
|
59
59
|
'Webgen::SourceHandler::Page', 'Webgen::SourceHandler::Feed',
|
60
60
|
'Webgen::SourceHandler::Sitemap'],
|
@@ -148,6 +148,7 @@ config.contentprocessor.tags.map({
|
|
148
148
|
'coderay' => 'Webgen::Tag::Coderay',
|
149
149
|
'date' => 'Webgen::Tag::Date',
|
150
150
|
'sitemap' => 'Webgen::Tag::Sitemap',
|
151
|
+
'tikz' => 'Webgen::Tag::TikZ',
|
151
152
|
:default => 'Webgen::Tag::Metainfo'
|
152
153
|
}, :doc => 'Tag processor name to class map')
|
153
154
|
|
@@ -190,6 +191,12 @@ config.tag.coderay.tab_width(8, :doc => 'Number of spaces used for a tabulator')
|
|
190
191
|
|
191
192
|
config.tag.date.format('%Y-%m-%d %H:%M:%S', :doc => 'The format of the date (same options as Ruby\'s Time#strftime)')
|
192
193
|
|
194
|
+
config.tag.tikz.path(nil, :doc => 'The source path of the created image', :mandatory => 'default')
|
195
|
+
config.tag.tikz.libraries(nil, :doc => 'An array of additional TikZ library names')
|
196
|
+
config.tag.tikz.opts(nil, :doc => 'A string with global options for the tikzpicture environment')
|
197
|
+
config.tag.tikz.resolution('72 72', :doc => 'A string specifying the render and output resolutions')
|
198
|
+
config.tag.tikz.transparent(false, :doc => 'Specifies whether the generated image should be transparent (only png)')
|
199
|
+
config.tag.tikz.img_attr({}, :doc => 'A hash of additional HTML attributes for the created img tag')
|
193
200
|
|
194
201
|
# All things regarding common functionality
|
195
202
|
website.autoload_service(:create_sitemap, 'Webgen::Common::Sitemap')
|
data/lib/webgen/node.rb
CHANGED
@@ -46,17 +46,6 @@ module Webgen
|
|
46
46
|
# Meta information associated with the node.
|
47
47
|
attr_reader :meta_info
|
48
48
|
|
49
|
-
# Set by other objects to +true+ if they think the object has changed since the last run. Must
|
50
|
-
# not be set to +false+ once it is +true+!
|
51
|
-
attr_accessor :dirty
|
52
|
-
|
53
|
-
# Set by other objects to +true+ if the meta information of the node has changed since the last
|
54
|
-
# run. Must not be set to +false+ once it is +true+!
|
55
|
-
attr_accessor :dirty_meta_info
|
56
|
-
|
57
|
-
# Has the node been created or has it been read from the cache?
|
58
|
-
attr_accessor :created
|
59
|
-
|
60
49
|
# Create a new Node instance.
|
61
50
|
#
|
62
51
|
# +parent+ (immutable)::
|
@@ -78,15 +67,27 @@ module Webgen
|
|
78
67
|
# found, the node is language neutral.
|
79
68
|
def initialize(parent, path, cn, meta_info = {})
|
80
69
|
@parent = parent
|
81
|
-
@path = path.freeze
|
82
70
|
@cn = cn.chomp('/').freeze
|
71
|
+
@children = []
|
72
|
+
reinit(path, meta_info)
|
73
|
+
init_rest
|
74
|
+
end
|
75
|
+
|
76
|
+
# Re-initializes an already initialized node and resets it to its pristine state.
|
77
|
+
def reinit(path, meta_info = {})
|
78
|
+
old_path = @path
|
79
|
+
@path = path.freeze
|
83
80
|
@lang = meta_info.delete('lang').freeze
|
84
81
|
@lang = nil unless is_file?
|
85
82
|
@meta_info = meta_info
|
86
|
-
@
|
87
|
-
@
|
88
|
-
|
89
|
-
|
83
|
+
@flags = Set.new([:dirty, :created])
|
84
|
+
if @tree
|
85
|
+
@tree.node_access[:path].delete(old_path) if old_path
|
86
|
+
@tree.register_path(self)
|
87
|
+
self.node_info.clear
|
88
|
+
self.node_info[:used_nodes] = Set.new
|
89
|
+
self.node_info[:used_meta_info_nodes] = Set.new
|
90
|
+
end
|
90
91
|
end
|
91
92
|
|
92
93
|
# Return the meta information item for +key+.
|
@@ -116,26 +117,50 @@ module Webgen
|
|
116
117
|
# Check if the node is the root node.
|
117
118
|
def is_root?; self == tree.root; end
|
118
119
|
|
120
|
+
# Check if the node is flagged with one of the following:
|
121
|
+
#
|
122
|
+
# :created:: Has the node been created or has it been read from the cache?
|
123
|
+
# :reinit:: Does the node need to be reinitialized?
|
124
|
+
# :dirty:: Set by other objects to +true+ if they think the object has changed since the last
|
125
|
+
# run. Must not be set to +false+ once it is +true+!
|
126
|
+
# :dirty_meta_info:: Set by other objects to +true+ if the meta information of the node has
|
127
|
+
# changed since the last run. Must not be set to +false+ once it is +true+!
|
128
|
+
def flagged(key)
|
129
|
+
@flags.include?(key)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Flag the node with the +keys+. See #flagged for valid keys.
|
133
|
+
def flag(*keys)
|
134
|
+
@flags += keys
|
135
|
+
website.blackboard.dispatch_msg(:node_flagged, self, keys)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Remove the flags +keys+ from the node.
|
139
|
+
def unflag(*keys)
|
140
|
+
@flags.subtract(keys)
|
141
|
+
website.blackboard.dispatch_msg(:node_unflagged, self, keys)
|
142
|
+
end
|
143
|
+
|
119
144
|
# Return +true+ if the node has changed since the last webgen run. If it has changed, +dirty+ is
|
120
145
|
# set to +true+.
|
121
146
|
def changed?
|
122
147
|
if_not_checked(:node) do
|
123
|
-
|
124
|
-
|
125
|
-
website.blackboard.dispatch_msg(:node_changed?, self) unless
|
148
|
+
flag(:dirty) if meta_info_changed? ||
|
149
|
+
node_info[:used_nodes].any? {|n| n != @absolute_lcn && (!tree[n] || tree[n].changed?)}
|
150
|
+
website.blackboard.dispatch_msg(:node_changed?, self) unless flagged(:dirty)
|
126
151
|
end
|
127
|
-
|
152
|
+
flagged(:dirty)
|
128
153
|
end
|
129
154
|
|
130
155
|
# Return +true+ if the meta information of the node has changed.
|
131
156
|
def meta_info_changed?
|
132
157
|
if_not_checked(:meta_info) do
|
133
|
-
|
158
|
+
flag(:dirty_meta_info) if node_info[:used_meta_info_nodes].any? do |n|
|
134
159
|
n != @absolute_lcn && (!tree[n] || tree[n].meta_info_changed?)
|
135
|
-
end
|
136
|
-
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless
|
160
|
+
end
|
161
|
+
website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged(:dirty_meta_info)
|
137
162
|
end
|
138
|
-
|
163
|
+
flagged(:dirty_meta_info)
|
139
164
|
end
|
140
165
|
|
141
166
|
# Return an informative representation of the node.
|
data/lib/webgen/page.rb
CHANGED
@@ -55,14 +55,17 @@ module Webgen
|
|
55
55
|
# the information. The +meta_info+ parameter can be used to provide default meta information.
|
56
56
|
def from_data(data, meta_info = {})
|
57
57
|
md = /(#{RE_META_INFO})?(.*)/m.match(normalize_eol(data))
|
58
|
-
|
59
|
-
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
60
|
-
end
|
61
|
-
meta_info = meta_info.merge(md[1].nil? ? {} : parse_meta_info(md[1]))
|
58
|
+
meta_info = meta_info.merge(parse_meta_info(md[1], data))
|
62
59
|
blocks = parse_blocks(md[2] || '', meta_info)
|
63
60
|
new(meta_info, blocks)
|
64
61
|
end
|
65
62
|
|
63
|
+
# Parse the given string +data+ in Webgen Page Format and return the found meta information.
|
64
|
+
def meta_info_from_data(data)
|
65
|
+
md = /(#{RE_META_INFO})?/m.match(normalize_eol(data))
|
66
|
+
parse_meta_info(md[1], data)
|
67
|
+
end
|
68
|
+
|
66
69
|
#######
|
67
70
|
private
|
68
71
|
#######
|
@@ -72,17 +75,24 @@ module Webgen
|
|
72
75
|
data.gsub(/\r\n?/, "\n")
|
73
76
|
end
|
74
77
|
|
75
|
-
# Parse the meta info string +
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
# Parse the meta info string in +mi_data+ and return the hash with the meta information. The
|
79
|
+
# original +data+ is used for checking the validness of the meta information block.
|
80
|
+
def parse_meta_info(mi_data, data)
|
81
|
+
if mi_data.nil? && data =~ RE_META_INFO_START
|
82
|
+
raise WebgenPageFormatError, 'Found start line for meta information block but no valid meta information block'
|
83
|
+
elsif mi_data.nil?
|
84
|
+
{}
|
85
|
+
else
|
86
|
+
begin
|
87
|
+
meta_info = YAML::load(mi_data.to_s)
|
88
|
+
unless meta_info.kind_of?(Hash)
|
89
|
+
raise WebgenPageFormatError, "Invalid structure of meta information block: expected YAML hash but found #{meta_info.class}"
|
90
|
+
end
|
91
|
+
rescue ArgumentError => e
|
92
|
+
raise WebgenPageFormatError, e.message
|
81
93
|
end
|
82
|
-
|
83
|
-
raise WebgenPageFormatError, e.message
|
94
|
+
meta_info
|
84
95
|
end
|
85
|
-
meta_info
|
86
96
|
end
|
87
97
|
|
88
98
|
# Parse all blocks in +data+ and return them. Meta information can be provided in +meta_info+
|
@@ -118,12 +128,12 @@ module Webgen
|
|
118
128
|
# The contents of the meta information block.
|
119
129
|
attr_reader :meta_info
|
120
130
|
|
121
|
-
# The
|
131
|
+
# The hash of blocks for the page.
|
122
132
|
attr_reader :blocks
|
123
133
|
|
124
134
|
# Create a new Page object with the meta information provided in +meta_info+ and the given
|
125
135
|
# +blocks+.
|
126
|
-
def initialize(meta_info = {}, blocks =
|
136
|
+
def initialize(meta_info = {}, blocks = {})
|
127
137
|
@meta_info = meta_info
|
128
138
|
@blocks = blocks
|
129
139
|
end
|
data/lib/webgen/path.rb
CHANGED
@@ -35,11 +35,24 @@ module Webgen
|
|
35
35
|
end
|
36
36
|
|
37
37
|
|
38
|
+
# Return +true+ if the given +path+ matches the given +pattern+ (trailing slashes of directories
|
39
|
+
# are not respected). For information on which patterns are supported, have a look at the
|
40
|
+
# documentation of File.fnmatch.
|
41
|
+
def self.match(path, pattern)
|
42
|
+
path = path.to_s.chomp('/') unless path == '/'
|
43
|
+
pattern = pattern.to_s.chomp('/') unless pattern == '/'
|
44
|
+
File.fnmatch(pattern, path, File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
38
48
|
include Comparable
|
39
49
|
|
40
|
-
# The full
|
50
|
+
# The full path.
|
41
51
|
attr_accessor :path
|
42
52
|
|
53
|
+
# The source path that lead to the creation of this path.
|
54
|
+
attr_accessor :source_path
|
55
|
+
|
43
56
|
# The basename part of the path.
|
44
57
|
attr_accessor :basename
|
45
58
|
|
@@ -55,11 +68,13 @@ module Webgen
|
|
55
68
|
# Extracted meta information for the path.
|
56
69
|
attr_accessor :meta_info
|
57
70
|
|
58
|
-
# Create a new Path object for +path+. The optional
|
59
|
-
#
|
60
|
-
|
71
|
+
# Create a new Path object for +path+. The optional +source_path+ parameter specifies the path
|
72
|
+
# that lead to the creation of this path. The optional block needs to return an IO object for
|
73
|
+
# the content of the path.
|
74
|
+
def initialize(path, source_path = path, &ioblock)
|
61
75
|
@meta_info = {}
|
62
76
|
@io = SourceIO.new(&ioblock) if block_given?
|
77
|
+
@source_path = source_path
|
63
78
|
analyse(path)
|
64
79
|
end
|
65
80
|
|
@@ -70,6 +85,7 @@ module Webgen
|
|
70
85
|
temp.path = temp.path.sub(/^#{Regexp.escape(prefix.chomp("/"))}/, '') if prefix #"
|
71
86
|
reanalyse = (@path == '/' || temp.path == '/')
|
72
87
|
temp.path = File.join(mp, temp.path)
|
88
|
+
temp.source_path = temp.path if @path == @source_path
|
73
89
|
if reanalyse
|
74
90
|
temp.send(:analyse, temp.path)
|
75
91
|
else
|
@@ -131,12 +147,6 @@ module Webgen
|
|
131
147
|
end
|
132
148
|
alias_method(:eql?, :==)
|
133
149
|
|
134
|
-
# Return +true+ if the localized path matches the given +pattern+. For information on which
|
135
|
-
# patterns are supported, have a look at the documentation of File.fnmatch.
|
136
|
-
def =~(pattern)
|
137
|
-
File.fnmatch(pattern, File.join(@directory, lcn), File::FNM_DOTMATCH|File::FNM_CASEFOLD|File::FNM_PATHNAME)
|
138
|
-
end
|
139
|
-
|
140
150
|
# Implemented sothat a Path looks like a String when used as key in a hash.
|
141
151
|
def <=>(other)
|
142
152
|
@path <=> other.to_str
|
@@ -42,9 +42,18 @@ module Webgen::SourceHandler
|
|
42
42
|
# <tt>node_info[:processor]</tt>:: Has to be set to the class name of the source handler. This is
|
43
43
|
# used by the Node class: all unknown method calls are forwarded
|
44
44
|
# to the node processor.
|
45
|
-
# <tt>node_info[:src]</tt>:: Has to be set to the string version of the
|
45
|
+
# <tt>node_info[:src]</tt>:: Has to be set to the string version of the path that lead to the
|
46
|
+
# creation of the node.
|
47
|
+
# <tt>node_info[:creation_path]</tt>:: Has to be set to the string version of the path that is
|
48
|
+
# used to create the path.
|
46
49
|
# <tt>meta_info['no_output']</tt>:: Has to be set to +true+ on nodes that are used during a
|
47
50
|
# webgen run but do not produce an output file.
|
51
|
+
# <tt>meta_info['modified_at']</tt>:: Is automatically set to the current time if not already set
|
52
|
+
# correctly (ie. if not a Time object).
|
53
|
+
#
|
54
|
+
# Note: The difference between +:src+ and +:creation_path+ is that a creation path need not have
|
55
|
+
# an existing source path representation. For example, fragments created from a page source path
|
56
|
+
# have a different +:creation_path+ which includes the fragment part.
|
48
57
|
#
|
49
58
|
# Additional information that is used only for processing purposes should be stored in the
|
50
59
|
# #node_info hash of a node as the #meta_info hash is reserved for real node meta information and
|
@@ -55,7 +64,8 @@ module Webgen::SourceHandler
|
|
55
64
|
# Path patterns define which paths are handled by a specific source handler. These patterns are
|
56
65
|
# specified in the <tt>sourcehandler.patterns</tt> configuration hash as a mapping from the source
|
57
66
|
# handler class name to an array of path patterns. The patterns need to have a format that
|
58
|
-
# <tt>Dir.glob</tt> can handle.
|
67
|
+
# <tt>Dir.glob</tt> can handle. You can use the configuration helper +patterns+ to set this (is
|
68
|
+
# shown in the example below).
|
59
69
|
#
|
60
70
|
# Specifying a path pattern does not mean that webgen uses the source handler. One also needs to
|
61
71
|
# provide an entry in the configuration value <tt>sourcehandler.invoke</tt>. This is a hash that
|
@@ -97,7 +107,7 @@ module Webgen::SourceHandler
|
|
97
107
|
#
|
98
108
|
# end
|
99
109
|
#
|
100
|
-
# WebsiteAccess.website.config.
|
110
|
+
# WebsiteAccess.website.config.patterns('SimpleCopy' => ['**/*.jpg', '**/*.png'])
|
101
111
|
# WebsiteAccess.website.config.sourcehandler.invoke[5] << 'SimpleCopy'
|
102
112
|
#
|
103
113
|
module Base
|
@@ -156,7 +166,9 @@ module Webgen::SourceHandler
|
|
156
166
|
if OutputPathHelpers.public_instance_methods(false).include?(method)
|
157
167
|
name = send(method, parent, path, use_lang_part)
|
158
168
|
name += '/' if path.path =~ /\/$/ && name !~ /\/$/
|
159
|
-
if node_exists?(parent, path, name)
|
169
|
+
if (node = node_exists?(parent, path, name)) && node.lang == path.meta_info['lang']
|
170
|
+
name = node.path
|
171
|
+
elsif node
|
160
172
|
name = send(method, parent, path, (path.meta_info['lang'].nil? ? false : true))
|
161
173
|
name += '/' if path.path =~ /\/$/ && name !~ /\/$/
|
162
174
|
end
|
@@ -172,21 +184,31 @@ module Webgen::SourceHandler
|
|
172
184
|
parent.tree[Webgen::Node.absolute_name(parent, path.lcn, :alcn)] || (!path.meta_info['no_output'] && parent.tree[output_path, :path])
|
173
185
|
end
|
174
186
|
|
175
|
-
# Create
|
187
|
+
# Create a node under +parent+ from +path+ if it does not already exists or needs to be
|
188
|
+
# re-initialized. The found node or the newly created node is returned afterwards. +nil+ is
|
189
|
+
# returned if no node can be created (e.g. when <tt>path.meta_info['draft']</tt> is set). Some
|
176
190
|
# additional node information like <tt>:src</tt> and <tt>:processor</tt> is set and the meta
|
177
|
-
# information is checked for validness. The created node is yielded if a block is
|
191
|
+
# information is checked for validness. The created/re-initialized node is yielded if a block is
|
192
|
+
# given.
|
178
193
|
def create_node(parent, path, output_path = self.output_path(parent, path))
|
179
|
-
return if path.meta_info['draft']
|
180
|
-
|
194
|
+
return nil if path.meta_info['draft']
|
195
|
+
node = node_exists?(parent, path, output_path)
|
196
|
+
if node && (node.node_info[:src] != path.source_path || node.node_info[:processor] != self.class.name)
|
197
|
+
log(:warn) { "Node already exists: source = #{path.source_path} | path = #{node.path} | alcn = #{node.absolute_lcn}"}
|
198
|
+
return node
|
199
|
+
elsif !node
|
181
200
|
node = Webgen::Node.new(parent, output_path, path.cn, path.meta_info)
|
182
|
-
|
183
|
-
node.
|
184
|
-
node.node_info[:processor] = self.class.name
|
185
|
-
yield(node) if block_given?
|
186
|
-
node
|
201
|
+
elsif node.flagged(:reinit)
|
202
|
+
node.reinit(output_path, path.meta_info)
|
187
203
|
else
|
188
|
-
|
204
|
+
return node
|
189
205
|
end
|
206
|
+
node['modified_at'] = Time.now unless node['modified_at'].kind_of?(Time)
|
207
|
+
node.node_info[:src] = path.source_path
|
208
|
+
node.node_info[:creation_path] = path.path
|
209
|
+
node.node_info[:processor] = self.class.name
|
210
|
+
yield(node) if block_given?
|
211
|
+
node
|
190
212
|
end
|
191
213
|
|
192
214
|
# Return the content of the given +node+. This default +content+ method just returns +nil+.
|