kodekopelli 0.8.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/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>
|