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){
this.location = this.path +':'+ pwpath.obj2args(args) },
// XXX do we need this...
get resolvedPath(){
return this.match() },
// NOTE: these are mostly here as helpers to be accessed via page
// actions...
// 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???
get name(){
@ -575,6 +582,9 @@ object.Constructor('Page', BasePage, {
// setup manually.
render_root: undefined,
get renderer(){
return (this.render_root || {}).path },
//
// <filter>(<source>)
// -> <result>
@ -1135,6 +1145,29 @@ object.Constructor('Page', BasePage, {
'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...
//
// 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...
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
// no data...
// NOTE: if we hit this it means that nothing was resolved,
@ -1471,6 +1523,13 @@ object.Constructor('pWikiPageElement', Page, {
set __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
// one of:
// .location = [path, hash]
@ -1496,6 +1555,7 @@ object.Constructor('pWikiPageElement', Page, {
.set.call(this, value) },
// XXX this is not persistent, is this what we want???
// XXX should this default to .path or to .name???
get title(){
return this.dom.getAttribute('title')
|| (this.dom.querySelector('h1') || {}).innerText
@ -1670,7 +1730,7 @@ module.System = {
</else>
</macro>
</sup>
(<a href="#@source(./path)/list">@include(./*/count/!)</a>)
(<a href="#@source(./path)/list">@include(./*/length/!)</a>)
&nbsp;
<a href="#@source(./path)/delete">&times;</a>
</macro>` },
@ -1749,28 +1809,6 @@ module.System = {
// 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(){
var date = (await this.get('..').data).ctime
return date ?
@ -1790,8 +1828,6 @@ module.System = {
{energetic: true}),
// XXX EXPERIMENTAL -- page types...
type: async function(){
return await this.get('..').type },
isAction: async function(){
return await this.get('..').type == 'action' ?
'action'

View File

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