added direct page actions + some tweaking and fixes...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-09-02 14:58:45 +03:00
parent e6adfd5489
commit a25322c397
2 changed files with 116 additions and 59 deletions

View File

@ -151,9 +151,16 @@ object.Constructor('BasePage', {
set args(args){ set args(args){
this.location = this.path +':'+ pwpath.obj2args(args) }, this.location = this.path +':'+ pwpath.obj2args(args) },
// XXX do we need this... // NOTE: these are mostly here as helpers to be accessed via page
get resolvedPath(){ // actions...
return this.match() }, // XXX should these be here or in Page???
// XXX should this call .match(..) or .resolve(..)???
get resolved(){
return this.resolve() },
get rootpath(){
return this.root ?
this.root.path
: this.path },
// XXX should these be writable??? // XXX should these be writable???
get name(){ get name(){
@ -575,6 +582,9 @@ object.Constructor('Page', BasePage, {
// setup manually. // setup manually.
render_root: undefined, render_root: undefined,
get renderer(){
return (this.render_root || {}).path },
// //
// <filter>(<source>) // <filter>(<source>)
// -> <result> // -> <result>
@ -1135,6 +1145,29 @@ object.Constructor('Page', BasePage, {
'join': ['macro'], 'join': ['macro'],
}, },
// direct actions...
//
// These are evaluated directly without the need to go through the
// whole page acquisition process...
//
// NOTE: these can not be overloaded.
// (XXX should this be so?)
actions: new Set([
'location',
'referrer',
'path',
'name',
'dir',
'resolved',
'rootpath',
'renderer',
'length',
'type',
//'ctime',
//'mtime',
]),
// events... // events...
// //
// NOTE: textUpdate event will not get triggered if text is updated // NOTE: textUpdate event will not get triggered if text is updated
@ -1182,6 +1215,25 @@ object.Constructor('Page', BasePage, {
// //
// XXX revise how we handle .strict mode... // XXX revise how we handle .strict mode...
get raw(){ return (async function(){ get raw(){ return (async function(){
// direct actions...
if(this.actions
&& this.actions.has(this.name)){
var name = this.name
var page = this.get('..')
var res = (this.isPattern
&& !this.energetic) ?
page
.each()
.map(function(page){
var res = page[name]
return typeof(res) == 'function' ?
res.call(page)
: res })
: page[this.name]
return typeof(res) == 'function' ?
res.call(page)
: res }
var data = await this.data var data = await this.data
// no data... // no data...
// NOTE: if we hit this it means that nothing was resolved, // NOTE: if we hit this it means that nothing was resolved,
@ -1471,6 +1523,13 @@ object.Constructor('pWikiPageElement', Page, {
set __clone_proto__(value){ set __clone_proto__(value){
this.__clone_proto = value }, this.__clone_proto = value },
actions: new Set([
...CachedPage.prototype.actions,
'title',
'hash'
]),
// NOTE: setting location will reset .hash set it directly via either // NOTE: setting location will reset .hash set it directly via either
// one of: // one of:
// .location = [path, hash] // .location = [path, hash]
@ -1496,6 +1555,7 @@ object.Constructor('pWikiPageElement', Page, {
.set.call(this, value) }, .set.call(this, value) },
// XXX this is not persistent, is this what we want??? // XXX this is not persistent, is this what we want???
// XXX should this default to .path or to .name???
get title(){ get title(){
return this.dom.getAttribute('title') return this.dom.getAttribute('title')
|| (this.dom.querySelector('h1') || {}).innerText || (this.dom.querySelector('h1') || {}).innerText
@ -1670,7 +1730,7 @@ module.System = {
</else> </else>
</macro> </macro>
</sup> </sup>
(<a href="#@source(./path)/list">@include(./*/count/!)</a>) (<a href="#@source(./path)/list">@include(./*/length/!)</a>)
&nbsp; &nbsp;
<a href="#@source(./path)/delete">&times;</a> <a href="#@source(./path)/delete">&times;</a>
</macro>` }, </macro>` },
@ -1749,28 +1809,6 @@ module.System = {
// metadata... // metadata...
// //
renderer: function(){
return (this.render_root || {}).path },
referrer: function(){
return this.referrer || this.path },
location: function(){
return this.get('..').location },
path: function(){
return this.get('..').path },
rootpath: function(){
return this.root.path },
resolved: async function(){
return this.get('..').resolve() },
dir: function(){
return this.get('..').dir },
name: function(){
return this.get('..').name },
title: function(){
var p = this.get('..')
return p.title
?? p.name },
count: async function(){
return this.get('..').length },
ctime: async function(){ ctime: async function(){
var date = (await this.get('..').data).ctime var date = (await this.get('..').data).ctime
return date ? return date ?
@ -1790,8 +1828,6 @@ module.System = {
{energetic: true}), {energetic: true}),
// XXX EXPERIMENTAL -- page types... // XXX EXPERIMENTAL -- page types...
type: async function(){
return await this.get('..').type },
isAction: async function(){ isAction: async function(){
return await this.get('..').type == 'action' ? return await this.get('..').type == 'action' ?
'action' 'action'

View File

@ -368,13 +368,16 @@ module.BaseStore = {
if(path.includes('*') if(path.includes('*')
|| path.includes('**')){ || path.includes('**')){
path = pwpath.split(path) path = pwpath.split(path)
// normalize trailing '/'...
path.at(-1) == ''
&& path.pop()
// match basedir and addon basename to the result... // match basedir and addon basename to the result...
var name = path[path.length-1] var name = path.at(-1)
if(name if(name
&& name != '' && name != ''
&& !name.includes('*')){ && !name.includes('*')){
path.pop() path.pop()
path.push('') //path.push('')
return (await this.match(path.join('/'), strict)) return (await this.match(path.join('/'), strict))
.map(function(p){ .map(function(p){
return pwpath.join(p, name) }) } } return pwpath.join(p, name) }) } }
@ -751,6 +754,16 @@ module.MetaStore = {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX not used...
var cacheProxy = function(name){
var func = function(path, ...args){
var cache = (this.root ?? this).cache
return cache[path]
?? (cache[path] =
object.parentCall(CachedStore[name], this, ...arguments)) }
Object.defineProperty(func, 'name', {value: name})
return func }
// XXX should this be a level-1 or level-2??? // XXX should this be a level-1 or level-2???
// XXX might be a fun idea to actually use this as a backend for BaseStore... // XXX might be a fun idea to actually use this as a backend for BaseStore...
// XXX make this a mixin... // XXX make this a mixin...
@ -758,38 +771,45 @@ module.MetaStore = {
// - timeout // - timeout
// - count // - count
// XXX TEST... // XXX TEST...
var CachedStoreMixin = var CachedStore =
module.CachedStoreMixin = { module.CachedStore = {
//__proto__: MetaStore, __proto__: MetaStore,
// format: __cache: undefined,
// { get cache(){
// <path>: <value>, return (this.__cache = this.__cache ?? {}) },
// } set cache(value){
__cache_data: undefined,
get __cache(){
return (this.__cache_data = this.__cache_data ?? {}) },
set __cache(value){
this.__cache_data = value }, this.__cache_data = value },
resetCache: function(){ clearCache: function(){
delete this.__cache_data this.cache = {}
return this }, return this },
__exists__: async function(path){ exists: async function(path){
return path in this.__cache return path in this.cache
|| object.parentCall(CachedStoreMixin.__exists__, this, ...arguments) }, || object.parentCall(CachedStore.exists, this, ...arguments) },
__get__: async function(path){ // XXX this sometimes caches promises...
return this.__cache[path] get: async function(path){
?? (this.__cache[path] = return this.cache[path]
await object.parentCall(CachedStoreMixin.__get__, this, ...arguments)) }, ?? (this.cache[path] =
__update__: async function(path, data){ await object.parentCall(CachedStore.get, this, ...arguments)) },
// XXX this is wrong??? update: async function(path, data){
this.__cache[path] = data this.cache[path] = data
return object.parentCall(CachedStoreMixin.__update__, this, ...arguments) }, return object.parentCall(CachedStore.update, this, ...arguments) },
__delete__: async function(path){ /* XXX
delete this.__cache[path] metadata: async function(path, data){
return object.parentCall(CachedStoreMixin.__delete__, this, ...arguments) }, if(data){
// XXX this is wrong -- get merged data...
this.cache[path] = data
return object.parentCall(CachedStore.metadata, this, ...arguments)
} else {
return this.cache[path]
?? (this.cache[path] =
await object.parentCall(CachedStore.metadata, this, ...arguments)) } },
//*/
delete: async function(path){
delete this.cache[path]
return object.parentCall(CachedStore.delete, this, ...arguments) },
} }
@ -798,7 +818,8 @@ module.CachedStoreMixin = {
var Store = var Store =
module.Store = module.Store =
MetaStore //MetaStore
CachedStore