vb@0: include homepage.en.yhtml2 vb@0: vb@0: page "Using YML 2" { vb@0: p >> vb@0: YML 2 is a smart ¬http://en.wikipedia.org/wiki/Template_processor template language¬ and vb@0: ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL concept¬. This guide will give vb@0: you a feeling, for what it's worth. vb@0: >> vb@0: vb@0: h2 id=wiki > Creating a Wiki like language for writing documentation vb@0: vb@0: p >> vb@0: Let's say, we want to define a small Wiki system, which should be translated from a Wiki vb@0: like language into HTML. This guide is written in one using YML 2. I call it ƒYHTML. You can vb@0: view the ¬homepage.en.yhtml2 source code of what you're reading now¬. It's about writing vb@0: web pages like that: vb@0: >> vb@0: vb@0: Code { vb@0: || vb@0: page "Hello, world" { vb@0: p ¬features#blockquote >>¬ vb@0: Hello, world! I can link here, say: vb@0: || vb@0: > vb@0: ] ¬http://en.wikipedia.org to Wikipedia¬ vb@0: > \n vb@0: || vb@0: ¬features#blockquote >>¬ vb@0: vb@0: p ¬features#blockquote >>¬ vb@0: || vb@0: > vb@0: ] This is ƒemphasized. And this is «code». vb@0: > \n vb@0: || vb@0: ¬features#blockquote >>¬ vb@0: } vb@0: || vb@0: } vb@0: p >> vb@0: Prerequisite: knowing how ¬http://en.wikipedia.org/wiki/Html#Markup HTML¬ works. vb@0: >> vb@0: vb@0: h2 id=how > How does that work? vb@0: vb@0: p >> vb@0: YML 2 is a template language. That means, you can define ¬http://en.wikipedia.org/wiki/Recursion recursive¬ vb@0: templates of what's to be generated. This is ¬homepage.en.yhtml2 the code¬; just click on underlined things vb@0: to get an explanation: vb@0: >> vb@0: vb@0: Code { vb@0: || vb@0: ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬ vb@0: ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" vb@0: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬ vb@0: vb@0: ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬ vb@0: a name¬features#named =¬"top"; vb@0: ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; vb@0: div id¬features#named =¬"entries" vb@0: ¬features#contentfc content¬; vb@0: ¬features#defaultbody }¬; vb@0: vb@0: ¬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") vb@0: ¬features#alias alias¬ html ¬features#defaultbody {¬ vb@0: head ¬features#subtree {¬ vb@0: title ¬features#pointer *title¬; vb@0: meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8"; vb@0: link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css"; vb@0: ¬features#subtree }¬ vb@0: vb@0: pageContent vb@0: ¬features#contentfc content¬; vb@0: ¬features#defaultbody }¬; vb@0: || vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "¬\s*(.*?)\s+(.*?)\s*¬" vb@0: > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "«(.*?)»" vb@0: > ¬features#userop as¬ code ¬features#quote >¬ %1 vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "ƒ(\S+)" vb@0: > ¬features#userop as¬ em ¬features#quote >¬ %1 vb@0: } vb@0: vb@0: h2 id=details > Details, please! vb@0: vb@0: h3 > Starting with XHTML headers vb@0: vb@0: p >> vb@0: Because HTML headers are boring and annoying, I'm copying them from document to document. And at last, vb@0: they ended here ;-) If you already have things in angle brackets, you can just add them to your YML 2 vb@0: document “as is”, because everything which starts with an opening angle bracket will be a “give through” vb@0: for the YML 2 toolchain. So our first two lines are: vb@0: >> vb@0: vb@0: Code vb@0: || vb@0: ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬ vb@0: ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" vb@0: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬ vb@0: || vb@0: vb@0: h3 > Defining the document structure vb@0: vb@0: p >> vb@0: A Webpage usually has a structure: it has a specific title and content. Beside that, technical things vb@0: have to be encoded. A Webpage in XHTML is XML text, setting xmlns to the right name space. That's how we vb@0: do that in YML 2: vb@0: >> vb@0: vb@0: Code vb@0: || vb@0: ¬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") vb@0: ¬features#alias alias¬ html ¬features#defaultbody {¬ vb@0: || vb@0: vb@0: p >> vb@0: First we ¬features#decl declare¬ the «page» function. It's ¬features#alias aliased to¬ «html», so it will vb@0: generate a «html» tag, not a «page» tag. vb@0: >> vb@0: vb@0: p >> vb@0: The first parameter, «*title», is a placeholder for the title of the document. The content of what we give vb@0: here later will be repeated at any place we're putting «*title» into our template. This technique is called vb@0: ¬features#pointer Pointers¬. vb@0: >> vb@0: vb@0: p >> vb@0: The two other attributes have ¬features#defaultattr Default Values¬, so they're generated each time the vb@0: «page» function will be called. vb@0: >> vb@0: vb@0: h3 > The Document content vb@0: vb@0: p >> vb@0: The document content is what is in the «{ ... }» block: vb@0: >> vb@0: vb@0: Code vb@0: || vb@0: ¬features#defaultbody {¬ vb@0: head ¬features#subtree {¬ vb@0: title ¬features#pointer *title¬; vb@0: meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8"; vb@0: link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css"; vb@0: ¬features#subtree }¬ vb@0: vb@0: pageContent vb@0: ¬features#contentfc content¬; vb@0: ¬features#defaultbody }¬; vb@0: || vb@0: vb@0: p >> vb@0: This reflects, that each HTML document has a «head» and a «body» section. Of course, we insert the «*title» vb@0: pointer value in the «title» tag. Then some meta data and a link to a nice vb@0: ¬http://en.wikipedia.org/wiki/Cascading_Style_Sheets CSS¬ ;-) vb@0: >> vb@0: vb@0: p >> vb@0: For the «body» section, we have a little helper function, «pageContent». The function named «content» is vb@0: a ¬features#contentfc placeholder¬, where the content of the page will be placed, when our «page» function vb@0: will be called. vb@0: >> vb@0: vb@0: h3 > Generating the «body» with the «pageContent» function vb@0: vb@0: p >> vb@0: The «pageContent» function is used for generating the «body» with standard elements; therefore, it's vb@0: ¬features#alias aliased¬ to «body»: vb@0: >> vb@0: vb@0: Code vb@0: || vb@0: ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬ vb@0: a name¬features#named =¬"top"; vb@0: ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; vb@0: div id¬features#named =¬"entries" vb@0: ¬features#contentfc content¬; vb@0: ¬features#defaultbody }¬; vb@0: || vb@0: vb@0: p >> vb@0: It first sets an HTML anchor, so links can reference the top of the page: vb@0: >> vb@0: vb@0: Code | a name¬features#named =¬"top"; vb@0: vb@0: p >> vb@0: Then a file with heading and navigation (the menu to the right on the page here) is being vb@0: ¬features#including included¬: vb@0: >> vb@0: vb@0: Code | ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; vb@0: vb@0: p >> vb@0: At last, the page content is being put in, surrounded by a «div» named «entries», so it can be referenced vb@0: later, too: vb@0: >> vb@0: vb@0: Code || vb@0: div id¬features#named =¬"entries" vb@0: ¬features#contentfc content¬; vb@0: || vb@0: vb@0: p >> vb@0: If you'll have a look on the included ¬heading.en.yhtml2 heading.en.yhtml2¬ file, then you'll see the vb@0: the static head and navigation sections hard coded. With the ¬format.css CSS file¬ everything is brought vb@0: to the right place. vb@0: >> vb@0: vb@0: h3 > Defining some operators for the Wiki like language vb@0: vb@0: p >> vb@0: The trick with a Wiki like language is, that one can write plain text, and adding structural things vb@0: to it, like links i.e. vb@0: >> vb@0: vb@0: p >> vb@0: So we need language constructs, which let us structure. In YML 2 these are called vb@0: ¬features#userop User defined in-text Operators¬: vb@0: >> vb@0: vb@0: Code { vb@0: > ¬features#userop define operator¬ vb@0: ] "¬\s*(.*?)\s+(.*?)\s*¬" vb@0: > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "«(.*?)»" vb@0: > ¬features#userop as¬ code ¬features#quote >¬ %1 vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "ƒ(\S+)" vb@0: > ¬features#userop as¬ em ¬features#quote >¬ %1 vb@0: } vb@0: vb@0: p >> vb@0: They look somewhat disturbing, if you're not familiar with vb@0: ¬http://en.wikipedia.org/wiki/Regular_expression Regex¬, so I will explain. vb@0: >> vb@0: vb@0: p >> vb@0: First we define a link: vb@0: >> vb@0: vb@0: Code { vb@0: > ¬features#userop define operator¬ vb@0: ] "¬\s*(.*?)\s+(.*?)\s*¬" vb@0: > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 vb@0: } vb@0: vb@0: p >> vb@0: The keyword «define operator» starts the definition. Then there is the Regex: vb@0: >> vb@0: vb@0: Code | "¬\s*(.*?)\s+(.*?)\s*¬" vb@0: vb@0: p { vb@0: "I decided I want to have the special character " "¬" " surrounding each link like this: " vb@0: code ] ¬http://en.wikipedia.org go to Wikipedia¬ vb@0: ". This is just like what ¬http://www.mediawiki.org MediaWiki¬ does with brackets; here the " vb@0: "same would read: «[http://en.wikipedia.org go to Wikipedia]»." vb@0: } vb@0: vb@0: p >> vb@0: I like using such special characters. This is because I'm using a vb@0: ¬http://www.apple.com/mac/ Mac¬ and ¬http://en.wikipedia.org/wiki/GNU/Linux GNU/Linux¬. vb@0: If you're using ¬http://www.microsoft.com/windows/ Windows¬, I really can recommend vb@0: ¬http://www.autohotkey.com/docs/Hotkeys.htm AutoHotkey¬. It's a great piece of software to expand the vb@0: keyboard capabilities of Windows (and much more). vb@0: >> vb@0: vb@0: p { vb@0: > How does this Regex stuff work? It's a ¬http://en.wikipedia.org/wiki/Pattern_matching pattern matching¬ language consuming characters with each vb@0: > command. Well, we want to have the following: The first thing between the vb@0: ] ¬ vb@0: > markers shell be the link target URL. All other things shell be the name of the link shown. vb@0: >> vb@0: For that case, we're first consuming whitespace with «\s*» – the «\s» means “an arbitrary whitespace vb@0: character” (like blank, newline, etc.). The asterisk «*» means “some of them or none”, so this vb@0: consumes all whitespace which is there (and gives no error if there is none). vb@0: >> vb@0: } vb@0: vb@0: p >> vb@0: Second, we open a group with parentheses «( )» This first group we can later reference as «%1» vb@0: when substituting. vb@0: >> vb@0: vb@0: p >> vb@0: Inside this group, we're telling that we want anything in it, no matter what it is. For this case, vb@0: we're using a dot «.» which means “any character”, followed by asterisk questionmark «*?», which is vb@0: the code for “consume as much as you can, but only up to the next code in the Regex”. The total vb@0: «(.*?)» consumes the target URL (without checking it). vb@0: >> vb@0: vb@0: p >> vb@0: Then we're consuming some whitespace again, this time with «\s+». Using a plus «+» instead of an vb@0: asterisk «*» or asterisk questionmark «*?» means: there has to be at least one whitespace character. vb@0: And we want whitespace between the URL and the name, right? ;-) vb@0: >> vb@0: vb@0: p >> vb@0: Now we're consuming the second group. We're consuming whatever is there – it's the name of the vb@0: link. We're using another «(.*?)» group for it. It will be group 2, and we can reference it with vb@0: this in the substitution: «%2». vb@0: >> vb@0: vb@0: p { vb@0: > At last we're consuming redundant whitespace with «\s*», and our Regex is closed by another vb@0: ] ¬ vb@0: > character. And that makes the total Regex: vb@0: } vb@0: vb@0: Code ] "¬\s*(.*?)\s+(.*?)\s*¬" vb@0: vb@0: p >> vb@0: So what can we do with it? What we want are «» tags. And that means, we want to vb@0: call a function like this: «a href="..." > ...» vb@0: >> vb@0: vb@0: p >> vb@0: As «href» we want to have the result of group 1, vb@0: because this is the link target. After the ¬features#quote Quote operator¬ «>» we want to have vb@0: what is the name of the link, that is the result of group 2. That we can write literally: vb@0: >> vb@0: vb@0: Code | a href="%1" > %2 vb@0: vb@0: p >> vb@0: Our first User defined in-text Operator is ready :-) vb@0: >> vb@0: vb@0: p >> vb@0: Maybe you would prefer using brackets. So just do it ;-) Change the Regex to this, and you vb@0: can use brackets for links like in MediaWiki; we have to escape the brackets «[ ]» with a vb@0: backslash «\\», because brackets are also codes in Regex, and we don't want the code, we really vb@0: want brackets: vb@0: >> vb@0: vb@0: Code | "\[\s*(.*?)\s+(.*?)\s*\]" vb@0: vb@0: p >> vb@0: The other two operators should now be easy to understand: vb@0: >> vb@0: vb@0: Code { vb@0: > ¬features#userop define operator¬ vb@0: ] "«(.*?)»" vb@0: > ¬features#userop as¬ code ¬features#quote >¬ %1 vb@0: vb@0: br; > ¬features#userop define operator¬ vb@0: ] "ƒ(\S+)" vb@0: > ¬features#userop as¬ em ¬features#quote >¬ %1 vb@0: } vb@0: vb@0: p >> vb@0: A tip: the code with an upper case letter S «\S» means, that only non-whitespace characters shell vb@0: be consumed. vb@0: >> vb@0: vb@0: h2 id=using > Using it vb@0: vb@0: p >> vb@0: How to write a new web page with our templates? Here's a ¬hello.en.yhtml2 hello world¬. We can use vb@0: ¬features#blockquote Block Quotes¬ for entering text, and our new self defined operators: vb@0: >> vb@0: vb@0: Code { vb@0: || vb@0: ¬features#including include¬ homepage.en.yhtml2 vb@0: vb@0: page "Hello, world" { vb@0: p ¬features#blockquote >>¬ vb@0: Hello, world! I can link here, say: vb@0: || vb@0: > vb@0: ] ¬http://en.wikipedia.org to Wikipedia¬ vb@0: > \n vb@0: || vb@0: ¬features#blockquote >>¬ vb@0: vb@0: p ¬features#blockquote >>¬ vb@0: || vb@0: > vb@0: ] This is ƒemphasized. And this is «code». vb@0: > \n vb@0: || vb@0: ¬features#blockquote >>¬ vb@0: } vb@0: || vb@0: } vb@0: vb@0: p >> vb@0: The result you can ¬hello see here¬: vb@0: >> vb@0: vb@0: iframe src="hello", width="100%", height=300 > ¬hello see here¬ vb@0: vb@0: div id=bottom { vb@0: > ¬index << back to Introduction¬ vb@0: > ¬#top ^Top^¬ vb@0: > ¬features >> The Features¬ vb@0: > ¬programming.en.yhtml2 (source)¬ vb@0: } vb@0: }