diff --git a/pwiki/page.js b/pwiki/page.js
index 1878e23..6544a64 100755
--- a/pwiki/page.js
+++ b/pwiki/page.js
@@ -2222,6 +2222,10 @@ module.System = {
×
` },
// XXX this is really slow...
+ // XXX need to handle count/offset arguments correctly...
+ // ...for this we'll need to be able to either:
+ // - count our own pages or
+ // - keep a global count
tree: {
text: object.doc`
diff --git a/pwiki/store/base.js b/pwiki/store/base.js
index 9fee575..309c2d2 100755
--- a/pwiki/store/base.js
+++ b/pwiki/store/base.js
@@ -293,9 +293,17 @@ module.BaseStore = {
// XXX should we have separate indexes for path, text and tags or
// cram the three together?
// XXX need to store this...
+ /* XXX
+ __search_options: {
+ preset: 'match',
+ tokenize: 'full',
+ },
+ //*/
__search: index.makeIndex('search',
async function(){
- var index = new flexsearch.Index()
+ var index = new flexsearch.Index(
+ this.__search_options
+ ?? {})
var update = this.__search.options.update
for(var path of (await this.paths)){
update.call(this, index, path, await this.get(path)) }
@@ -387,6 +395,7 @@ module.BaseStore = {
: '/'+p
if(pages.has(p)){
return p+args } } },
+
//
// Resolve page for path
// .match()
@@ -407,6 +416,73 @@ module.BaseStore = {
// actual existing pages, while in non-strict mode the pattern will
// match all sub-paths.
//
+ __match_args__: {
+ //
+ // : function(value, args){
+ // // setup state if needed and pre-check...
+ // // ...
+ // return no_check_needed ?
+ // false
+ // // path predicate...
+ // : function(path){
+ // if( path_matches ){
+ // return true } } },
+ //
+ // NOTE: handlers are run in order of definition.
+ //
+ tags: async function(tags){
+ tags = typeof(tags) == 'string' ?
+ this.parseTags(tags)
+ : false
+ tags && await this.tags
+ return tags
+ && function(path){
+ // tags -> skip untagged pages...
+ var t = this.tags.paths[path]
+ if(!t){
+ return false }
+ for(var tag of tags){
+ if(!t || !t.has(tag)){
+ return false } }
+ return true } },
+ search: async function(search){
+ search = search
+ && new Set(await this.search(search))
+ return search instanceof Set
+ && function(path){
+ // nothing found or not in match list...
+ if(search.size == 0
+ || !search.has(path)){
+ return false }
+ return true } },
+ // XXX EXPERIMENTAL...
+ // XXX add page/page-size???
+ offset: function(offset){
+ offset = parseInt(offset)
+ return !!offset
+ && function(path){
+ offset--
+ return !(offset >= 0) } },
+ count: function(count){
+ count = parseInt(count)
+ return !!count
+ && function(path){
+ count--
+ return !!(count >= 0) } },
+ },
+ __match_args: async function(args){
+ var that = this
+ var predicates = []
+ for(var [key, gen] of Object.entries(this.__match_args__ ?? {})){
+ var p = await gen.call(this, args[key], args)
+ p && predicates.push(p) }
+ return predicates.length > 0 ?
+ function(path){
+ for(var p of predicates){
+ if(!p.call(that, path)){
+ return false } }
+ return true }
+ : undefined },
match: async function(path, strict=false){
var that = this
// pattern match * / **
@@ -416,11 +492,7 @@ module.BaseStore = {
var {path, args} = pwpath.splitArgs(path)
var all = args.all
- var tags = args.tags
- tags = typeof(tags) == 'string' ?
- this.parseTags(tags)
- : false
- tags && await this.tags
+ var test = await this.__match_args(args)
args = pwpath.joinArgs('', args)
// NOTE: we are matching full paths only here so leading and
@@ -444,16 +516,9 @@ module.BaseStore = {
// skip metadata paths...
if(p.includes('*')){
return res }
- // skip untagged pages...
- if(tags){
- var t = that.tags.paths[p]
- if(!t){
- return res }
- for(var tag of tags){
- if(!t || !t.has(tag)){
- return res } } }
+ // check path: stage 1
var m = [...p.matchAll(pattern)]
- m.length > 0
+ var visible = m.length > 0
&& (!all ?
// test if we need to hide things....
m.reduce(function(res, m){
@@ -462,6 +527,16 @@ module.BaseStore = {
: !/(^\.|[\\\/]\.)/.test(m[1])
}, true)
: true)
+ // args...
+ // NOTE: this needs to be between path checking
+ // stages as we need to skip paths depending
+ // on the all argument...
+ if(visible
+ && test
+ && !test(p)){
+ return res }
+ // check path: stage 2
+ visible
&& (m = m[0])
&& (!strict
|| m[0] == p)
diff --git a/pwiki2.js b/pwiki2.js
index 3ba48d6..a4d827a 100755
--- a/pwiki2.js
+++ b/pwiki2.js
@@ -12,7 +12,7 @@
* - pouchdb-couchdb sync -
* - pouchdb-pouchdb sync (p2p via webrtc) - XXX
* - tags - DONE
-* - search -
+* - search - DONE
* - images - XXX
* - GUI -
* - CLI -
@@ -74,17 +74,6 @@
* XXX generalize html/dom api...
* ...see refresh() in pwiki2.html
* XXX test pouchdb latency at scale in browser...
-* XXX BUG: for some reason deleting and refreshing takes ~2x as long as
-* refreshing...
-* to reproduce:
-* pwiki.path = '/tree' // reports about ~2sec
-* await pwiki.get('/Test/Subtree/Page2/delete').raw // refresh reports ~4sec (XXX)
-* while:
-* pwiki.path = '/tree' // reports about ~2sec
-* await pwiki.get('/Test/Subtree/Page2').delete() // fast
-* pwiki.path = '/tree' // reports about ~2sec
-* XXX test with action...
-* ...cane we make everything index-related sync?
* XXX macros: .depends: need fast path pattern matching...
* XXX macros / CACHE: convert a /path/* dependency to /path/** if a script
* is recursive...
@@ -120,23 +109,6 @@
* ...likely no...
* ...would depend on where we iterate pages and on whether
* we can/should reach that spot from within the parser...
-* XXX page access mothods (.get(..) / .__get__(..) via path + args)
-* - path -- DONE
-* - tags --
-* - search --
-* Syntax:
-* /path/to/*:tags=a,b,c:search=some text
-* +--------+ . . . . . . . . . . . . . . . . path
-* +--------+ . . . . . . . . . . . tags
-* +--------------+ . . search
-* order is not relevant here...
-* each of the methods narrows down the previous' results
-* XXX FEATURE list macro paging...
-* ...should this be macro level or handled in .each()
-* what mode?
-* - count + block-offset (preferred)
-* - count + elem-offset
-* - from + to
* XXX revise/update sort...
* XXX FEATURE images...
* XXX async/live render...
@@ -252,7 +224,6 @@
* XXX add action to reset overloaded (bootstrap/.next) pages...
* - per page
* - global
-* XXX TEST @macro(..) and @slot(..) must overload in the same way...
* XXX should render templates (_view and the like) be a special case
* or render as any other page???
* ...currently they are rendered in the context of the page and
@@ -322,8 +293,8 @@
* - get tags from page -- DONE
* - show tagged pages -- DONE
* - search
-* - paths --
-* - text --
+* - paths -- ???
+* - text -- DONE
* - markdown -- DONE
* - WikiWord -- DONE
* - dom filter mechanics -- DONE