diff --git a/README.md b/README.md
index 6733951..f23f8f7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Portable Wiki (pWiki)
+# Portable Wiki (pWiki)
_NOTE: the project is currently in prototype phase, thus while most things
are likely to change, the implementation / API **will definitely** change! ;)_
diff --git a/bootstrap.js b/bootstrap.js
index 8cac713..d766288 100755
--- a/bootstrap.js
+++ b/bootstrap.js
@@ -1,3 +1,3 @@
// This file is generated automatically, all changes made here will be lost.
-var Bootstrap = {"Templates":{"text":"
\r\n\t\r\n\r\n\r\n\r\n\r\n"},"Doc/Macros":{"text":"# pWiki Macros\r\n\r\n## Syntax\r\n\r\nAny macro can be used in any of the two forms, either _inline_ or _HTML-like_.\r\n\r\nInline:\r\n```\r\n@macro-name(value)\r\n```\r\n\r\nHTML-style:\r\n```\r\n\r\n\r\n\r\n ...text...\r\n\r\n```\r\n\r\nThe two forms are almost identical, with the only difference being that the \r\ninline form does not support body text (note that some macros may provide\r\nthis functionality as an argument, namely `slot`).\r\n\r\nThe two forms exist to fill two distinct functions:\r\n- inline: compatible with attribute values and short\r\n- html-like: element-like, simpler when dealing with html\r\n\r\n### Escaping macros\r\n\r\nMacros can be escaped for inclusion in the page, the two types of macros \r\nare escaped a bit differently:\r\n\r\n- inline macros -- escaped by preceding with a `\\`\r\n\r\n ```\r\n \\\\@include(SomePage)\r\n ```\r\n\r\n Displayed in page as:\r\n\r\n \\@include(SomePage)\r\n\r\n _NOTE: if displayed on github, this will show an extra \"\\\" in both \r\n cases, this should be ignored as pWiki will consume the escaping \"\\\" \r\n in both the code example and the preview._\r\n\r\n\r\n- html-like macros -- escaped _the HTML way_\r\n\r\n ```\r\n <include src=\"SomePage\"\\>\r\n ```\r\n\r\n Displayed in page as:\r\n\r\n <include src=\"SomePage\"\\\\>\r\n\r\n\r\n\r\n\r\n## Macros\r\n\r\n### now ()\r\n\r\nGet current date in seconds since epoch, this is equivalet Javascript's\r\n`Date.now()`.\r\n\r\nThis is mostly used for automatically creating paths (see: todo / outline)\r\n\r\n\r\n### filter (name)\r\n\r\nEnable or disable a page filter.\r\n\r\nA filter is a way to transform the page source.\r\n\r\nArguments:\r\n- `name` -- filter name. If name is preceded with a '-' then it \r\nwill be forced off. This is useful for disabling _default_ filters, or \r\nfilters added previously in templates.\r\n\r\nFilters:\r\n- wikiword (default)\r\n- markdown\r\n\r\nExample:\r\n- `[./_edit]` -- see the macro at the end of the page.\r\n\r\n\r\n### include (src isolated text)\r\n\r\nInclude a page. The included page is rendered independently from current\r\npage and is inserted as-is in macro body.\r\n\r\nNote that this will produce a `include` tag in the code that contains \r\nthe included page, this makes this tag not suitable for use anywhere \r\nbut an html element body.\r\n\r\nArguments:\r\n- `src` -- path to source page.\r\n- `isolated` -- prevent slots from included page from affecting the including page. \r\n- `text` -- is used when recursive include is detected and ignored otherwise.\r\n\r\n### source (src) / quote (src)\r\n\r\nInsert a page without rendering. This is similar to include but will not\r\nrender the page. \r\n\r\nThe difference between `source` and `quote` is:\r\n- _source_ includes the page as-is\r\n- _quotes_ escapes the page (i.e. _quotes_ it's source) for its code to \r\n display in the rendered HTML correctly.\r\n\r\nArguments:\r\n- `src` -- path to source page.\r\n\r\n\r\n\r\n### slot (name text)\r\n\r\nDefine or fill a slot.\r\n\r\nFirst occurrence of a `name` will _define_ a slot and fill it with `text`.\r\nEach new occurrence of a name will change slot content.\r\n\r\n\r\n### macro (name src text) / else ()\r\n\r\nApply macro to source page and include the result.\r\n\r\nThis is similar to include but does not require a separate page.\r\n\r\nBoth `name` and `src` are optional.\r\n\r\nIf `name` is given a _named macro_ is defined. This macro can be later \r\nreferenced (used) by name. A named macro can be redefined/overridden.\r\n\r\nIf `src` is given a macro is applied to a specific page or range of pages\r\n(see: WikiPath).\r\n\r\nFor a macro to be useful it must have a body (`text`), either defined as\r\na named macro or in the current macro.\r\n\r\nArguments:\r\n- `name` -- macro name (optional).\r\n- `src` -- path to source page (optional).\r\n\r\n\r\n`else` macro is applicable inside `macro`. it is used when the `src` path\r\nof `macro` matches no pages.\r\n\r\n\r\n\r\n\r\n"},"Doc/Path":{"text":""},"System/style":{"text":"body {\r\n\tfont-family: /*worksans,*/ opensans, sans-serif;\r\n}\r\n\r\n.raw,\r\n.text {\r\n\tdisplay: block;\r\n}\r\n\r\n.item.checked {\r\n\topacity: 0.3;\r\n}\r\n.item.checked:hover {\r\n\topacity: 0.8;\r\n}\r\n.item.checked .item-content * {\r\n\ttext-decoration: line-through;\r\n}\r\n\r\n.button {\r\n\ttext-decoration: none;\r\n}\r\n.button:last-child {\r\n\tmargin-right: 5px;\r\n}\r\n\r\n.separator~* {\r\n\tfloat: right;\r\n}\r\n\r\npre {\r\n\tdisplay: block;\r\n\tbackground-color: rgba(0, 0, 0, 0.05);\r\n\tpadding: 5px;\r\n}\r\n\r\n.item:hover {\r\n}\r\n.item .button {\r\n\tdisplay: none;\r\n}\r\n.item:hover .button {\r\n\tdisplay: inline-block;\r\n}\r\n\r\n.sort-handle {\r\n\topacity: 0.1;\r\n\tpadding-left: 5px;\r\n\tpadding-right: 5px;\r\n\tcursor: pointer;\r\n\ttext-decoration: none;\r\n}\r\n.item:hover .sort-handle {\r\n\topacity: 0.3;\r\n}\r\n.sort-placeholder {\r\n\tdisplay: block;\r\n}\r\n\r\n/* vim:set ts=4 sw=4 ft=css : */\r\n"},"Templates/all_pages":{"text":"\r\n\t
\r\n \r\n\r\n\r\n\t\r\n\r\n\r\n\r\nhome\r\n\r\n\r\n"},"Doc/About":{"text":"# Portable Wiki (pWiki)\n\n_NOTE: the project is currently in prototype phase, thus while most things \nare likely to change, the implementation / API **will definitely** change! ;)_\n\n### Project goals / main features:\n\n- _Simple embeddable Wiki_\n\n To be used as a zero-workflow app documentation platform, i.e. \n documentation that can be created, edited, tweaked and updated in-app \n without requiring setting up and maintaining a write-convert-embed \n workflow.\n\n This was a requirement on the _ImageGrid.Viewer_ project and as a \n side-effect pWiki hosts it's own documentation too.\n\n- _Pluggable storage and synchronization_ mechanisms\n\n A set of tools and API's to enable data synchronization between pWiki\n instances.\n\n- _Self-hosted_ and flexible user interface\n\n The pWiki interface is implemented as a set of pWiki pages and \n templates within pWiki itself (see: [Templates] / [/bootstrap](bootstrap)), \n this enables the user to customize the look feel and to some extent \n the function of the interface from within pWiki, without touching the \n code.\n\n- pWiki _portable app_\n\n This is a simple note / todo / outline app.\n\n The pWiki app is a stand-alone instance of pWiki wrapped in an app \n supporting all major desktop as well as mobile platforms.\n\n The app serves the following goals:\n\n - a simple and functional note / todo / outline app (obviously)\n - an external/portable Wiki editor, as an alternative for \n in-target-app documentation editor with ability to seamlesly \n synchronize with the target app pWiki instance.\n - a stand-alone testing platform and reference implementation for \n pWiki components.\n\n\n### General Documentation:\n- [Doc/About] / [general info](README.md) -- This document.\n- [Doc/Path] / [bootstrap path](bootstrap/Doc/Path.md) -- Path mechanics.\n- [Doc/Macros] / [bootstrap macros](bootstrap/Doc/Macros.md) -- Macro documentation\n\n\n\n\n"},"WikiHome":{"text":"@include(Doc/About)"}}
\ No newline at end of file
+var Bootstrap = {"Templates":{"text":"
\r\n\t\r\n\r\n\r\n\r\n\r\n"},"Doc/Macros":{"text":"# pWiki Macros\r\n\r\n## Syntax\r\n\r\nAny macro can be used in any of the two forms, either _inline_ or _HTML-like_.\r\n\r\nInline:\r\n```\r\n@macro-name(value)\r\n```\r\n\r\nHTML-style:\r\n```\r\n\r\n\r\n\r\n ...text...\r\n\r\n```\r\n\r\nThe two forms are almost identical, with the only difference being that the \r\ninline form does not support body text (note that some macros may provide\r\nthis functionality as an argument, namely `slot`).\r\n\r\nThe two forms exist to fill two distinct functions:\r\n- inline: compatible with attribute values and short\r\n- html-like: element-like, simpler when dealing with html\r\n\r\n### Escaping macros\r\n\r\nMacros can be escaped for inclusion in the page, the two types of macros \r\nare escaped a bit differently:\r\n\r\n- inline macros -- escaped by preceding with a `\\`\r\n\r\n ```\r\n \\\\@include(SomePage)\r\n ```\r\n\r\n Displayed in page as:\r\n\r\n \\@include(SomePage)\r\n\r\n _NOTE: if displayed on github, this will show an extra \"\\\" in both \r\n cases, this should be ignored as pWiki will consume the escaping \"\\\" \r\n in both the code example and the preview._\r\n\r\n\r\n- html-like macros -- escaped _the HTML way_\r\n\r\n ```\r\n <include src=\"SomePage\"\\>\r\n ```\r\n\r\n Displayed in page as:\r\n\r\n <include src=\"SomePage\"\\\\>\r\n\r\n\r\n\r\n\r\n## Macros\r\n\r\n### now ()\r\n\r\nGet current date in seconds since epoch, this is equivalet Javascript's\r\n`Date.now()`.\r\n\r\nThis is mostly used for automatically creating paths (see: todo / outline)\r\n\r\n\r\n### filter (name)\r\n\r\nEnable or disable a page filter.\r\n\r\nA filter is a way to transform the page source.\r\n\r\nArguments:\r\n- `name` -- filter name. If name is preceded with a '-' then it \r\nwill be forced off. This is useful for disabling _default_ filters, or \r\nfilters added previously in templates.\r\n\r\nFilters:\r\n- wikiword (default)\r\n- markdown\r\n\r\nExample:\r\n- `[./_edit]` -- see the macro at the end of the page.\r\n\r\n\r\n### include (src isolated text)\r\n\r\nInclude a page. The included page is rendered independently from current\r\npage and is inserted as-is in macro body.\r\n\r\nNote that this will produce a `include` tag in the code that contains \r\nthe included page, this makes this tag not suitable for use anywhere \r\nbut an html element body.\r\n\r\nArguments:\r\n- `src` -- path to source page.\r\n- `isolated` -- prevent slots from included page from affecting the including page. \r\n- `text` -- is used when recursive include is detected and ignored otherwise.\r\n\r\n### source (src) / quote (src)\r\n\r\nInsert a page without rendering. This is similar to include but will not\r\nrender the page. \r\n\r\nThe difference between `source` and `quote` is:\r\n- _source_ includes the page as-is\r\n- _quotes_ escapes the page (i.e. _quotes_ it's source) for its code to \r\n display in the rendered HTML correctly.\r\n\r\nArguments:\r\n- `src` -- path to source page.\r\n\r\n\r\n\r\n### slot (name text)\r\n\r\nDefine or fill a slot.\r\n\r\nFirst occurrence of a `name` will _define_ a slot and fill it with `text`.\r\nEach new occurrence of a name will change slot content.\r\n\r\n\r\n### macro (name src text) / else ()\r\n\r\nApply macro to source page and include the result.\r\n\r\nThis is similar to include but does not require a separate page.\r\n\r\nBoth `name` and `src` are optional.\r\n\r\nIf `name` is given a _named macro_ is defined. This macro can be later \r\nreferenced (used) by name. A named macro can be redefined/overridden.\r\n\r\nIf `src` is given a macro is applied to a specific page or range of pages\r\n(see: WikiPath).\r\n\r\nFor a macro to be useful it must have a body (`text`), either defined as\r\na named macro or in the current macro.\r\n\r\nArguments:\r\n- `name` -- macro name (optional).\r\n- `src` -- path to source page (optional).\r\n\r\n\r\n`else` macro is applicable inside `macro`. it is used when the `src` path\r\nof `macro` matches no pages.\r\n\r\n\r\n\r\n\r\n"},"Doc/Path":{"text":""},"System/style":{"text":"body {\r\n\tfont-family: /*worksans,*/ opensans, sans-serif;\r\n}\r\n\r\n.raw,\r\n.text {\r\n\tdisplay: block;\r\n}\r\n\r\n.item.checked {\r\n\topacity: 0.3;\r\n}\r\n.item.checked:hover {\r\n\topacity: 0.8;\r\n}\r\n.item.checked .item-content * {\r\n\ttext-decoration: line-through;\r\n}\r\n\r\n.button {\r\n\ttext-decoration: none;\r\n}\r\n.button:last-child {\r\n\tmargin-right: 5px;\r\n}\r\n\r\n.separator~* {\r\n\tfloat: right;\r\n}\r\n\r\npre {\r\n\tdisplay: block;\r\n\tbackground-color: rgba(0, 0, 0, 0.05);\r\n\tpadding: 5px;\r\n}\r\n\r\n.item:hover {\r\n}\r\n.item .button {\r\n\tdisplay: none;\r\n}\r\n.item:hover .button {\r\n\tdisplay: inline-block;\r\n}\r\n\r\n.sort-handle {\r\n\topacity: 0.1;\r\n\tpadding-left: 5px;\r\n\tpadding-right: 5px;\r\n\tcursor: pointer;\r\n\ttext-decoration: none;\r\n}\r\n.item:hover .sort-handle {\r\n\topacity: 0.3;\r\n}\r\n.sort-placeholder {\r\n\tdisplay: block;\r\n}\r\n\r\n/* vim:set ts=4 sw=4 ft=css : */\r\n"},"Templates/all_pages":{"text":"\r\n\t
\r\n \r\n\r\n\r\n\t\r\n\r\n\r\n\r\nhome\r\n\r\n\r\n"},"Doc/About":{"text":"# Portable Wiki (pWiki)\n\n_NOTE: the project is currently in prototype phase, thus while most things \nare likely to change, the implementation / API **will definitely** change! ;)_\n\n### Project goals / main features:\n\n- _Simple embeddable Wiki_\n\n To be used as a zero-workflow app documentation platform, i.e. \n documentation that can be created, edited, tweaked and updated in-app \n without requiring setting up and maintaining a write-convert-embed \n workflow.\n\n This was a requirement on the _ImageGrid.Viewer_ project and as a \n side-effect pWiki hosts it's own documentation too.\n\n- _Pluggable storage and synchronization_ mechanisms\n\n A set of tools and API's to enable data synchronization between pWiki\n instances.\n\n- _Self-hosted_ and flexible user interface\n\n The pWiki interface is implemented as a set of pWiki pages and \n templates within pWiki itself (see: [Templates] / [/bootstrap](bootstrap)), \n this enables the user to customize the look feel and to some extent \n the function of the interface from within pWiki, without touching the \n code.\n\n- pWiki _portable app_\n\n This is a simple note / todo / outline app.\n\n The pWiki app is a stand-alone instance of pWiki wrapped in an app \n supporting all major desktop as well as mobile platforms.\n\n The app serves the following goals:\n\n - a simple and functional note / todo / outline app (obviously)\n - an external/portable Wiki editor, as an alternative for \n in-target-app documentation editor with ability to seamlesly \n synchronize with the target app pWiki instance.\n - a stand-alone testing platform and reference implementation for \n pWiki components.\n\n\n### General Documentation:\n- [Doc/About] / [general info](README.md) -- This document.\n- [Doc/Path] / [bootstrap path](bootstrap/Doc/Path.md) -- Path mechanics.\n- [Doc/Macros] / [bootstrap macros](bootstrap/Doc/Macros.md) -- Macro documentation\n\n\n\n\n"},"WikiHome":{"text":"@include(Doc/About)"}}
\ No newline at end of file
diff --git a/bootstrap/Doc/Macros.md b/bootstrap/Doc/Macros.md
index 7d5c85c..efc3a39 100644
--- a/bootstrap/Doc/Macros.md
+++ b/bootstrap/Doc/Macros.md
@@ -1,4 +1,4 @@
-# pWiki Macros
+# pWiki Macros
## Syntax
diff --git a/index.html b/index.html
index 83b46d6..ffe1bb2 100755
--- a/index.html
+++ b/index.html
@@ -48,14 +48,15 @@ var save = () => {
}
var reload = () => {
+ // load the page...
$('.wiki')
.html(Wiki.title[0] == '_' ? Wiki.text : Wiki.get('./_view').text)
.ready(update_editor)
save()
- $('title').text(Wiki.location)
-
+ // checkbox state...
+ // XXX move this to post-filters...
$('input[type="checkbox"].state')
// initial state...
.each(function(){
@@ -84,6 +85,7 @@ var reload = () => {
}
var update_editor = function(){
+ // XXX move this to post-filters...
$('.sortable')
.sortable({
handle: ".sort-handle",
@@ -95,6 +97,7 @@ var update_editor = function(){
// XXX make this update on enter...
// XXX account for title of edited page...
+ // XXX move this to post-filters...
$('.title')
.focus(function(){
var to = $(this).attr('saveto') || '.'
@@ -120,6 +123,7 @@ var update_editor = function(){
/*
// live update text...
// XXX is this the right way to go for large documents???
+ // XXX move this to post-filters...
var text = $('.text')
.focus(function(){
console.log('EDITING:', Wiki.path)
@@ -159,6 +163,7 @@ var update_editor = function(){
//text.html(Wiki.get(text.attr('saveto')).text)
+ // XXX move this to post-filters...
var raw = $('.raw')
.focus(function(){
var to = $(this).attr('saveto') || '.'
diff --git a/wiki.js b/wiki.js
index 8fe2827..cf03317 100755
--- a/wiki.js
+++ b/wiki.js
@@ -112,6 +112,11 @@ var macro = {
'wikiword',
'noscript',
],
+ __post_filters__: [
+ //'noscript',
+ 'title',
+ 'editor',
+ ],
// Macros...
//
@@ -396,6 +401,51 @@ var macro = {
},
+ // Post-filters...
+ //
+ // These are run on the final page.
+ //
+ // The main goal is to setup editors and other active stuff that the
+ // user should not have direct access to, but that should be
+ // configurable per instance...
+ //
+ // for tech and other details see .filter
+ //
+ post_filter: {
+ noscript: function(context, elem){
+ // XXX
+ return elem
+ },
+
+ title: function(context, elem){
+ elem = $(elem)
+ var title = elem.find('.text h1').first()
+
+ // show first H1 as title...
+ if(elem.find('.text').text().trim().indexOf(title.text().trim()) == 0){
+ title.detach()
+ elem.find('slot[name="title"]').html(title.html())
+ $('title').html(title.text())
+
+ // show location...
+ } else {
+ $('title').text(context.location)
+ }
+
+ return elem
+ },
+ // XXX this needs save/reload...
+ editor: function(context, elem){
+ // XXX title
+ // XXX text
+ // XXX raw
+ // XXX checkbox
+
+ return elem
+ },
+ },
+
+
// Parsing:
// 1) expand macros
// 2) apply filters
@@ -528,41 +578,42 @@ var macro = {
return parsed
}
-
+ var _filter = function(lst, filters){
+ lst
+ // 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 = filters[k]
+ }
+ // could not find the filter...
+ if(!k){
+ //console.warn('Unknown filter:', f)
+ return
+ }
+ // use the filter...
+ parsed = k.call(that, context, parsed)
+ })
+ }
// macro stage...
_parse(context, parsed, this.macro)
// filter stage...
- 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...
- parsed = k.call(that, context, parsed)
- })
+ _filter(state.filters.concat(this.__filters__), this.filter)
// merge includes...
parsed
@@ -597,12 +648,6 @@ var macro = {
}).join('\n')
}))
- console.log('>>>>',
- context.path,
- skip_post,
- parsed.find(':not([isolated="true"]) slot').length,
- parsed.find('[isolated="true"] slot').length)
-
// post processing...
if(!skip_post){
// fill slots...
@@ -651,6 +696,10 @@ var macro = {
// && _parse(context, parsed, this.post_macro)
}
+ // post-filter stage...
+ // XXX get list from context.config...
+ _filter(this.__post_filters__, this.post_filter)
+
// XXX shuld we get rid of the root span???
return parsed.contents()
},
@@ -919,7 +968,7 @@ var PathActions = {
var Wiki = {
__wiki_data: data,
- __config_page__: 'System/Settings',
+ __config_page__: 'System/settings',
__home_page__: 'WikiHome',
@@ -1271,7 +1320,7 @@ var Wiki = {
return this.title == 'raw' ? this.raw
: this.__macro_parser__.parse(this, this.raw) },
get code(){
- return this.text.html() },
+ return this.text.text() },
// NOTE: this is set by setting .text