diff --git a/wiki.js b/wiki.js
index 7df725b..3882774 100755
--- a/wiki.js
+++ b/wiki.js
@@ -74,326 +74,12 @@ function Macro(doc, args, func){
}
+
// XXX should inline macros support named args???
var macro = {
__include_marker__: '__include_marker__',
- // Abstract macro syntax:
- // Inline macro:
- // @macro(arg ..)
- //
- // HTML-like:
- //
- //
- // HTML-like with body:
- //
- // ..text..
- //
- //
- // XXX should inline macros support named args???
- __macro__pattern__:
- ///<([a-zA-Z-_:]+)(.|[\n\r])*?(>(.|[\n\r])*?<\/\1>|\/>)|@([a-zA-Z-_]+)\(([^)]*)\)/mg,
- [[
- //
- // text
- '<([a-zA-Z-_:]+)(.|[\\n\\r])*?(>(.|[\\n\\r])*?<\\/\\1>|\\/>)',
- /*// same as above but HTML-level...
- '<([a-zA-Z-_:]+)(.|[\\n\\r])*?(>(.|[\\n\\r])*?<\\/\\1>|\\/>)'
- .replace(//g, '\\>'),
- //*/
-
- // @macro(arg ..)
- '@([a-zA-Z-_]+)\\(([^)]*)\\)'
- ].join('|'), 'mg'],
-
- // default filters...
- //
- // NOTE: these are added AFTER the user defined filters...
- __filters__: [
- 'wikiword',
- ],
-
- // Macros...
- //
- macro: {
- // select filter to post-process text...
- filter: Macro('Filter to post-process text',
- ['name'],
- function(context, args, text, state){
- var filter = args[0] || args.name
-
- filter[0] == '-' ?
- // disabled -- keep at head of list...
- state.filters.unshift(filter)
- // normal -- tail...
- : state.filters.push(filter)
-
- return ''
- }),
-
- // include page/slot...
- //
- // NOTE: this will render the page in the caller's context.
- // NOTE: included pages are rendered completely independently
- // from the including page.
- //
- // XXX do we need to control the rendering of nested pages???
- // ...currently I do not think so...
- // ...if required this can be done via global and local
- // filters... (now filters are only local)
- // XXX do we need to render just one slot??? (slot arg)
- // e.g. include PageX SlotY
- include: Macro('Include page',
- ['src'],
- function(context, args, _, state){
- var path = args.src
-
- // get and prepare the included page...
- state.include
- .push(context.get(path))
-
- // return the marker...
- return this.__include_marker__
- }),
-
- // NOTE: this is similar to include, the difference is that this
- // includes the page source to the current context while
- // include works in an isolated context
- source: Macro('Include page source (without parsing)',
- ['src'],
- function(context, args, _, state){
- var path = args.src
-
- return context.get(path).raw
- }),
-
- // fill/define slot (stage 1)...
- //
- // XXX which should have priority the arg text or the content???
- slot: Macro('Define/fill slot',
- ['name', 'text'],
- function(context, args, text, state){
- var name = args.name
-
- // XXX
- text = text || args.text
- text = this.parse(context, text, state, true)
-
- if(state.slots[name] == null){
- state.slots[name] = text
- // return a slot macro parsable by stage 2...
- return ''+ text +''
-
- } else if(name in state.slots){
- state.slots[name] = text
- return ''
- }
- }),
- },
-
- // Post macros...
- //
- post_macro: {
- slot: Macro('',
- ['name'],
- function(context, args, text, state){
- var name = args.name
-
- if(state.slots[name] == null){
- return text
-
- } else if(name in state.slots){
- return state.slots[name]
- }
- }),
- },
-
- // Filters...
- //
- // Signature:
- // filter(text) -> html
- //
- filter: {
- default: 'html',
-
- html: function(context, text){ return $('
').html(text).html() },
-
- json: 'text',
- text: function(context, text){ return $('
').text(text).html() },
-
- // XXX
- //nl2br: function(context, text){ return $('
').html(text.replace(/\n/g, '
\n')) },
-
- wikiword: function(context, text){
- return setWikiWords(text, true, this.__include_marker__) },
- },
-
-
- // Parsing:
- // 1) expand macros
- // 2) apply filters
- // 3) merge and parse included pages:
- // 1) expand macros
- // 2) apply filters
- // 4) expand post-macros
- //
- // NOTE: stage 4 parsing is executed on the final merged page only
- // once. i.e. it is not performed on the included pages.
- // NOTE: included pages are parsed in their own context.
- // NOTE: slots are parsed in the context of their containing page
- // and not in the location they are being placed.
- //
- // XXX support quoted text...
- parseElem: function(text, stage){
- var res = {}
-
- // @
()
- if(text[0] == '@'){
- var d = text.match(/@([a-zA-Z-_:]*)\(([^)]*)\)/)
-
- res.text = ''
- res.name = d[1]
- var args = res.args = {}
-
- // XXX support escaped quotes...
- //var a = d[2].split(/\s+/g)
- var a = d[2]
- .split(/((['"]).*?\2)|\s+/g)
- // cleanup...
- .filter(function(e){ return e && e != '' && !/^['"]$/.test(e)})
- // remove quotes...
- .map(function(e){ return /^(['"]).*\1$/.test(e) ? e.slice(1, -1) : e })
-
- a.forEach(function(e, i){
- args[((stage[res.name] || {}).macro_args || [])[i] || i] = e
- })
-
- // XXX not sure about this....
- //if(args.text){
- // res.text = args.text
- //}
-
- // html-like...
- } else {
- var elem = res.elem = $('').html(text).children().eq(0)
- res.name = elem.prop('tagName').toLowerCase()
-
- var args = res.args = {}
- var a = elem.prop('attributes')
-
- for(var i=0; i
look inside...
- : m.elem && m.text != ''?
- m.elem.html(_parse(context, m.text, macro))[0].outerHTML
- // else nothing changed...
- : match
- })
- }
-
- // macro...
- text = _parse(context, text, this.macro)
-
- // filter...
- state.filters
- .concat(this.__filters__)
- // unique -- leave last occurance..
- .filter(function(k, i, lst){
- return k[0] != '-'
- // filter dupplicates...
- && lst.slice(i+1).indexOf(k) == -1
- // filter disabled...
- && lst.slice(0, i).indexOf('-' + k) == -1
- })
- // unique -- leave first occurance..
- //.filter(function(k, i, lst){ return lst.slice(0, i).indexOf(k) == -1 })
- // apply the filters...
- .forEach(function(f){
- var k = f
- // get filter aliases...
- var seen = []
- while(typeof(k) == typeof('str') && seen.indexOf(k) == -1){
- seen.push(k)
- k = that.filter[k]
- }
- // could not find the filter...
- if(!k){
- console.warn('Unknown filter:', f)
- return
- }
- // use the filter...
- text = k.call(that, context, text)
- })
-
- // merge includes...
- // XXX need to check for errors (includes list shorter/longer
- // than number of markers)...
- text = text.replace(RegExp(this.__include_marker__, 'g'), function(){
- var page = state.include.shift()
- // NOTE: we are quoting html here, this is done to prevent
- // included html from messing up the outer structure with
- // things like unclosed tags and stuff...
- // XXX can this be anything other than html?
- return $('')
- .append($('')
- .addClass('include')
- .attr('src', page.path)
- .html(page.parse({ slots: state.slots }, true)))
- .html()
- })
-
- // post macro...
- if(!skip_post){
- text = _parse(context, text, this.post_macro)
- }
-
- window.t = text
-
- return text
- },
-}
-
-
-// XXX should inline macros support named args???
-var macro2 = {
-
- __include_marker__: '__include_marker__',
-
// Abstract macro syntax:
// Inline macro:
// @macro(arg ..)
@@ -539,6 +225,21 @@ var macro2 = {
},
+ // Parsing:
+ // 1) expand macros
+ // 2) apply filters
+ // 3) merge and parse included pages:
+ // 1) expand macros
+ // 2) apply filters
+ // 4) expand post-macros
+ //
+ // NOTE: stage 4 parsing is executed on the final merged page only
+ // once. i.e. it is not performed on the included pages.
+ // NOTE: included pages are parsed in their own context.
+ // NOTE: slots are parsed in the context of their containing page
+ // and not in the location they are being placed.
+ //
+ // XXX support quoted text...
// XXX this expect a different macro signature:
// macro(context, element, state)
// -> text
@@ -909,7 +610,7 @@ var Wiki = {
'\\[[^\\]]+\\]',
].join('|') +')', 'g'),
- __macro_parser__: macro2,
+ __macro_parser__: macro,
// Resolve '.' and '..' relative to current page...