mirror of
https://github.com/flynx/pWiki.git
synced 2026-08-24 08:16:43 +00:00
bugfix + tests + docs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
acf37a4832
commit
b879049346
@ -7,6 +7,8 @@ Any macro can be used in any of the two forms, either _inline_ or _HTML-like_.
|
|||||||
Inline:
|
Inline:
|
||||||
```
|
```
|
||||||
@macro-name(value)
|
@macro-name(value)
|
||||||
|
|
||||||
|
@macro-name(value text=" ...text... ")
|
||||||
```
|
```
|
||||||
|
|
||||||
HTML-style:
|
HTML-style:
|
||||||
@ -27,6 +29,28 @@ The two forms exist to fill two distinct functions:
|
|||||||
- html-like: element-like, simpler when dealing with html
|
- html-like: element-like, simpler when dealing with html
|
||||||
|
|
||||||
|
|
||||||
|
### Positional and keyword attributes
|
||||||
|
|
||||||
|
Attributes (arguments) can be set sequentially by value, as they are
|
||||||
|
defined or by name in any order.
|
||||||
|
|
||||||
|
The following are equivalent:
|
||||||
|
```
|
||||||
|
<slot abc "some text"/>
|
||||||
|
<slot name=abc text="some text"/>
|
||||||
|
<slot "some text" name=abc/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Keyword attributes are special attributes that are given by name rather
|
||||||
|
than by value by default and if no value is set explicitly it defaults
|
||||||
|
to `true` if passed, and to false if omitted.
|
||||||
|
|
||||||
|
The following are equivalent:
|
||||||
|
```
|
||||||
|
<slot some-name hidden/>
|
||||||
|
<slot some-name hidden=true/>
|
||||||
|
```
|
||||||
|
|
||||||
### Special attributes
|
### Special attributes
|
||||||
|
|
||||||
Two special attributes are handled differently: `text` and `body`, these
|
Two special attributes are handled differently: `text` and `body`, these
|
||||||
@ -108,6 +132,7 @@ This will enable writing documents (mainly in _markdown_) that are usable
|
|||||||
bot from within pWiki as well as outside.
|
bot from within pWiki as well as outside.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Macros
|
## Macros
|
||||||
|
|
||||||
### now ()
|
### now ()
|
||||||
@ -132,33 +157,56 @@ use.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### slot (<name> <text> shown|hidden)
|
### slot (<name> <text> shown|hidden) / content
|
||||||
|
|
||||||
```
|
```
|
||||||
\@slot(<name>)
|
@slot(<name>)
|
||||||
\@slot(<name> <text>)
|
@slot(<name> <text>)
|
||||||
\@slot(<name> <text> hidden)
|
@slot(<name> <text> hidden)
|
||||||
\@slot(<name> <text> shown)
|
@slot(<name> <text> shown)
|
||||||
|
|
||||||
|
<slot <name> ...>
|
||||||
|
...
|
||||||
|
<content/>
|
||||||
|
...
|
||||||
|
</slot>
|
||||||
```
|
```
|
||||||
|
|
||||||
Define or fill a slot.
|
Define or fill a slot.
|
||||||
|
|
||||||
First occurrence of a slot `name` will _define_ a slot and set its value
|
First occurrence of a slot `name` will _define_ a slot and set its value
|
||||||
(fill it) with `text` if given.
|
(fill it) with `text` if given.
|
||||||
Each new occurrence of a name will override slot content.
|
Each new occurrence of a slot with the same name will override slot content.
|
||||||
|
|
||||||
Only the first occurance of the `name` slot macro is displayed by default.
|
Only the first occurance of the `name` slot macro is displayed by default.
|
||||||
|
|
||||||
Slot display can be explicitly controlled via the `hidden` and `shown`
|
Slot display can be explicitly controlled via the `hidden` and `shown`
|
||||||
keywords, if both are given `hidden` has precedence.
|
keywords, if both are given `hidden` has precedence. All _shown_ slots of
|
||||||
|
the same name will display the same value.
|
||||||
|
|
||||||
Nested slots are processed in order of occurrence, i.e. a nested slot can
|
Nested slots are processed in order of occurrence, i.e. a nested slot can
|
||||||
override it's parent's value.
|
override it's parent's value.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
```
|
```
|
||||||
<slot X> some text <slot X "new text"/></slot>
|
<slot X>
|
||||||
|
some text
|
||||||
|
<slot X "new text"/>
|
||||||
|
</slot>
|
||||||
```
|
```
|
||||||
Will resolve to: `new text`
|
Will resolve to: `new text`
|
||||||
|
|
||||||
|
`<content/>` / `@content()` if encountered will be replaced with previous
|
||||||
|
slot value.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
<slot X text="some text"/>
|
||||||
|
|
||||||
|
<slot X>[[ <content/> ]]</slot>
|
||||||
|
```
|
||||||
|
Will resolve to `[[ some text ]]`
|
||||||
|
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
@ -182,7 +230,7 @@ Will resolve to: `new text`
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### filter (name)
|
### filter (name)
|
||||||
|
|
||||||
|
|||||||
@ -1309,6 +1309,13 @@ module.parser = {
|
|||||||
// ...
|
// ...
|
||||||
// </slot>
|
// </slot>
|
||||||
//
|
//
|
||||||
|
// Wrap previous value of slot
|
||||||
|
// <slot name=<name>>
|
||||||
|
// ...
|
||||||
|
// <content/>
|
||||||
|
// ...
|
||||||
|
// </slot>
|
||||||
|
//
|
||||||
// Force show a slot...
|
// Force show a slot...
|
||||||
// <slot shown ... />
|
// <slot shown ... />
|
||||||
//
|
//
|
||||||
@ -1325,12 +1332,9 @@ module.parser = {
|
|||||||
// all other slots with <name> will replace its content, unless
|
// all other slots with <name> will replace its content, unless
|
||||||
// explicit shown/hidden arguments are given.
|
// explicit shown/hidden arguments are given.
|
||||||
// NOTE: hidden has precedence over shown if both are given.
|
// NOTE: hidden has precedence over shown if both are given.
|
||||||
// XXX revise...
|
|
||||||
//
|
//
|
||||||
// XXX do we need to be able to insert previous slot value???
|
// XXX can there be a situation where not all <content/> elements
|
||||||
// ...this was implemented via <content/>, but the naming
|
// are cleared???
|
||||||
// was not obvious, should be something like <overridden/>
|
|
||||||
// or <previous/>...
|
|
||||||
// XXX revise the use of hidden/shown use mechanic and if it's
|
// XXX revise the use of hidden/shown use mechanic and if it's
|
||||||
// needed...
|
// needed...
|
||||||
slot: Macro(
|
slot: Macro(
|
||||||
@ -1358,34 +1362,43 @@ module.parser = {
|
|||||||
|
|
||||||
// set slot value...
|
// set slot value...
|
||||||
//
|
//
|
||||||
// NOTE: the slots are filled sequentially, in
|
|
||||||
// order of opening elements, rather than
|
|
||||||
// topologically, i.e. filled on the way down
|
|
||||||
// the tree vs. up.
|
|
||||||
var slot = slots[name] ??= []
|
var slot = slots[name] ??= []
|
||||||
// NOTE: the placeholder is a stand-in for our
|
// NOTE: the placeholder is a stand-in for our
|
||||||
// current value that is still to be generated.
|
// current value that is still to be generated...
|
||||||
var placeholder = [...(0 in slot ? slot : [])]
|
var placeholder = [...slot]
|
||||||
slot.splice(0, slot.length, placeholder)
|
slot.splice(0, slot.length, placeholder)
|
||||||
// expand slot body...
|
// expand body...
|
||||||
body = body ?
|
body = body ?
|
||||||
parser.expand(this, body ?? [], state)
|
parser.expand(this, body ?? [], state)
|
||||||
: body
|
: body
|
||||||
// if slot not overriden, write our value...
|
// if slot not overriden, write our value...
|
||||||
if(slot[0] === placeholder){
|
if(slot[0] === placeholder){
|
||||||
slot.splice(0, 1,
|
slot.splice(0, slot.length,
|
||||||
...(body != null ?
|
...(body != null ?
|
||||||
[body]
|
[body]
|
||||||
: placeholder)) }
|
: placeholder))
|
||||||
|
// placeholder -> <content/>
|
||||||
|
body = placeholder }
|
||||||
|
// <content/> -- handle slot's original value...
|
||||||
|
slot[0] =
|
||||||
|
body.flat().length > 0
|
||||||
|
&& slot[0] instanceof Array ?
|
||||||
|
slot[0]
|
||||||
|
.map(function(e){
|
||||||
|
if(e && e.name == 'content'){
|
||||||
|
return body }
|
||||||
|
return e })
|
||||||
|
: slot[0]
|
||||||
|
|
||||||
return hidden ?
|
return hidden ?
|
||||||
''
|
''
|
||||||
: Object.assign(
|
: Object.assign(
|
||||||
// stage II: place the latest slot value...
|
// stage II: place the latest slot value...
|
||||||
function(st){
|
function(st){
|
||||||
return ((st ?? state).slots ?? {})[name]
|
return ((st ?? state).slots ?? {})[name] },
|
||||||
?? body },
|
|
||||||
{slot: name}) }) })),
|
{slot: name}) }) })),
|
||||||
|
// XXX do not like this name...
|
||||||
|
content: ['slot'],
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -56,7 +56,7 @@ test.Setups({
|
|||||||
...ins.map(function(e){
|
...ins.map(function(e){
|
||||||
return e + '<slot slot>third</slot>' }),
|
return e + '<slot slot>third</slot>' }),
|
||||||
'third' ]} },
|
'third' ]} },
|
||||||
|
// nested...
|
||||||
slot_nested: function(assert){
|
slot_nested: function(assert){
|
||||||
return {code: [
|
return {code: [
|
||||||
'<slot slot>[[ <slot slot.content/> ]]</slot>@slot(slot.content value)',
|
'<slot slot>[[ <slot slot.content/> ]]</slot>@slot(slot.content value)',
|
||||||
@ -65,8 +65,7 @@ test.Setups({
|
|||||||
return {code: [
|
return {code: [
|
||||||
'<slot slot>[[ <slot slot.content/> ]]</slot>@slot(slot value)',
|
'<slot slot>[[ <slot slot.content/> ]]</slot>@slot(slot value)',
|
||||||
'value' ]} },
|
'value' ]} },
|
||||||
|
// nested-self...
|
||||||
// recursion...
|
|
||||||
slot_nested_nested: function(assert){
|
slot_nested_nested: function(assert){
|
||||||
return {code: [
|
return {code: [
|
||||||
'<slot slot>[[ <slot slot value/> ]]</slot>',
|
'<slot slot>[[ <slot slot value/> ]]</slot>',
|
||||||
@ -76,6 +75,32 @@ test.Setups({
|
|||||||
return {code: [
|
return {code: [
|
||||||
'<slot slot>[[ <slot slot/> ]]</slot>',
|
'<slot slot>[[ <slot slot/> ]]</slot>',
|
||||||
'[[ ]]' ]} },
|
'[[ ]]' ]} },
|
||||||
|
// slot content...
|
||||||
|
slot_content: function(assert){
|
||||||
|
return {code: [
|
||||||
|
'<slot slot>[[ <content/> ]]</slot>',
|
||||||
|
'[[ ]]' ]} },
|
||||||
|
slot_content_multi: function(assert){
|
||||||
|
return {code: [
|
||||||
|
'<slot slot "moo"/><slot slot>[[ <content/> <content/> <content/> ]]</slot>',
|
||||||
|
'[[ moo moo moo ]]' ]} },
|
||||||
|
slot_content_filled: function(assert){
|
||||||
|
var ins = this.slot_content(assert).code.slice(0, -1)
|
||||||
|
return {code: [
|
||||||
|
...ins.map(function(e){
|
||||||
|
return '<slot slot "content"/>' + e }),
|
||||||
|
'[[ content ]]' ]} },
|
||||||
|
slot_content_content_filled: function(assert){
|
||||||
|
var ins = this.slot_content_filled(assert).code
|
||||||
|
var res = ins.pop()
|
||||||
|
return {code: [
|
||||||
|
...ins.map(function(e){
|
||||||
|
return e +'<slot slot>(( <content/> ))</slot>' }),
|
||||||
|
'(( '+ res +' ))' ]} },
|
||||||
|
slot_content_nested: function(assert){
|
||||||
|
return {code: [
|
||||||
|
'<slot slot>moo<slot slot>[[ <content/> ]]</slot></slot>',
|
||||||
|
'[[ moo ]]' ]} },
|
||||||
|
|
||||||
/* XXX SHOWN_HIDDEN
|
/* XXX SHOWN_HIDDEN
|
||||||
// XXX these need to be revised...
|
// XXX these need to be revised...
|
||||||
@ -125,6 +150,24 @@ test.Modifiers({
|
|||||||
string: 'string',
|
string: 'string',
|
||||||
}
|
}
|
||||||
return state },
|
return state },
|
||||||
|
slot: function(assert, state){
|
||||||
|
state.code = [
|
||||||
|
...state.code
|
||||||
|
.slice(0, -1)
|
||||||
|
.map(function(e){
|
||||||
|
return `[[ <slot parent>${e}</slot> ]]` }),
|
||||||
|
`[[ ${state.code.at(-1)} ]]`,
|
||||||
|
]
|
||||||
|
return state },
|
||||||
|
slot_expand: function(assert, state){
|
||||||
|
state.code = [
|
||||||
|
...state.code
|
||||||
|
.slice(0, -1)
|
||||||
|
.map(function(e){
|
||||||
|
return `[[ <slot parent/> ]]<slot parent>${e}</slot>` }),
|
||||||
|
`[[ ${state.code.at(-1)} ]]`,
|
||||||
|
]
|
||||||
|
return state },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user