kodekopelli 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/LICENSE +32 -0
- data/README +78 -0
- data/Rakefile +87 -0
- data/bin/kodekopelli +5 -0
- data/examples/faqomatic/config.xml +40 -0
- data/examples/faqomatic/content.rhtml +376 -0
- data/examples/faqomatic/generated/README.txt +1 -0
- data/examples/faqomatic/includes/shampoo_answer.txt +1 -0
- data/examples/faqomatic/templates/faqs.txt +22 -0
- data/examples/faqomatic/templates/great_big.txt +3 -0
- data/examples/faqomatic/templates/html_wrapper.txt +9 -0
- data/examples/thankyounotes/config.xml +18 -0
- data/examples/thankyounotes/content.rhtml +528 -0
- data/examples/thankyounotes/generated/README.txt +1 -0
- data/examples/thankyounotes/includes/poem.txt +3 -0
- data/examples/thankyounotes/templates/thanks.txt +14 -0
- data/examples/treemenu/config.xml +110 -0
- data/examples/treemenu/content.rhtml +324 -0
- data/examples/treemenu/generated/README.txt +1 -0
- data/examples/treemenu/templates/authorized.txt +1 -0
- data/examples/treemenu/templates/menu_category.txt +4 -0
- data/examples/treemenu/templates/menu_item.txt +3 -0
- data/examples/treemenu/templates/simple_menu.txt +3 -0
- data/lib/kodekopelli.rb +56 -0
- data/lib/kodekopelli/expandable_properties.rb +63 -0
- data/lib/kodekopelli/file_generator.rb +726 -0
- data/lib/kodekopelli/frozen_key_hash.rb +67 -0
- data/lib/kodekopelli/minimal_logger.rb +50 -0
- data/lib/kodekopelli/properties_file.rb +41 -0
- data/lib/kodekopelli/util.rb +30 -0
- data/rakefile +87 -0
- data/test/abstract_unit.rb +4 -0
- data/test/fixtures/definitions/invalid/empty +0 -0
- data/test/fixtures/definitions/invalid/gibberish.txt +6 -0
- data/test/fixtures/definitions/kodekopelli.xsd +95 -0
- data/test/fixtures/definitions/valid/empty_files.xml +49 -0
- data/test/fixtures/definitions/valid/kodekopelli_rocks_files.xml +359 -0
- data/test/fixtures/definitions/valid/simplest.xml +8 -0
- data/test/fixtures/includes/bang.txt +1 -0
- data/test/fixtures/includes/c.txt +1 -0
- data/test/fixtures/includes/d.txt +1 -0
- data/test/fixtures/includes/e.txt +1 -0
- data/test/fixtures/includes/empty.txt +0 -0
- data/test/fixtures/includes/i.txt +1 -0
- data/test/fixtures/includes/k.txt +1 -0
- data/test/fixtures/includes/k_upper.txt +1 -0
- data/test/fixtures/includes/kodekopelli_rocks.txt +1 -0
- data/test/fixtures/includes/l.txt +1 -0
- data/test/fixtures/includes/o.txt +1 -0
- data/test/fixtures/includes/p.txt +1 -0
- data/test/fixtures/includes/r.txt +1 -0
- data/test/fixtures/includes/s.txt +1 -0
- data/test/fixtures/includes/space.txt +1 -0
- data/test/fixtures/properties/comments.properties +17 -0
- data/test/fixtures/properties/empty.properties +0 -0
- data/test/fixtures/properties/expandable.properties +2 -0
- data/test/fixtures/properties/none_valid.properties +1 -0
- data/test/fixtures/properties/simple.properties +5 -0
- data/test/fixtures/templates/anything_att.txt +1 -0
- data/test/fixtures/templates/anything_att_prop.txt +1 -0
- data/test/fixtures/templates/anything_prop.txt +1 -0
- data/test/fixtures/templates/anything_prop_att.txt +1 -0
- data/test/fixtures/templates/blank.txt +0 -0
- data/test/fixtures/templates/child_output.txt +1 -0
- data/test/fixtures/templates/kodekopelli_blanks +1 -0
- data/test/tc_expandable_properties.rb +106 -0
- data/test/tc_file_generator.rb +20 -0
- data/test/tc_frozen_key_hash.rb +34 -0
- data/test/tc_properties_file.rb +52 -0
- data/test/tc_util.rb +55 -0
- data/test/ts_all_tests.rb +9 -0
- data/test/ts_functional.rb +86 -0
- metadata +133 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
COPYRIGHT AND PERMISSION NOTICE
|
2
|
+
|
3
|
+
Copyright (c) 2005 Free Range Data LLC
|
4
|
+
|
5
|
+
All rights reserved.
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
8
|
+
copy of this software and associated documentation files (the
|
9
|
+
"Software"), to deal in the Software without restriction, including
|
10
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
11
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
12
|
+
permit persons to whom the Software is furnished to do so, subject to
|
13
|
+
the following conditions:
|
14
|
+
|
15
|
+
The above copyright notice and this permission notice shall be included
|
16
|
+
in all copies or substantial portions of the Software.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
19
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
20
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
21
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
22
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
23
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
24
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
Except as contained in this notice, the name of a copyright holder shall
|
27
|
+
not be used in advertising or otherwise to promote the sale, use or other
|
28
|
+
dealings in this Software without prior written authorization of the
|
29
|
+
copyright holder.
|
30
|
+
|
31
|
+
Kodekopelli and the Kodekopelli logo are trademarks of
|
32
|
+
Free Range Data.
|
data/README
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
K
|
2
|
+
ODE KO
|
3
|
+
PEL LI K
|
4
|
+
ODEKOP EL LI KO
|
5
|
+
DEK O PE LL
|
6
|
+
IK OD EK OP
|
7
|
+
ELLIKODE KO PELL IK
|
8
|
+
O DEK OPELLIK ODE
|
9
|
+
KOPELLIKODEK
|
10
|
+
OPELLIKODEK
|
11
|
+
OPELLIKODEKOPELLIKOD
|
12
|
+
EKOPELLIKODEKOPELLIKOD
|
13
|
+
EKOPELLIKODE KOPELLIKOD
|
14
|
+
EKOPELLIKODEK OPELLI
|
15
|
+
KODEKOPELLIKOD EK
|
16
|
+
OPELLIKODEKOPELL IKO
|
17
|
+
DEKOPELLIKODEKOPE LLI
|
18
|
+
KODEPELLIKODE KOPELLIKODE
|
19
|
+
KOPELLIKODEKOPEL LI
|
20
|
+
KODEKOPE LLIKODEKOPELLIK
|
21
|
+
ODEKOPELL IK
|
22
|
+
ODEKOPELL IK
|
23
|
+
ODEKOPELLI KOD
|
24
|
+
EKOPELLIKODE KO
|
25
|
+
PELLIKODEKOPELLIK OD
|
26
|
+
EKOPELLIKODEKOPEL
|
27
|
+
LIKODEKOPEL LI
|
28
|
+
KODEKOP ELLIKOD
|
29
|
+
EKOPE LLIKO
|
30
|
+
DEK
|
31
|
+
OPELL TM
|
32
|
+
IKODEKOP
|
33
|
+
ELLIKOD
|
34
|
+
|
35
|
+
Kodekopelli -- making code generation rock since 2003. Do it well.
|
36
|
+
Do it once. Let Kodekopelli do the rest.
|
37
|
+
|
38
|
+
Kodekopelli is an unobtrusive, unassuming code generator that leverages the
|
39
|
+
expressiveness of the Ruby language and the ERB lightweight templating system
|
40
|
+
to help facilitate the Don't Repeat Yourself (DRY) Principle in a manner
|
41
|
+
consistent with agile development practices. That means playing well in an
|
42
|
+
environment of continuous integration and utilizing idioms familiar
|
43
|
+
(or, at least, intuitive) to users of automated build systems like Ant,
|
44
|
+
NAnt and Rake. Kodekopelli provides an additional layer of abstraction
|
45
|
+
between the creative thought and real engineering work in which humans
|
46
|
+
excel and the drudgery of those tedious tasks better left to computers.
|
47
|
+
All too often, said tedium steals valuable time from the lives of developers
|
48
|
+
who accept those burdens as badges of honor or as inevitable occupational hazards.
|
49
|
+
|
50
|
+
== License
|
51
|
+
|
52
|
+
Kodekopelli is released under the business-friendly MIT license.
|
53
|
+
|
54
|
+
== _Legalese_
|
55
|
+
|
56
|
+
The Kodekopelli logo and the Kodekopelli name are trademarks of Free Range Data LLC.
|
57
|
+
|
58
|
+
== Additional Documentation
|
59
|
+
|
60
|
+
Additional documentation, including a usage manual, may be found at the
|
61
|
+
Kodekopelli site[http://www.kodekopelli.org].
|
62
|
+
|
63
|
+
== Examples
|
64
|
+
|
65
|
+
Numerous examples may be found both in the /examples folder
|
66
|
+
of this distribution and on the
|
67
|
+
Kodekopelli site[http://www.kodekopelli.org].
|
68
|
+
|
69
|
+
== Support
|
70
|
+
|
71
|
+
The Kodekopelli site is located at http://www.kodekopelli.org
|
72
|
+
|
73
|
+
Technical assistance and Kodekopelli enterprise support services
|
74
|
+
are available from Free Range Data LLC (http://www.freerangedata.com).
|
75
|
+
|
76
|
+
Please feel free to submit comments, feature requests, or enhancements.
|
77
|
+
If your enhancement is integrated into Kodekopelli, your name will be
|
78
|
+
added to the list of contributors on the main site.
|
data/Rakefile
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/contrib/rubyforgepublisher'
|
8
|
+
|
9
|
+
PKG_NAME = 'kodekopelli'
|
10
|
+
PKG_VERSION = ENV['KODEKOPELLI_VERSION'] || '0.8.0'
|
11
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
12
|
+
BUILD_DIR = "build"
|
13
|
+
TEST_OUTPUT_DIR = "test/output"
|
14
|
+
PACKAGE_DIR = "pkg"
|
15
|
+
|
16
|
+
RELEASE_NAME = "REL #{PKG_VERSION}"
|
17
|
+
|
18
|
+
RUBY_FORGE_PROJECT = 'kodekopelli'
|
19
|
+
RUBY_FORGE_USER = 'hastyb0y'
|
20
|
+
|
21
|
+
PKG_FILES = FileList[
|
22
|
+
"lib/**/*", "test/**/*", "doc/**/*", "examples/**/*", "[A-Z]*", "rakefile"
|
23
|
+
].exclude(/\bCVS\b|-$/)
|
24
|
+
|
25
|
+
desc "Default Task"
|
26
|
+
task :default => [ :clean, :prepare, :test, :rdoc ]
|
27
|
+
|
28
|
+
desc "Scorch-the-earth removal of all build artifacts."
|
29
|
+
task :clean do
|
30
|
+
rm_rf BUILD_DIR
|
31
|
+
rm_rf TEST_OUTPUT_DIR
|
32
|
+
rm_rf PACKAGE_DIR
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Prepares the blank canvas for build process(es)."
|
36
|
+
task :prepare do
|
37
|
+
FileUtils.mkdir_p TEST_OUTPUT_DIR
|
38
|
+
end
|
39
|
+
|
40
|
+
# Run the unit and functional tests
|
41
|
+
Rake::TestTask.new { |t|
|
42
|
+
t.libs << "test"
|
43
|
+
t.pattern = 'test/ts_all_tests.rb'
|
44
|
+
t.verbose = true
|
45
|
+
}
|
46
|
+
desc "Run the unit tests."
|
47
|
+
task :test => [ :clean, :prepare ] do
|
48
|
+
end
|
49
|
+
|
50
|
+
# Generate the RDoc documentation
|
51
|
+
Rake::RDocTask.new { |rdoc|
|
52
|
+
rdoc.rdoc_dir = "#{BUILD_DIR}/doc/rdoc"
|
53
|
+
rdoc.title = "Kodekopelli"
|
54
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
55
|
+
rdoc.rdoc_files.include('README', 'LICENSE', 'CHANGELOG')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
}
|
58
|
+
|
59
|
+
# Create compressed packages
|
60
|
+
spec = Gem::Specification.new do |s|
|
61
|
+
s.platform = Gem::Platform::RUBY
|
62
|
+
s.name = PKG_NAME
|
63
|
+
s.summary = "Making code generation rock since 2003. Do it well. Do it once. Let Kodekopelli do the rest."
|
64
|
+
s.version = PKG_VERSION
|
65
|
+
|
66
|
+
s.author = "Rich Wertz"
|
67
|
+
s.email = "rich@kodekopelli.org"
|
68
|
+
s.rubyforge_project = RUBY_FORGE_PROJECT
|
69
|
+
s.homepage = "http://www.kodekopelli.org"
|
70
|
+
|
71
|
+
s.has_rdoc = true
|
72
|
+
s.extra_rdoc_files = [ "README", "CHANGELOG", "LICENSE" ]
|
73
|
+
s.test_file = "test/ts_all_tests.rb"
|
74
|
+
s.requirements << 'none'
|
75
|
+
s.require_path = "lib"
|
76
|
+
s.autorequire = PKG_NAME
|
77
|
+
s.files = PKG_FILES
|
78
|
+
|
79
|
+
s.bindir = "bin"
|
80
|
+
s.executables = ["kodekopelli"]
|
81
|
+
s.default_executable = "kodekopelli"
|
82
|
+
end
|
83
|
+
|
84
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
85
|
+
# pkg.need_tar = true
|
86
|
+
# pkg.need_zip = true
|
87
|
+
end
|
data/bin/kodekopelli
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<kodekopelli>
|
3
|
+
<property location="." name="basedir" />
|
4
|
+
<property location="${basedir}/templates" name="template.dir" />
|
5
|
+
<property location="${basedir}/includes" name="include.dir" />
|
6
|
+
<property location="${basedir}/generated" name="output.dir" />
|
7
|
+
<property location="${template.dir}/html_wrapper.txt" name="html" />
|
8
|
+
<property location="${template.dir}/great_big.txt" name="big" />
|
9
|
+
<property location="${template.dir}/faqs.txt" name="faqs" />
|
10
|
+
<filegroup>
|
11
|
+
<file name="${output.dir}/faqs.html">
|
12
|
+
<composite template="${html}">
|
13
|
+
<composite template="${faqs}">
|
14
|
+
<composite question="Does fuzzy logic tickle?">
|
15
|
+
<template>Yes, but only on Tuesdays.</template>
|
16
|
+
</composite>
|
17
|
+
<composite
|
18
|
+
question="If vegetarians eat vegetables, what do humanitarians eat?">
|
19
|
+
<template><![CDATA[The world may never know...]]></template>
|
20
|
+
</composite>
|
21
|
+
<composite question="Is animal shampoo tested on humans?">
|
22
|
+
<include file="${include.dir}/shampoo_answer.txt" />
|
23
|
+
</composite>
|
24
|
+
<composite question="Can someone be a closet claustrophobic?">
|
25
|
+
<composite bigs="1" template="${big}">
|
26
|
+
<template>No.</template>
|
27
|
+
</composite>
|
28
|
+
</composite>
|
29
|
+
<composite
|
30
|
+
question="Can you imagine a world without hypothetical questions?">
|
31
|
+
<template>Absolutely</template>
|
32
|
+
<template> </template>
|
33
|
+
<template>not</template>
|
34
|
+
<template>.</template>
|
35
|
+
</composite>
|
36
|
+
</composite>
|
37
|
+
</composite>
|
38
|
+
</file>
|
39
|
+
</filegroup>
|
40
|
+
</kodekopelli>
|
@@ -0,0 +1,376 @@
|
|
1
|
+
<p class="note">
|
2
|
+
<strong>Please Note</strong> This example should be considered a work in progress.
|
3
|
+
Although all associated configuration files and templates have been completed and
|
4
|
+
are included in this example, not all supporting text has been added.
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
This simple example demonstrates basic Kodekopelli functionality
|
8
|
+
and recommended practices. The following Kodekopelli concepts
|
9
|
+
not covered by previous examples are illustrated herein:
|
10
|
+
</p>
|
11
|
+
<ul>
|
12
|
+
<li>
|
13
|
+
Using <a href="<%= att 'manual' %>#templates">template</a> elements.
|
14
|
+
</li>
|
15
|
+
<li>
|
16
|
+
Using <a href="<%= att 'manual' %>#composites">composite</a> elements.
|
17
|
+
</li>
|
18
|
+
<li>
|
19
|
+
Creating <a href="<%= att 'manual' %>#kodekopellitemplates">Kodekopelli templates</a>
|
20
|
+
templates that access the attribute values of child
|
21
|
+
elements.
|
22
|
+
</li>
|
23
|
+
<li>
|
24
|
+
Explicitly specifying template text in a Kodekopelli configuration
|
25
|
+
file.
|
26
|
+
</li>
|
27
|
+
</ul>
|
28
|
+
<h2>Problem</h2>
|
29
|
+
<p>
|
30
|
+
Your static web site contains a page dedicated to FAQs, or
|
31
|
+
<em>frequently-asked questions</em>. Each time that a new
|
32
|
+
question/answer combination is added, you must
|
33
|
+
manually add the new question, create a link to the question's
|
34
|
+
answer and, possibly, shuffle the order of the questions. Although
|
35
|
+
the amount of work required isn't overwhelming, it's tedious--especially
|
36
|
+
when questions must be rearranged. Also, you would like to minimize the
|
37
|
+
coupling between the actual questions and answers and the presentation
|
38
|
+
logic.
|
39
|
+
</p>
|
40
|
+
<h2>Solution</h2>
|
41
|
+
<p>
|
42
|
+
Use Kodekopelli to abstract questions and answers away from presentation
|
43
|
+
logic, so that any reordering or question additions, modifications or
|
44
|
+
deletions may be performed
|
45
|
+
within a single Kodekopelli configuration file.
|
46
|
+
</p>
|
47
|
+
<h3>Project Structure</h3>
|
48
|
+
<p>
|
49
|
+
Starting from a fresh, empty folder
|
50
|
+
of your choice, create subfolders mirroring the following structure:
|
51
|
+
</p>
|
52
|
+
<pre class="code">
|
53
|
+
/generated
|
54
|
+
/templates
|
55
|
+
/includes
|
56
|
+
</pre>
|
57
|
+
<p>
|
58
|
+
The <em>generated</em> folder will contain those files that Kodekopelli
|
59
|
+
generates during processing. The <em>templates</em> folder will contain
|
60
|
+
those files that Kodekopelli will interpret as
|
61
|
+
<a href="<%= att 'manual' %>#kodekopellitemplates">Kodekopelli templates</a>.
|
62
|
+
The <em>includes</em> folder will contain those static files that are available
|
63
|
+
to be <a href="<%= att 'manual' %>#includes">included</a>,
|
64
|
+
but not interpreted, by Kodekopelli. Please note that this project layout is
|
65
|
+
not required for Kodekopelli to function correctly; rather, it is introduced as
|
66
|
+
a respectable starting point for your projects.
|
67
|
+
</p>
|
68
|
+
<h3>The Goal</h3>
|
69
|
+
<p>
|
70
|
+
This example will demonstrate using Kodekopelli to create the simple
|
71
|
+
FAQ list shown below. Questions listed at the top of the list
|
72
|
+
will contain links to their corresponding answers that will, conversely,
|
73
|
+
contain links back to their questions. FAQ lists structured in this
|
74
|
+
manner make it very easy for users to navigate back and forth
|
75
|
+
between questions and answers without losing their relative positions
|
76
|
+
within the question list.
|
77
|
+
</p>
|
78
|
+
<div class="example">
|
79
|
+
<big>
|
80
|
+
<strong>
|
81
|
+
Questions</strong></big>
|
82
|
+
<br />
|
83
|
+
<ol>
|
84
|
+
<li id="question_1">
|
85
|
+
Does fuzzy logic tickle?
|
86
|
+
<a href="#faq_1">
|
87
|
+
Answer »
|
88
|
+
</a>
|
89
|
+
</li>
|
90
|
+
<li id="question_2">
|
91
|
+
If vegetarians eat vegetables, what do humanitarians eat?
|
92
|
+
<a href="#faq_2">
|
93
|
+
Answer »
|
94
|
+
</a>
|
95
|
+
</li>
|
96
|
+
<li id="question_3">
|
97
|
+
Is animal shampoo tested on humans?
|
98
|
+
<a href="#faq_3">
|
99
|
+
Answer »
|
100
|
+
</a>
|
101
|
+
</li>
|
102
|
+
<li id="question_4">
|
103
|
+
Can someone be a closet claustrophobic?
|
104
|
+
<a href="#faq_4">
|
105
|
+
Answer »
|
106
|
+
</a>
|
107
|
+
</li>
|
108
|
+
<li id="question_5">
|
109
|
+
Can you imagine a world without hypothetical questions?
|
110
|
+
<a href="#faq_5">
|
111
|
+
Answer »
|
112
|
+
</a>
|
113
|
+
</li>
|
114
|
+
</ol>
|
115
|
+
<big>
|
116
|
+
<strong>
|
117
|
+
Answers</strong></big>
|
118
|
+
<br />
|
119
|
+
<br />
|
120
|
+
<strong id="faq_1">
|
121
|
+
1. Does fuzzy logic tickle?</strong>
|
122
|
+
<br />
|
123
|
+
Yes, but only on Tuesdays.
|
124
|
+
<p>
|
125
|
+
<a href="#question_1">
|
126
|
+
« Back
|
127
|
+
</a>
|
128
|
+
</p>
|
129
|
+
<strong id="faq_2">
|
130
|
+
2. If vegetarians eat vegetables, what do humanitarians eat?</strong>
|
131
|
+
<br />
|
132
|
+
The world may never know...
|
133
|
+
<p>
|
134
|
+
<a href="#question_2">
|
135
|
+
« Back
|
136
|
+
</a>
|
137
|
+
</p>
|
138
|
+
<strong id="faq_3">
|
139
|
+
3. Is animal shampoo tested on humans?</strong>
|
140
|
+
<br />
|
141
|
+
Who told you!?!
|
142
|
+
<p>
|
143
|
+
<a href="#question_3">
|
144
|
+
« Back
|
145
|
+
</a>
|
146
|
+
</p>
|
147
|
+
<strong id="faq_4">
|
148
|
+
4. Can someone be a closet claustrophobic?</strong>
|
149
|
+
<br />
|
150
|
+
<big>
|
151
|
+
<big>
|
152
|
+
<big>
|
153
|
+
<big>
|
154
|
+
No.</big></big></big>
|
155
|
+
</big>
|
156
|
+
<p>
|
157
|
+
<a href="#question_4">
|
158
|
+
« Back
|
159
|
+
</a>
|
160
|
+
</p>
|
161
|
+
<strong id="faq_5">
|
162
|
+
5. Can you imagine a world without hypothetical questions?</strong>
|
163
|
+
<br />
|
164
|
+
Absolutely not.
|
165
|
+
<p>
|
166
|
+
<a href="#question_5">
|
167
|
+
« Back
|
168
|
+
</a>
|
169
|
+
</p>
|
170
|
+
</div>
|
171
|
+
<h3>The Configuration File</h3>
|
172
|
+
<p>
|
173
|
+
Using your favorite text or XML
|
174
|
+
editor, create a file called config.xml with the following content at the
|
175
|
+
root level of your project folder:
|
176
|
+
</p>
|
177
|
+
<pre class="code">
|
178
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
179
|
+
<kodekopelli>
|
180
|
+
</kodekopelli>
|
181
|
+
</pre>
|
182
|
+
<p>
|
183
|
+
Create properties representing the project structure.
|
184
|
+
</p>
|
185
|
+
<pre class="code">
|
186
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
187
|
+
<span class="focus"><property location="." name="basedir" />
|
188
|
+
<property location="${basedir}/templates" name="template.dir" />
|
189
|
+
<property location="${basedir}/includes" name="include.dir" />
|
190
|
+
<property location="${basedir}/generated" name="output.dir" /></span>
|
191
|
+
</kodekopelli>
|
192
|
+
</pre>
|
193
|
+
<p>
|
194
|
+
The configuration file at this point does not contain enough information
|
195
|
+
for Kodekopelli to process without error. Before additional configuration directives
|
196
|
+
are provided, however, our attention should turn to the templates that will
|
197
|
+
be required to create the <em>FAQ-O-Matic</em>. Since the FAQ list
|
198
|
+
created in this example will be rendered as an HTML snippet, it would be
|
199
|
+
wise to create a wrapper template containing enough markup to house the
|
200
|
+
FAQ list in a well-formed HTML document.
|
201
|
+
</p>
|
202
|
+
<h3>The HTML Wrapper Template</h3>
|
203
|
+
<p>
|
204
|
+
Using your favorite
|
205
|
+
text editor, create a new file containing the following markup.
|
206
|
+
</p>
|
207
|
+
<pre class="code">
|
208
|
+
<html>
|
209
|
+
<head>
|
210
|
+
<title><%= h att('title') %></title>
|
211
|
+
</head>
|
212
|
+
<body>
|
213
|
+
<h1><%= h att('title') %></h1>
|
214
|
+
<%= child_output %>
|
215
|
+
</body>
|
216
|
+
</html>
|
217
|
+
</pre>
|
218
|
+
<p>
|
219
|
+
This template creates a minimal HTML wrapper that checks for the presence
|
220
|
+
of an attribute named <em>title</em>. If found, the value of the
|
221
|
+
<em>title</em> attribute is used for the page title and also
|
222
|
+
for the page header. More importantly, the template also includes the
|
223
|
+
outcome of all child element processing within the body of the HTML
|
224
|
+
document, using the <em>child_output</em> method. Now that the
|
225
|
+
template is complete, save it under the <em>templates</em> folder
|
226
|
+
using the name <em>html_wrapper.txt</em>.
|
227
|
+
</p>
|
228
|
+
<p>
|
229
|
+
Now add the information for the new template to the configuration file.
|
230
|
+
</p>
|
231
|
+
<pre class="code">
|
232
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
233
|
+
<property location="." name="basedir" />
|
234
|
+
<property location="${basedir}/templates" name="template.dir" />
|
235
|
+
<property location="${basedir}/includes" name="include.dir" />
|
236
|
+
<property location="${basedir}/generated" name="output.dir" />
|
237
|
+
<span class="focus"><property location="${template.dir}/html_wrapper.txt" name="html" /></span>
|
238
|
+
</kodekopelli>
|
239
|
+
</pre>
|
240
|
+
|
241
|
+
<h3>The Great Big Text Template</h3>
|
242
|
+
<p>
|
243
|
+
This template is very simple, as it wraps a variable number of
|
244
|
+
<big>...</big> elements around all child element output.
|
245
|
+
The number of <em>big</em> wrappers added corresponds
|
246
|
+
to the value of the <em>bigs</em> attribute provided. If no value is
|
247
|
+
provided for the <em>bigs</em> attribute, a default value of '1' is
|
248
|
+
used. Save this template under the <em>templates</em> folder using the name
|
249
|
+
<em>great_big.txt</em>.
|
250
|
+
</p>
|
251
|
+
<pre class="code">
|
252
|
+
<% att('bigs', 1).to_i.times {%><big><%} %>
|
253
|
+
<%= child_output %>
|
254
|
+
<% att('bigs', 1).to_i.times {%></big><%} %>
|
255
|
+
</pre>
|
256
|
+
<p>
|
257
|
+
Add the information for the <em>great big text</em> template to the configuration file.
|
258
|
+
</p>
|
259
|
+
<pre class="code">
|
260
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
261
|
+
<property location="." name="basedir" />
|
262
|
+
<property location="${basedir}/templates" name="template.dir" />
|
263
|
+
<property location="${basedir}/includes" name="include.dir" />
|
264
|
+
<property location="${basedir}/generated" name="output.dir" />
|
265
|
+
<property location="${template.dir}/html_wrapper.txt" name="html" />
|
266
|
+
<span class="focus"><property location="${template.dir}/great_big.txt" name="big" /></span>
|
267
|
+
</kodekopelli>
|
268
|
+
</pre>
|
269
|
+
<h3>The FAQs Template</h3>
|
270
|
+
<p>
|
271
|
+
The FAQs template is a <em>composite</em> template responsible for building
|
272
|
+
the actual FAQ list.
|
273
|
+
</p>
|
274
|
+
|
275
|
+
<pre class="code">
|
276
|
+
<big><strong>Questions</strong></big><br />
|
277
|
+
<ol>
|
278
|
+
<% question_counter = 1 %>
|
279
|
+
<% child_iterator { |current_child, text| %>
|
280
|
+
<li id="question_<%= question_counter.to_s %>">
|
281
|
+
<%= node_att(current_child, 'question') %>
|
282
|
+
<a href="<%= "#faq_#{question_counter.to_s}" %>">Answer »</a>
|
283
|
+
</li>
|
284
|
+
<% question_counter += 1 %>
|
285
|
+
<% } %>
|
286
|
+
</ol>
|
287
|
+
<big><strong>Answers</strong></big><br /><br />
|
288
|
+
<% answer_counter = 1 %>
|
289
|
+
<% child_iterator { |current_child, text| %>
|
290
|
+
<strong id="faq_<%= answer_counter.to_s %>">
|
291
|
+
<%= answer_counter.to_s %>. <%= node_att(current_child,'question') %></strong><br />
|
292
|
+
<%= text %>
|
293
|
+
<p>
|
294
|
+
<a href="#question_<%= answer_counter.to_s %>">« Back</a>
|
295
|
+
</p>
|
296
|
+
<% answer_counter += 1 %>
|
297
|
+
<% } %>
|
298
|
+
</pre>
|
299
|
+
<p>
|
300
|
+
Add the information for the final template to the configuration file.
|
301
|
+
</p>
|
302
|
+
<pre class="code">
|
303
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
304
|
+
<property location="." name="basedir" />
|
305
|
+
<property location="${basedir}/templates" name="template.dir" />
|
306
|
+
<property location="${basedir}/includes" name="include.dir" />
|
307
|
+
<property location="${basedir}/generated" name="output.dir" />
|
308
|
+
<property location="${template.dir}/html_wrapper.txt" name="html" />
|
309
|
+
<property location="${template.dir}/great_big.txt" name="big" />
|
310
|
+
<span class="focus"><property location="${template.dir}/faqs.txt" name="faqs" /></span>
|
311
|
+
</kodekopelli>
|
312
|
+
</pre>
|
313
|
+
<h3>Back to the Configuration File</h3>
|
314
|
+
<pre class="code">
|
315
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
316
|
+
<kodekopelli>
|
317
|
+
<property location="." name="basedir" />
|
318
|
+
<property location="${basedir}/templates" name="template.dir" />
|
319
|
+
<property location="${basedir}/includes" name="include.dir" />
|
320
|
+
<property location="${basedir}/generated" name="output.dir" />
|
321
|
+
<property location="${template.dir}/html_wrapper.txt" name="html" />
|
322
|
+
<property location="${template.dir}/great_big.txt" name="big" />
|
323
|
+
<property location="${template.dir}/faqs.txt" name="faqs" />
|
324
|
+
<filegroup>
|
325
|
+
<file name="${output.dir}/faqs.html">
|
326
|
+
<composite template="${html}">
|
327
|
+
<composite template="${faqs}">
|
328
|
+
<composite question="Does fuzzy logic tickle?">
|
329
|
+
<template>Yes, but only on Tuesdays.</template>
|
330
|
+
</composite>
|
331
|
+
<composite
|
332
|
+
question="If vegetarians eat vegetables, what do humanitarians eat?">
|
333
|
+
<template><![CDATA[The world may never know...]]></template>
|
334
|
+
</composite>
|
335
|
+
<composite question="Is animal shampoo tested on humans?">
|
336
|
+
<include file="${include.dir}/shampoo_answer.txt" />
|
337
|
+
</composite>
|
338
|
+
<composite question="Can someone be a closet claustrophobic?">
|
339
|
+
<composite bigs="1" template="${big}">
|
340
|
+
<template>No.</template>
|
341
|
+
</composite>
|
342
|
+
</composite>
|
343
|
+
<composite
|
344
|
+
question="Can you imagine a world without hypothetical questions?">
|
345
|
+
<template>Absolutely</template>
|
346
|
+
<template> </template>
|
347
|
+
<template>not</template>
|
348
|
+
<template>.</template>
|
349
|
+
</composite>
|
350
|
+
</composite>
|
351
|
+
</composite>
|
352
|
+
</file>
|
353
|
+
</filegroup>
|
354
|
+
</kodekopelli>
|
355
|
+
</pre>
|
356
|
+
<p>
|
357
|
+
The configuration file is complete and is now ready for processing by Kodekopelli.
|
358
|
+
From the top level of your project folder, invoke Kodekopelli from the command line:
|
359
|
+
</p>
|
360
|
+
<pre class="code">
|
361
|
+
% <span class="focus">kodekopelli config.xml</span>
|
362
|
+
</pre>
|
363
|
+
<p>
|
364
|
+
After Kodekopelli has finished processing the file, you may view the FAQ list
|
365
|
+
within the context of the HTML page located in the project's
|
366
|
+
<em>generated</em> folder.
|
367
|
+
</p>
|
368
|
+
<h2>Notes</h2>
|
369
|
+
<ul>
|
370
|
+
<li>
|
371
|
+
The template and composite level elements used to create the answers
|
372
|
+
for the FAQ questions above have been made intentionally diverse so that
|
373
|
+
the reader may be aware that there are numerous solutions to the same
|
374
|
+
problem when using Kodekopelli.
|
375
|
+
</li>
|
376
|
+
</ul>
|