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