0
|
1 |
include homepage.en.yhtml2
|
|
2 |
|
|
3 |
page "Using YML 2" {
|
|
4 |
p >>
|
|
5 |
YML 2 is a smart ¬http://en.wikipedia.org/wiki/Template_processor template language¬ and
|
|
6 |
¬http://en.wikipedia.org/wiki/Domain-specific_language DSL concept¬. This guide will give
|
|
7 |
you a feeling, for what it's worth.
|
|
8 |
>>
|
|
9 |
|
|
10 |
h2 id=wiki > Creating a Wiki like language for writing documentation
|
|
11 |
|
|
12 |
p >>
|
|
13 |
Let's say, we want to define a small Wiki system, which should be translated from a Wiki
|
|
14 |
like language into HTML. This guide is written in one using YML 2. I call it ƒYHTML. You can
|
|
15 |
view the ¬homepage.en.yhtml2 source code of what you're reading now¬. It's about writing
|
|
16 |
web pages like that:
|
|
17 |
>>
|
|
18 |
|
|
19 |
Code {
|
|
20 |
||
|
|
21 |
page "Hello, world" {
|
|
22 |
p ¬features#blockquote >>¬
|
|
23 |
Hello, world! I can link here, say:
|
|
24 |
||
|
|
25 |
>
|
|
26 |
] ¬http://en.wikipedia.org to Wikipedia¬
|
|
27 |
> \n
|
|
28 |
||
|
|
29 |
¬features#blockquote >>¬
|
|
30 |
|
|
31 |
p ¬features#blockquote >>¬
|
|
32 |
||
|
|
33 |
>
|
|
34 |
] This is ƒemphasized. And this is «code».
|
|
35 |
> \n
|
|
36 |
||
|
|
37 |
¬features#blockquote >>¬
|
|
38 |
}
|
|
39 |
||
|
|
40 |
}
|
|
41 |
p >>
|
|
42 |
Prerequisite: knowing how ¬http://en.wikipedia.org/wiki/Html#Markup HTML¬ works.
|
|
43 |
>>
|
|
44 |
|
|
45 |
h2 id=how > How does that work?
|
|
46 |
|
|
47 |
p >>
|
|
48 |
YML 2 is a template language. That means, you can define ¬http://en.wikipedia.org/wiki/Recursion recursive¬
|
|
49 |
templates of what's to be generated. This is ¬homepage.en.yhtml2 the code¬; just click on underlined things
|
|
50 |
to get an explanation:
|
|
51 |
>>
|
|
52 |
|
|
53 |
Code {
|
|
54 |
||
|
|
55 |
¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬
|
|
56 |
¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
57 |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬
|
|
58 |
|
|
59 |
¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬
|
|
60 |
a name¬features#named =¬"top";
|
|
61 |
¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
|
|
62 |
div id¬features#named =¬"entries"
|
|
63 |
¬features#contentfc content¬;
|
|
64 |
¬features#defaultbody }¬;
|
|
65 |
|
|
66 |
¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml")
|
|
67 |
¬features#alias alias¬ html ¬features#defaultbody {¬
|
|
68 |
head ¬features#subtree {¬
|
|
69 |
title ¬features#pointer *title¬;
|
|
70 |
meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8";
|
|
71 |
link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css";
|
|
72 |
¬features#subtree }¬
|
|
73 |
|
|
74 |
pageContent
|
|
75 |
¬features#contentfc content¬;
|
|
76 |
¬features#defaultbody }¬;
|
|
77 |
||
|
|
78 |
|
|
79 |
br; > ¬features#userop define operator¬
|
|
80 |
] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
|
|
81 |
> ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
|
|
82 |
|
|
83 |
br; > ¬features#userop define operator¬
|
|
84 |
] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
|
|
85 |
> ¬features#userop as¬ code ¬features#quote >¬ %1
|
|
86 |
|
|
87 |
br; > ¬features#userop define operator¬
|
|
88 |
] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
|
|
89 |
> ¬features#userop as¬ em ¬features#quote >¬ %1
|
|
90 |
}
|
|
91 |
|
|
92 |
h2 id=details > Details, please!
|
|
93 |
|
|
94 |
h3 > Starting with XHTML headers
|
|
95 |
|
|
96 |
p >>
|
|
97 |
Because HTML headers are boring and annoying, I'm copying them from document to document. And at last,
|
|
98 |
they ended here ;-) If you already have things in angle brackets, you can just add them to your YML 2
|
|
99 |
document “as is”, because everything which starts with an opening angle bracket will be a “give through”
|
|
100 |
for the YML 2 toolchain. So our first two lines are:
|
|
101 |
>>
|
|
102 |
|
|
103 |
Code
|
|
104 |
||
|
|
105 |
¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬
|
|
106 |
¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
107 |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬
|
|
108 |
||
|
|
109 |
|
|
110 |
h3 > Defining the document structure
|
|
111 |
|
|
112 |
p >>
|
|
113 |
A Webpage usually has a structure: it has a specific title and content. Beside that, technical things
|
|
114 |
have to be encoded. A Webpage in XHTML is XML text, setting xmlns to the right name space. That's how we
|
|
115 |
do that in YML 2:
|
|
116 |
>>
|
|
117 |
|
|
118 |
Code
|
|
119 |
||
|
|
120 |
¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml")
|
|
121 |
¬features#alias alias¬ html ¬features#defaultbody {¬
|
|
122 |
||
|
|
123 |
|
|
124 |
p >>
|
|
125 |
First we ¬features#decl declare¬ the «page» function. It's ¬features#alias aliased to¬ «html», so it will
|
|
126 |
generate a «html» tag, not a «page» tag.
|
|
127 |
>>
|
|
128 |
|
|
129 |
p >>
|
|
130 |
The first parameter, «*title», is a placeholder for the title of the document. The content of what we give
|
|
131 |
here later will be repeated at any place we're putting «*title» into our template. This technique is called
|
|
132 |
¬features#pointer Pointers¬.
|
|
133 |
>>
|
|
134 |
|
|
135 |
p >>
|
|
136 |
The two other attributes have ¬features#defaultattr Default Values¬, so they're generated each time the
|
|
137 |
«page» function will be called.
|
|
138 |
>>
|
|
139 |
|
|
140 |
h3 > The Document content
|
|
141 |
|
|
142 |
p >>
|
|
143 |
The document content is what is in the «{ ... }» block:
|
|
144 |
>>
|
|
145 |
|
|
146 |
Code
|
|
147 |
||
|
|
148 |
¬features#defaultbody {¬
|
|
149 |
head ¬features#subtree {¬
|
|
150 |
title ¬features#pointer *title¬;
|
|
151 |
meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8";
|
|
152 |
link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css";
|
|
153 |
¬features#subtree }¬
|
|
154 |
|
|
155 |
pageContent
|
|
156 |
¬features#contentfc content¬;
|
|
157 |
¬features#defaultbody }¬;
|
|
158 |
||
|
|
159 |
|
|
160 |
p >>
|
|
161 |
This reflects, that each HTML document has a «head» and a «body» section. Of course, we insert the «*title»
|
|
162 |
pointer value in the «title» tag. Then some meta data and a link to a nice
|
|
163 |
¬http://en.wikipedia.org/wiki/Cascading_Style_Sheets CSS¬ ;-)
|
|
164 |
>>
|
|
165 |
|
|
166 |
p >>
|
|
167 |
For the «body» section, we have a little helper function, «pageContent». The function named «content» is
|
|
168 |
a ¬features#contentfc placeholder¬, where the content of the page will be placed, when our «page» function
|
|
169 |
will be called.
|
|
170 |
>>
|
|
171 |
|
|
172 |
h3 > Generating the «body» with the «pageContent» function
|
|
173 |
|
|
174 |
p >>
|
|
175 |
The «pageContent» function is used for generating the «body» with standard elements; therefore, it's
|
|
176 |
¬features#alias aliased¬ to «body»:
|
|
177 |
>>
|
|
178 |
|
|
179 |
Code
|
|
180 |
||
|
|
181 |
¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬
|
|
182 |
a name¬features#named =¬"top";
|
|
183 |
¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
|
|
184 |
div id¬features#named =¬"entries"
|
|
185 |
¬features#contentfc content¬;
|
|
186 |
¬features#defaultbody }¬;
|
|
187 |
||
|
|
188 |
|
|
189 |
p >>
|
|
190 |
It first sets an HTML anchor, so links can reference the top of the page:
|
|
191 |
>>
|
|
192 |
|
|
193 |
Code | a name¬features#named =¬"top";
|
|
194 |
|
|
195 |
p >>
|
|
196 |
Then a file with heading and navigation (the menu to the right on the page here) is being
|
|
197 |
¬features#including included¬:
|
|
198 |
>>
|
|
199 |
|
|
200 |
Code | ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
|
|
201 |
|
|
202 |
p >>
|
|
203 |
At last, the page content is being put in, surrounded by a «div» named «entries», so it can be referenced
|
|
204 |
later, too:
|
|
205 |
>>
|
|
206 |
|
|
207 |
Code ||
|
|
208 |
div id¬features#named =¬"entries"
|
|
209 |
¬features#contentfc content¬;
|
|
210 |
||
|
|
211 |
|
|
212 |
p >>
|
|
213 |
If you'll have a look on the included ¬heading.en.yhtml2 heading.en.yhtml2¬ file, then you'll see the
|
|
214 |
the static head and navigation sections hard coded. With the ¬format.css CSS file¬ everything is brought
|
|
215 |
to the right place.
|
|
216 |
>>
|
|
217 |
|
|
218 |
h3 > Defining some operators for the Wiki like language
|
|
219 |
|
|
220 |
p >>
|
|
221 |
The trick with a Wiki like language is, that one can write plain text, and adding structural things
|
|
222 |
to it, like links i.e.
|
|
223 |
>>
|
|
224 |
|
|
225 |
p >>
|
|
226 |
So we need language constructs, which let us structure. In YML 2 these are called
|
|
227 |
¬features#userop User defined in-text Operators¬:
|
|
228 |
>>
|
|
229 |
|
|
230 |
Code {
|
|
231 |
> ¬features#userop define operator¬
|
|
232 |
] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
|
|
233 |
> ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
|
|
234 |
|
|
235 |
br; > ¬features#userop define operator¬
|
|
236 |
] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
|
|
237 |
> ¬features#userop as¬ code ¬features#quote >¬ %1
|
|
238 |
|
|
239 |
br; > ¬features#userop define operator¬
|
|
240 |
] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
|
|
241 |
> ¬features#userop as¬ em ¬features#quote >¬ %1
|
|
242 |
}
|
|
243 |
|
|
244 |
p >>
|
|
245 |
They look somewhat disturbing, if you're not familiar with
|
|
246 |
¬http://en.wikipedia.org/wiki/Regular_expression Regex¬, so I will explain.
|
|
247 |
>>
|
|
248 |
|
|
249 |
p >>
|
|
250 |
First we define a link:
|
|
251 |
>>
|
|
252 |
|
|
253 |
Code {
|
|
254 |
> ¬features#userop define operator¬
|
|
255 |
] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
|
|
256 |
> ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
|
|
257 |
}
|
|
258 |
|
|
259 |
p >>
|
|
260 |
The keyword «define operator» starts the definition. Then there is the Regex:
|
|
261 |
>>
|
|
262 |
|
|
263 |
Code | "¬\s*(.*?)\s+(.*?)\s*¬"
|
|
264 |
|
|
265 |
p {
|
|
266 |
"I decided I want to have the special character " "¬" " surrounding each link like this: "
|
|
267 |
code ] ¬http://en.wikipedia.org go to Wikipedia¬
|
|
268 |
". This is just like what ¬http://www.mediawiki.org MediaWiki¬ does with brackets; here the "
|
|
269 |
"same would read: «[http://en.wikipedia.org go to Wikipedia]»."
|
|
270 |
}
|
|
271 |
|
|
272 |
p >>
|
|
273 |
I like using such special characters. This is because I'm using a
|
|
274 |
¬http://www.apple.com/mac/ Mac¬ and ¬http://en.wikipedia.org/wiki/GNU/Linux GNU/Linux¬.
|
|
275 |
If you're using ¬http://www.microsoft.com/windows/ Windows¬, I really can recommend
|
|
276 |
¬http://www.autohotkey.com/docs/Hotkeys.htm AutoHotkey¬. It's a great piece of software to expand the
|
|
277 |
keyboard capabilities of Windows (and much more).
|
|
278 |
>>
|
|
279 |
|
|
280 |
p {
|
|
281 |
> How does this Regex stuff work? It's a ¬http://en.wikipedia.org/wiki/Pattern_matching pattern matching¬ language consuming characters with each
|
|
282 |
> command. Well, we want to have the following: The first thing between the
|
|
283 |
] ¬
|
|
284 |
> markers shell be the link target URL. All other things shell be the name of the link shown.
|
|
285 |
>>
|
|
286 |
For that case, we're first consuming whitespace with «\s*» – the «\s» means “an arbitrary whitespace
|
|
287 |
character” (like blank, newline, etc.). The asterisk «*» means “some of them or none”, so this
|
|
288 |
consumes all whitespace which is there (and gives no error if there is none).
|
|
289 |
>>
|
|
290 |
}
|
|
291 |
|
|
292 |
p >>
|
|
293 |
Second, we open a group with parentheses «( )» This first group we can later reference as «%1»
|
|
294 |
when substituting.
|
|
295 |
>>
|
|
296 |
|
|
297 |
p >>
|
|
298 |
Inside this group, we're telling that we want anything in it, no matter what it is. For this case,
|
|
299 |
we're using a dot «.» which means “any character”, followed by asterisk questionmark «*?», which is
|
|
300 |
the code for “consume as much as you can, but only up to the next code in the Regex”. The total
|
|
301 |
«(.*?)» consumes the target URL (without checking it).
|
|
302 |
>>
|
|
303 |
|
|
304 |
p >>
|
|
305 |
Then we're consuming some whitespace again, this time with «\s+». Using a plus «+» instead of an
|
|
306 |
asterisk «*» or asterisk questionmark «*?» means: there has to be at least one whitespace character.
|
|
307 |
And we want whitespace between the URL and the name, right? ;-)
|
|
308 |
>>
|
|
309 |
|
|
310 |
p >>
|
|
311 |
Now we're consuming the second group. We're consuming whatever is there – it's the name of the
|
|
312 |
link. We're using another «(.*?)» group for it. It will be group 2, and we can reference it with
|
|
313 |
this in the substitution: «%2».
|
|
314 |
>>
|
|
315 |
|
|
316 |
p {
|
|
317 |
> At last we're consuming redundant whitespace with «\s*», and our Regex is closed by another
|
|
318 |
] ¬
|
|
319 |
> character. And that makes the total Regex:
|
|
320 |
}
|
|
321 |
|
|
322 |
Code ] "¬\s*(.*?)\s+(.*?)\s*¬"
|
|
323 |
|
|
324 |
p >>
|
|
325 |
So what can we do with it? What we want are «<a href="..." />» tags. And that means, we want to
|
|
326 |
call a function like this: «a href="..." > ...»
|
|
327 |
>>
|
|
328 |
|
|
329 |
p >>
|
|
330 |
As «href» we want to have the result of group 1,
|
|
331 |
because this is the link target. After the ¬features#quote Quote operator¬ «>» we want to have
|
|
332 |
what is the name of the link, that is the result of group 2. That we can write literally:
|
|
333 |
>>
|
|
334 |
|
|
335 |
Code | a href="%1" > %2
|
|
336 |
|
|
337 |
p >>
|
|
338 |
Our first User defined in-text Operator is ready :-)
|
|
339 |
>>
|
|
340 |
|
|
341 |
p >>
|
|
342 |
Maybe you would prefer using brackets. So just do it ;-) Change the Regex to this, and you
|
|
343 |
can use brackets for links like in MediaWiki; we have to escape the brackets «[ ]» with a
|
|
344 |
backslash «\\», because brackets are also codes in Regex, and we don't want the code, we really
|
|
345 |
want brackets:
|
|
346 |
>>
|
|
347 |
|
|
348 |
Code | "\[\s*(.*?)\s+(.*?)\s*\]"
|
|
349 |
|
|
350 |
p >>
|
|
351 |
The other two operators should now be easy to understand:
|
|
352 |
>>
|
|
353 |
|
|
354 |
Code {
|
|
355 |
> ¬features#userop define operator¬
|
|
356 |
] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
|
|
357 |
> ¬features#userop as¬ code ¬features#quote >¬ %1
|
|
358 |
|
|
359 |
br; > ¬features#userop define operator¬
|
|
360 |
] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
|
|
361 |
> ¬features#userop as¬ em ¬features#quote >¬ %1
|
|
362 |
}
|
|
363 |
|
|
364 |
p >>
|
|
365 |
A tip: the code with an upper case letter S «\S» means, that only non-whitespace characters shell
|
|
366 |
be consumed.
|
|
367 |
>>
|
|
368 |
|
|
369 |
h2 id=using > Using it
|
|
370 |
|
|
371 |
p >>
|
|
372 |
How to write a new web page with our templates? Here's a ¬hello.en.yhtml2 hello world¬. We can use
|
|
373 |
¬features#blockquote Block Quotes¬ for entering text, and our new self defined operators:
|
|
374 |
>>
|
|
375 |
|
|
376 |
Code {
|
|
377 |
||
|
|
378 |
¬features#including include¬ homepage.en.yhtml2
|
|
379 |
|
|
380 |
page "Hello, world" {
|
|
381 |
p ¬features#blockquote >>¬
|
|
382 |
Hello, world! I can link here, say:
|
|
383 |
||
|
|
384 |
>
|
|
385 |
] ¬http://en.wikipedia.org to Wikipedia¬
|
|
386 |
> \n
|
|
387 |
||
|
|
388 |
¬features#blockquote >>¬
|
|
389 |
|
|
390 |
p ¬features#blockquote >>¬
|
|
391 |
||
|
|
392 |
>
|
|
393 |
] This is ƒemphasized. And this is «code».
|
|
394 |
> \n
|
|
395 |
||
|
|
396 |
¬features#blockquote >>¬
|
|
397 |
}
|
|
398 |
||
|
|
399 |
}
|
|
400 |
|
|
401 |
p >>
|
|
402 |
The result you can ¬hello see here¬:
|
|
403 |
>>
|
|
404 |
|
|
405 |
iframe src="hello", width="100%", height=300 > ¬hello see here¬
|
|
406 |
|
|
407 |
div id=bottom {
|
|
408 |
> ¬index << back to Introduction¬
|
|
409 |
> ¬#top ^Top^¬
|
|
410 |
> ¬features >> The Features¬
|
|
411 |
> ¬programming.en.yhtml2 (source)¬
|
|
412 |
}
|
|
413 |
}
|