>b's YML 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
16 KiB

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