mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-16 16:11:39 +00:00
cleanup and tweaking...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
95f803ce00
commit
e3246c7fb2
163
pwiki/page.js
163
pwiki/page.js
@ -505,7 +505,7 @@ object.Constructor('Page', BasePage, {
|
||||
QUOTING_MACROS: ['quote'],
|
||||
|
||||
// templates used to render a page via .text
|
||||
PAGE_TEMPLATE: '_text',
|
||||
PAGE_TEMPLATE: '_view',
|
||||
|
||||
// NOTE: comment this out to make the system fail when nothing is
|
||||
// resolved, not even the System/NotFound page...
|
||||
@ -658,6 +658,7 @@ object.Constructor('Page', BasePage, {
|
||||
// the context, this potentially can lead to false positives.
|
||||
//
|
||||
// XXX should this be lazy???
|
||||
// XXX should we use .__parser__.expand(..) instead of .parse(..) ???
|
||||
include: Macro(
|
||||
['src', 'recursive', 'join', ['isolated']],
|
||||
async function(args, body, state, key='included', handler){
|
||||
@ -758,6 +759,7 @@ object.Constructor('Page', BasePage, {
|
||||
// XXX need to handle pattern paths (like include: join=...)
|
||||
// XXX need a way to escape macros -- i.e. include </quote> in a quoted text...
|
||||
quote: Macro(
|
||||
//['src', 'filter', 'text', 'join'],
|
||||
['src', 'filter', 'text'],
|
||||
async function(args, body, state){
|
||||
var src = args.src //|| args[0]
|
||||
@ -866,12 +868,18 @@ object.Constructor('Page', BasePage, {
|
||||
// show first instance...
|
||||
: name in slots)
|
||||
|
||||
slots[name] = [...await this.__parser__.expand(this, text, state)]
|
||||
// NOTE: we prioritize the nested slots over the current...
|
||||
delete slots[name]
|
||||
var slot = await this.__parser__.expand(this, text, state)
|
||||
slots[name] =
|
||||
slots[name]
|
||||
?? slot
|
||||
|
||||
return hidden ?
|
||||
''
|
||||
: function(state){
|
||||
return state.slots[name] } }),
|
||||
'slot-content': ['slot'],
|
||||
|
||||
//
|
||||
// <macro src=<url>> .. </macro>
|
||||
@ -969,7 +977,7 @@ object.Constructor('Page', BasePage, {
|
||||
&& (text || args['else'])){
|
||||
var else_block = _getBlock('else')
|
||||
return else_block ?
|
||||
[...await this.__parser__.expand(this, else_block, state)]
|
||||
await this.__parser__.expand(this, else_block, state)
|
||||
: undefined }
|
||||
|
||||
// sort pages...
|
||||
@ -980,15 +988,13 @@ object.Constructor('Page', BasePage, {
|
||||
var join_block = _getBlock('join')
|
||||
|
||||
// apply macro text...
|
||||
var res = await pages
|
||||
.map(function(page, i){
|
||||
var res = pages
|
||||
.map(function(page){
|
||||
return that.__parser__.expand(page, text, state) })
|
||||
return join_block ?
|
||||
res.between(await that.__parser__.expand(
|
||||
res.between(
|
||||
// render join block relative to the path before the first '*'...
|
||||
that.get(that.path.split(/\*/).shift()),
|
||||
join_block,
|
||||
state))
|
||||
await that.__parser__.expand(base, join_block, state))
|
||||
: res } }),
|
||||
|
||||
// nesting rules...
|
||||
@ -1200,10 +1206,10 @@ module.System = {
|
||||
// These are used to control how a page is rendered.
|
||||
//
|
||||
// pWiki has to have a template appended to any path, if one is not
|
||||
// given then "_text" is used internally.
|
||||
// given then "_view" is used internally.
|
||||
//
|
||||
// A template is rendered in the context of the parent page, e.g.
|
||||
// for /path/to/page, the actual rendered template is /path/to/page/_text
|
||||
// for /path/to/page, the actual rendered template is /path/to/page/_view
|
||||
// and it is rendered from /path/to/page.
|
||||
//
|
||||
// A template is any page named starting with an underscore ("_")
|
||||
@ -1217,10 +1223,10 @@ module.System = {
|
||||
//
|
||||
// XXX all of these should support pattern pages...
|
||||
_text: {
|
||||
//text: '@include(. isolated join="@source(file-separator)")' },
|
||||
// XXX problem: the show slot
|
||||
text: '@include(. isolated join="@source(file-separator)")' },
|
||||
_view: {
|
||||
text: object.doc`
|
||||
<slot name="header">@source(./path)/_edit</slot>
|
||||
<slot name="header">/list @source(./path)/_edit</slot>
|
||||
<hr>
|
||||
<slot name="content"></slot>
|
||||
<hr>
|
||||
@ -1239,7 +1245,22 @@ module.System = {
|
||||
'<macro src="." join="@source(file-separator)">'
|
||||
+'<pre wikiwords="no"><quote filter="quote-tags" src="."/></pre>'
|
||||
+'</macro>'},
|
||||
// XXX can we reuse _text here???
|
||||
/* XXX can we reuse _view here???
|
||||
_edit: {
|
||||
text:
|
||||
'@include(PageTemplate)'
|
||||
+'<slot name="header">@source(./path)</slot>'
|
||||
+'<slot name="content">'
|
||||
+'<macro src="." join="@source(file-separator)">'
|
||||
+'<pre class="editor" '
|
||||
+'wikiwords="no" '
|
||||
+'contenteditable '
|
||||
+'oninput="saveContent(\'@source(./path)\', this.innerText)">'
|
||||
+'<quote filter="quote-tags" src="."/>'
|
||||
+'</pre>'
|
||||
+'</macro>'
|
||||
+'</slot>'},
|
||||
/*/
|
||||
_edit: {
|
||||
text:
|
||||
'@source(./path)'
|
||||
@ -1252,13 +1273,30 @@ module.System = {
|
||||
+'<quote filter="quote-tags" src="."/>'
|
||||
+'</pre>'
|
||||
+'</macro>'},
|
||||
//*/
|
||||
edit: {
|
||||
text:
|
||||
//'@include(PageTemplate)'
|
||||
'@include(_view)'
|
||||
+'<slot name="header">@source(../path)</slot>'
|
||||
+'<slot name="content">'
|
||||
// XXX for some reason this is not called...
|
||||
+'<macro src=".." join="@source(file-separator)">'
|
||||
+'<pre class="editor" '
|
||||
+'wikiwords="no" '
|
||||
+'contenteditable '
|
||||
+'oninput="saveContent(\'@source(./path)\', this.innerText)">'
|
||||
+'<quote filter="quote-tags" src="."/>'
|
||||
+'</pre>'
|
||||
+'</macro>'
|
||||
+'</slot>'},
|
||||
|
||||
// XXX this does not yet work...
|
||||
// XXX "_test" breaks differently than "test"
|
||||
//_test: {
|
||||
test: {
|
||||
text: object.doc`
|
||||
@source(_text)
|
||||
@source(_view)
|
||||
<slot name="header">HEADER</slot>
|
||||
<slot name="content">CONTENT</slot>
|
||||
<slot name="footer">FOOTER</slot> `},
|
||||
@ -1269,68 +1307,41 @@ module.System = {
|
||||
|
||||
|
||||
list: {
|
||||
text: `<macro src="../*/path" join="@source(line-separator)">@source(.)</macro>` },
|
||||
text: object.doc`
|
||||
<slot name="header">
|
||||
/list
|
||||
<a href="#@source(../../path)/list">⇑</a>
|
||||
@source(../path)
|
||||
</slot>
|
||||
<macro src="../*" join="@source(line-separator)">
|
||||
<a href="#@source(./path)/list">↳</a>
|
||||
<a href="#@source(./path)">@source(./name)</a>
|
||||
<a href="#@source(./path)/delete">×</a>
|
||||
</macro>` },
|
||||
// XXX this is really slow...
|
||||
// XXX for some reason replacing both @quote(..) with @source(..) in
|
||||
// the links will break macro parsing...
|
||||
// XXX should this be all or tree???
|
||||
tree: {
|
||||
text: object.doc`
|
||||
<macro src="../*">
|
||||
<div>
|
||||
<a href="#@quote(./path)">@source(./name)</a>
|
||||
<a href="#@quote(./path)/delete">×</a>
|
||||
<a href="#@source(./path)">@source(./name)</a>
|
||||
<a href="#@source(./path)/delete">×</a>
|
||||
<div style="padding-left: 30px">
|
||||
@source(./tree)
|
||||
</div>
|
||||
</div>
|
||||
</macro>` },
|
||||
|
||||
// XXX this is somewhat broken...
|
||||
all: {
|
||||
text: `@include(../**/path join="<br>")`},
|
||||
info: {
|
||||
text: object.doc`
|
||||
# @source(./path)
|
||||
|
||||
- Render root: @source(./renderer)
|
||||
- Render root: @source(./renderer)
|
||||
|
||||
` },
|
||||
|
||||
// XXX tests...
|
||||
//
|
||||
test_page: function(){
|
||||
console.log('--- RENDERER:', this.render_root)
|
||||
console.log('--- PATH: ', this.path)
|
||||
console.log('--- REFERRER:', this.referrer)
|
||||
console.log('--- PAGE:', this)
|
||||
return this.path },
|
||||
test_list: function(){
|
||||
return 'abcdef'.split('') },
|
||||
// XXX problem: it appears that we can't fill a slot from within a slot...
|
||||
// ...the "content" slot below does not override the content slot in _text
|
||||
test_base_slots: {
|
||||
text: object.doc`OUTER
|
||||
<slot name="header">HEADER</slot>
|
||||
<slot name="content">CONTENT</slot>
|
||||
<slot name="footer">FOOTER</SLOT> `},
|
||||
// XXX does not work yet...
|
||||
test_slots: {
|
||||
text: object.doc`
|
||||
Sequential:
|
||||
<slot name="sequential">unfilled</slot>
|
||||
<slot name="sequential">filled</slot>
|
||||
<slot name="sequential">refilled</slot>
|
||||
<br><br>
|
||||
Nested:
|
||||
<slot name="nested">
|
||||
unfilled
|
||||
<slot name="nested">
|
||||
filled
|
||||
<slot name="nested">
|
||||
refilled
|
||||
</slot>
|
||||
</slot>
|
||||
</slot> ` },
|
||||
Path: @source(../path)<br>
|
||||
Resolved path: @source(../resolved)<br>
|
||||
Referrer: @source(../referrer)<br>
|
||||
Renderer: @source(../renderer)<br>
|
||||
ctime: @source(../ctime)<br>
|
||||
mtime: @source(../mtime)<br>
|
||||
<hr>
|
||||
<pre wikiwords="no"><quote filter="quote-tags" src=".."/></pre> ` },
|
||||
|
||||
// page parts...
|
||||
//
|
||||
@ -1348,15 +1359,24 @@ module.System = {
|
||||
DeletingPage: {
|
||||
text: 'Deleting: @source(../path)' },
|
||||
|
||||
PageTemplate: {
|
||||
text: object.doc`
|
||||
<slot name="header">@source(./path)/_edit</slot>
|
||||
<hr>
|
||||
<slot name="content"></slot>
|
||||
<hr>
|
||||
<slot name="footer"></slot> ` },
|
||||
|
||||
|
||||
// page actions...
|
||||
//
|
||||
|
||||
|
||||
// metadata...
|
||||
//
|
||||
renderer: function(){
|
||||
return (this.render_root || {}).path },
|
||||
referrer: function(){
|
||||
return this.referrer || this.path },
|
||||
path: function(){
|
||||
return this.get('..').path },
|
||||
location: function(){
|
||||
@ -1366,9 +1386,9 @@ module.System = {
|
||||
name: function(){
|
||||
return this.get('..').name },
|
||||
ctime: function(){
|
||||
return this.get('..').data.ctime },
|
||||
return this.get('..').data.ctime ?? '' },
|
||||
mtime: function(){
|
||||
return this.get('..').data.mtime },
|
||||
return this.get('..').data.mtime ?? '' },
|
||||
|
||||
// XXX this can be a list for pattern paths...
|
||||
resolved: function(){
|
||||
@ -1412,6 +1432,11 @@ module.System = {
|
||||
// XXX System/forward
|
||||
// XXX System/sort
|
||||
// XXX System/reverse
|
||||
|
||||
|
||||
// XXX broken...
|
||||
test_list: function(){
|
||||
return 'abcdef'.split('') },
|
||||
}
|
||||
|
||||
var Settings =
|
||||
|
||||
@ -387,18 +387,13 @@ module.BaseParser = {
|
||||
|
||||
// Expand macros...
|
||||
//
|
||||
// <ast> ::= [ <item>, .. ]
|
||||
// <item> ::=
|
||||
// <string>
|
||||
// // returned by .macros.filter(..)
|
||||
// | {
|
||||
// // XXX is this still relevant...
|
||||
// filters: [
|
||||
// '<filter>'
|
||||
// | '-<filter>',
|
||||
// ...
|
||||
// ],
|
||||
// data: [ <item>, .. ],
|
||||
// }
|
||||
// <func>
|
||||
// | <promise>
|
||||
// | <string>
|
||||
// | { data: <ast> }
|
||||
// | <ast>
|
||||
//
|
||||
// XXX macros: we are mixing up ast state and parse state...
|
||||
// one should only be used for parsing and be forgotten after
|
||||
@ -440,13 +435,37 @@ module.BaseParser = {
|
||||
} else {
|
||||
yield res } } },
|
||||
|
||||
// recursively resolve and enumerate the ast...
|
||||
//
|
||||
// <ast> ::= [ <item>, .. ]
|
||||
// <item> ::=
|
||||
// <string>
|
||||
// | { data: <ast> }
|
||||
//
|
||||
// XXX should this also resolve e.data???
|
||||
resolve: async function*(page, ast, state={}){
|
||||
// NOTE: we need to await for ast here as we need stage 2 of
|
||||
// parsing to happen AFTER everything else completes...
|
||||
for(var e of await ast){
|
||||
e = typeof(e) == 'function' ?
|
||||
e.call(page, state)
|
||||
: e
|
||||
|
||||
if(e instanceof Array){
|
||||
yield* this.resolve(page, e, state)
|
||||
} else if(e instanceof Object && 'data' in e){
|
||||
yield { data: await this.resolve(page, e.data, state) }
|
||||
} else {
|
||||
yield e } } },
|
||||
|
||||
// Fully parse a page...
|
||||
//
|
||||
// This runs in two stages:
|
||||
// - expand the page
|
||||
// - resolve the page
|
||||
// - lex the page -- .lex(..)
|
||||
// - group block elements -- .group(..)
|
||||
// - expand macros -- .expand(..)
|
||||
// - resolve ast -- .resolve(..)
|
||||
// - apply filters
|
||||
//
|
||||
// NOTE: this has to synchronize everything between stage 1 (up to
|
||||
@ -458,7 +477,6 @@ module.BaseParser = {
|
||||
// them on demand rather than on encounter (as is now), e.g.
|
||||
// a slot when loaded will replace the prior occurrences...
|
||||
//
|
||||
// XXX this should be recursive....
|
||||
// XXX add a special filter to clear pending filters... (???)
|
||||
parse: async function(page, ast, state={}){
|
||||
var that = this
|
||||
@ -468,17 +486,7 @@ module.BaseParser = {
|
||||
this.expand(page, ast, state)
|
||||
: ast
|
||||
|
||||
// NOTE: we need to await for ast here as we need stage 2 of
|
||||
// parsing to happen AFTER everything else completes...
|
||||
return await Promise.iter((await ast)
|
||||
.flat()
|
||||
// post handlers...
|
||||
.map(function(section){
|
||||
return typeof(section) == 'function' ?
|
||||
// NOTE: this can produce promises...
|
||||
section.call(page, state)
|
||||
: section }))
|
||||
.flat()
|
||||
return await this.resolve(page, ast, state)
|
||||
// filters...
|
||||
.map(function(section){
|
||||
return (
|
||||
|
||||
@ -165,7 +165,7 @@ module.BaseStore = {
|
||||
.replace(/^\/|\/$/g, '')
|
||||
.replace(/\//g, '\\/')
|
||||
.replace(/\*\*/g, '.*')
|
||||
.replace(/\*/g, '[^\\/]*')
|
||||
.replace(/(?<=^|[\\\/]+|[^.])\*/g, '[^\\/]*')
|
||||
}(?=[\\\\\/]|$)`)
|
||||
return [...(await this.paths())
|
||||
// NOTE: we are not using .filter(..) here as wee
|
||||
|
||||
@ -179,11 +179,9 @@ pwiki.pwiki
|
||||
text: object.doc`
|
||||
Sequential:
|
||||
<slot name="sequential">unfilled</slot>
|
||||
|
||||
<slot name="sequential">filled</slot>
|
||||
|
||||
<slot name="sequential">refilled</slot>
|
||||
|
||||
<br><br>
|
||||
Nested:
|
||||
<slot name="nested">
|
||||
unfilled
|
||||
@ -194,6 +192,18 @@ pwiki.pwiki
|
||||
</slot>
|
||||
</slot>
|
||||
</slot> `, })
|
||||
.update({
|
||||
location: '/test/nesting',
|
||||
text: object.doc`
|
||||
Quote in macro:
|
||||
<macro src=".">
|
||||
<quote src="./path"/>
|
||||
</macro>
|
||||
<hr>
|
||||
Quote in slot:
|
||||
<slot name="moo">
|
||||
<quote src="./path"/>
|
||||
</slot>` })
|
||||
.update({
|
||||
location: '/test/a',
|
||||
text: 'a',
|
||||
|
||||
24
pwiki2.js
24
pwiki2.js
@ -1,33 +1,17 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
*
|
||||
* XXX nested slots do not seem to work...
|
||||
* XXX BUG: /** /paths -- does not work...
|
||||
* XXX might be a good idea for slots to support getting previous slot
|
||||
* content, e.g.:
|
||||
* <slot name="header"><slot-content/> new text</slot>
|
||||
* XXX BUG?: markdown: when parsing chunks each chunk gets an open/closed
|
||||
* <p> inserted at start/end -- this breaks stuff returned by macros...
|
||||
* ...there are two ways to dance around this:
|
||||
* - make filters run a bit more globaly -- per block...
|
||||
* - find a local parser...
|
||||
* XXX BUG?: empty stores do not appear to show up in listings...
|
||||
* ...this is expected but not intuitive...
|
||||
* might be a good idea to add a special path like /Stores to list
|
||||
* sub-stores...
|
||||
* XXX add something like /stores to list store info...
|
||||
* XXX OPTIMIZE: /tree is really slow...
|
||||
* ...is the problem purely in the async/await playing ping-pong???
|
||||
* XXX might be a good idea to make things optionally sync via a .sync()
|
||||
* method, or request a specific set of data (in the parser, after
|
||||
* collecting all the stuff needed and fetching it in one go)...
|
||||
* XXX might be a good idea to add page caching (state.page_cache) relative
|
||||
* to a path on parsing, to avoid re-matching the same page over and
|
||||
* over again from the same context
|
||||
* format:
|
||||
* {
|
||||
* <basedir>: {
|
||||
* <path>: <data>,
|
||||
* ...
|
||||
* },
|
||||
* ...
|
||||
* }
|
||||
* XXX BUG: FF: conflict between object.run and PouchDB...
|
||||
* XXX BUG: browser: .get('/*').raw hangs in the browser context...
|
||||
* XXX BUG?: /_tree for some reason does not show anything on lower levels...
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user