@embedpdf/plugin-search 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e="START_SEARCH_SESSION",s="STOP_SEARCH_SESSION",a="SET_SEARCH_FLAGS",i="SET_SHOW_ALL_RESULTS",r="START_SEARCH",h="SET_SEARCH_RESULTS",l="SET_ACTIVE_RESULT_INDEX";function n(t){return{type:a,payload:t}}function o(t){return{type:i,payload:t}}function c(t,e,s){return{type:h,payload:{results:t,total:e,activeResultIndex:s}}}const u=class extends t.BasePlugin{constructor(e,s,a){super(e,s),this.searchStop$=t.createBehaviorEmitter(),this.searchStart$=t.createBehaviorEmitter(),this.searchResult$=t.createBehaviorEmitter(),this.searchActiveResultChange$=t.createBehaviorEmitter(),this.searchResultState$=t.createBehaviorEmitter(),this.searchState$=t.createBehaviorEmitter(),this.engine=a,this.loader=this.registry.getPlugin("loader").provides(),this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this)),this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this))}handleDocumentLoaded(t){this.currentDocument=t,this.state.active&&this.startSearchSession()}handleLoaderEvent(t){("error"===t.type||"start"===t.type&&this.currentDocument)&&(this.state.active&&this.stopSearchSession(),this.currentDocument=void 0)}async initialize(t){this.dispatch(n(t.flags||[])),this.dispatch(o(void 0===t.showAllResults||t.showAllResults))}onStoreUpdated(t,e){this.searchResultState$.emit({results:e.results,activeResultIndex:e.activeResultIndex,showAllResults:e.showAllResults,active:e.active}),this.searchState$.emit(e)}buildCapability(){return{startSearch:this.startSearchSession.bind(this),stopSearch:this.stopSearchSession.bind(this),searchAllPages:this.searchAllPages.bind(this),nextResult:this.nextResult.bind(this),previousResult:this.previousResult.bind(this),goToResult:this.goToResult.bind(this),setShowAllResults:t=>this.dispatch(o(t)),getShowAllResults:()=>this.state.showAllResults,onSearchResult:this.searchResult$.on,onSearchStart:this.searchStart$.on,onSearchStop:this.searchStop$.on,onActiveResultChange:this.searchActiveResultChange$.on,onSearchResultStateChange:this.searchResultState$.on,onStateChange:this.searchState$.on,getFlags:()=>this.state.flags,setFlags:t=>this.setFlags(t),getState:()=>this.state}}setFlags(t){this.dispatch(n(t)),this.state.active&&this.searchAllPages(this.state.query,!0)}notifySearchStart(){this.searchStart$.emit()}notifySearchStop(){this.searchStop$.emit()}notifyActiveResultChange(t){this.searchActiveResultChange$.emit(t)}startSearchSession(){this.currentDocument&&(this.dispatch({type:e}),this.notifySearchStart())}stopSearchSession(){this.currentDocument&&this.getState().active&&(this.dispatch({type:s}),this.notifySearchStop())}async searchAllPages(t,e=!1){const s=t.trim();return this.state.query!==s||e?(this.dispatch({type:r,payload:s}),s&&this.currentDocument?(this.state.active||this.startSearchSession(),new Promise((t=>{this.engine.searchAllPages(this.currentDocument,s,this.state.flags).wait((e=>{const s=e.total>0?0:-1;this.dispatch(c(e.results,e.total,s)),this.searchResult$.emit(e),e.total>0&&this.notifyActiveResultChange(0),t(e)}),(e=>{console.error("Error during search:",e),this.dispatch(c([],0,-1)),t({results:[],total:0})}))}))):(this.dispatch(c([],0,-1)),{results:[],total:0})):{results:this.state.results,total:this.state.total}}nextResult(){if(0===this.state.results.length)return-1;const t=this.state.activeResultIndex>=this.state.results.length-1?0:this.state.activeResultIndex+1;return this.goToResult(t)}previousResult(){if(0===this.state.results.length)return-1;const t=this.state.activeResultIndex<=0?this.state.results.length-1:this.state.activeResultIndex-1;return this.goToResult(t)}goToResult(t){return 0===this.state.results.length||t<0||t>=this.state.results.length?-1:(this.dispatch(function(t){return{type:l,payload:t}}(t)),this.notifyActiveResultChange(t),t)}async destroy(){this.state.active&&this.currentDocument&&this.stopSearchSession(),this.searchResult$.clear(),this.searchStart$.clear(),this.searchStop$.clear(),this.searchActiveResultChange$.clear(),this.searchResultState$.clear(),this.searchState$.clear()}};u.id="search";let S=u;const d="search",p={id:d,name:"Search Plugin",version:"1.0.0",provides:["search"],requires:["loader"],optional:[],defaultConfig:{enabled:!0,flags:[]}},R={flags:[],results:[],total:0,activeResultIndex:-1,showAllResults:!0,query:"",loading:!1,active:!1},g={manifest:p,create:(t,e)=>new S(d,t,e),reducer:(t=R,n)=>{switch(n.type){case e:return{...t,active:!0};case s:return{...t,results:[],total:0,activeResultIndex:-1,query:"",loading:!1,active:!1};case a:return{...t,flags:n.payload};case i:return{...t,showAllResults:n.payload};case r:return{...t,loading:!0,query:n.payload};case h:return{...t,results:n.payload.results,total:n.payload.total,activeResultIndex:n.payload.activeResultIndex,loading:!1};case l:return{...t,activeResultIndex:n.payload};default:return t}},initialState:R};exports.SEARCH_PLUGIN_ID=d,exports.SearchPlugin=S,exports.SearchPluginPackage=g,exports.initialState=R,exports.manifest=p;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e=require("@embedpdf/models"),s="START_SEARCH_SESSION",a="STOP_SEARCH_SESSION",i="SET_SEARCH_FLAGS",r="SET_SHOW_ALL_RESULTS",h="START_SEARCH",l="SET_SEARCH_RESULTS",n="APPEND_SEARCH_RESULTS",c="SET_ACTIVE_RESULT_INDEX";function o(t){return{type:i,payload:t}}function u(t){return{type:r,payload:t}}function d(t,e,s){return{type:l,payload:{results:t,total:e,activeResultIndex:s}}}function S(t){return{type:c,payload:t}}const p=class extends t.BasePlugin{constructor(e,s,a){super(e,s),this.searchStop$=t.createBehaviorEmitter(),this.searchStart$=t.createBehaviorEmitter(),this.searchResult$=t.createBehaviorEmitter(),this.searchActiveResultChange$=t.createBehaviorEmitter(),this.searchResultState$=t.createBehaviorEmitter(),this.searchState$=t.createBehaviorEmitter(),this.engine=a,this.loader=this.registry.getPlugin("loader").provides(),this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this)),this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this))}handleDocumentLoaded(t){this.currentDocument=t,this.state.active&&this.startSearchSession()}handleLoaderEvent(t){("error"===t.type||"start"===t.type&&this.currentDocument)&&(this.state.active&&this.stopSearchSession(),this.currentDocument=void 0)}async initialize(t){this.dispatch(o(t.flags||[])),this.dispatch(u(void 0===t.showAllResults||t.showAllResults))}onStoreUpdated(t,e){this.searchResultState$.emit({results:e.results,activeResultIndex:e.activeResultIndex,showAllResults:e.showAllResults,active:e.active}),this.searchState$.emit(e)}buildCapability(){return{startSearch:this.startSearchSession.bind(this),stopSearch:this.stopSearchSession.bind(this),searchAllPages:this.searchAllPages.bind(this),nextResult:this.nextResult.bind(this),previousResult:this.previousResult.bind(this),goToResult:this.goToResult.bind(this),setShowAllResults:t=>this.dispatch(u(t)),getShowAllResults:()=>this.state.showAllResults,onSearchResult:this.searchResult$.on,onSearchStart:this.searchStart$.on,onSearchStop:this.searchStop$.on,onActiveResultChange:this.searchActiveResultChange$.on,onSearchResultStateChange:this.searchResultState$.on,onStateChange:this.searchState$.on,getFlags:()=>this.state.flags,setFlags:t=>this.setFlags(t),getState:()=>this.state}}setFlags(t){this.dispatch(o(t)),this.state.active&&this.searchAllPages(this.state.query,!0)}notifySearchStart(){this.searchStart$.emit()}notifySearchStop(){this.searchStop$.emit()}notifyActiveResultChange(t){this.searchActiveResultChange$.emit(t)}startSearchSession(){this.currentDocument&&(this.dispatch({type:s}),this.notifySearchStart())}stopSearchSession(){var t,e;if(this.currentDocument&&this.state.active){try{null==(e=null==(t=this.currentTask)?void 0:t.abort)||e.call(t,{type:"abort",code:"cancelled",message:"search stopped"})}catch{}this.currentTask=void 0,this.dispatch({type:a}),this.notifySearchStop()}}searchAllPages(t,s=!1){var a,i;const r=t.trim();if(this.state.query===r&&!s)return e.PdfTaskHelper.resolve({results:this.state.results,total:this.state.total});if(this.currentTask){try{null==(i=(a=this.currentTask).abort)||i.call(a,{type:"abort",code:"superseded",message:"new search"})}catch{}this.currentTask=void 0}if(this.dispatch({type:h,payload:r}),!r||!this.currentDocument)return this.dispatch(d([],0,-1)),e.PdfTaskHelper.resolve({results:[],total:0});this.state.active||this.startSearchSession();const l=this.currentTask=this.engine.searchAllPages(this.currentDocument,r,this.state.flags);return l.onProgress((t=>{var e,s;(null==(e=null==t?void 0:t.results)?void 0:e.length)&&(this.dispatch((s=t.results,{type:n,payload:{results:s}})),-1===this.state.activeResultIndex&&(this.dispatch(S(0)),this.notifyActiveResultChange(0)))})),l.wait((t=>{this.currentTask=void 0;const e=t.total>0?0:-1;this.dispatch(d(t.results,t.total,e)),this.searchResult$.emit(t),t.total>0&&this.notifyActiveResultChange(0)}),(t=>{this.currentTask=void 0,console.error("Error during search:",t),this.dispatch(d([],0,-1))})),l}nextResult(){if(0===this.state.results.length)return-1;const t=this.state.activeResultIndex>=this.state.results.length-1?0:this.state.activeResultIndex+1;return this.goToResult(t)}previousResult(){if(0===this.state.results.length)return-1;const t=this.state.activeResultIndex<=0?this.state.results.length-1:this.state.activeResultIndex-1;return this.goToResult(t)}goToResult(t){return 0===this.state.results.length||t<0||t>=this.state.results.length?-1:(this.dispatch(S(t)),this.notifyActiveResultChange(t),t)}async destroy(){this.state.active&&this.currentDocument&&this.stopSearchSession(),this.searchResult$.clear(),this.searchStart$.clear(),this.searchStop$.clear(),this.searchActiveResultChange$.clear(),this.searchResultState$.clear(),this.searchState$.clear()}};p.id="search";let R=p;const v="search",g={id:v,name:"Search Plugin",version:"1.0.0",provides:["search"],requires:["loader"],optional:[],defaultConfig:{enabled:!0,flags:[]}},y={flags:[],results:[],total:0,activeResultIndex:-1,showAllResults:!0,query:"",loading:!1,active:!1},A={manifest:g,create:(t,e)=>new R(v,t,e),reducer:(t=y,e)=>{switch(e.type){case s:return{...t,active:!0};case a:return{...t,results:[],total:0,activeResultIndex:-1,query:"",loading:!1,active:!1};case i:return{...t,flags:e.payload};case r:return{...t,showAllResults:e.payload};case h:return{...t,loading:!0,query:e.payload,results:[],total:0,activeResultIndex:-1};case n:{const s=[...t.results,...e.payload.results],a=-1===t.activeResultIndex&&s.length>0?0:t.activeResultIndex;return{...t,results:s,total:s.length,activeResultIndex:a,loading:!0}}case l:return{...t,results:e.payload.results,total:e.payload.total,activeResultIndex:e.payload.activeResultIndex,loading:!1};case c:return{...t,activeResultIndex:e.payload};default:return t}},initialState:y};exports.SEARCH_PLUGIN_ID=v,exports.SearchPlugin=R,exports.SearchPluginPackage=A,exports.initialState=y,exports.manifest=g;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/actions.ts","../src/lib/search-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { MatchFlag, SearchResult } from '@embedpdf/models';\n\n// Action Types\nexport const START_SEARCH_SESSION = 'START_SEARCH_SESSION';\nexport const STOP_SEARCH_SESSION = 'STOP_SEARCH_SESSION';\nexport const SET_SEARCH_FLAGS = 'SET_SEARCH_FLAGS';\nexport const SET_SHOW_ALL_RESULTS = 'SET_SHOW_ALL_RESULTS';\nexport const START_SEARCH = 'START_SEARCH';\nexport const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS';\nexport const SET_ACTIVE_RESULT_INDEX = 'SET_ACTIVE_RESULT_INDEX';\n\n// Action Interfaces\nexport interface StartSearchSessionAction extends Action {\n type: typeof START_SEARCH_SESSION;\n}\n\nexport interface StopSearchSessionAction extends Action {\n type: typeof STOP_SEARCH_SESSION;\n}\n\nexport interface SetSearchFlagsAction extends Action {\n type: typeof SET_SEARCH_FLAGS;\n payload: MatchFlag[];\n}\n\nexport interface SetShowAllResultsAction extends Action {\n type: typeof SET_SHOW_ALL_RESULTS;\n payload: boolean;\n}\n\nexport interface StartSearchAction extends Action {\n type: typeof START_SEARCH;\n payload: string;\n}\n\nexport interface SetSearchResultsAction extends Action {\n type: typeof SET_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n total: number;\n activeResultIndex: number;\n };\n}\n\nexport interface SetActiveResultIndexAction extends Action {\n type: typeof SET_ACTIVE_RESULT_INDEX;\n payload: number;\n}\n\n// Union Type for All Actions\nexport type SearchAction =\n | StartSearchSessionAction\n | StopSearchSessionAction\n | SetSearchFlagsAction\n | SetShowAllResultsAction\n | StartSearchAction\n | SetSearchResultsAction\n | SetActiveResultIndexAction;\n\n// Action Creators\nexport function startSearchSession(): StartSearchSessionAction {\n return { type: START_SEARCH_SESSION };\n}\n\nexport function stopSearchSession(): StopSearchSessionAction {\n return { type: STOP_SEARCH_SESSION };\n}\n\nexport function setSearchFlags(flags: MatchFlag[]): SetSearchFlagsAction {\n return { type: SET_SEARCH_FLAGS, payload: flags };\n}\n\nexport function setShowAllResults(showAll: boolean): SetShowAllResultsAction {\n return { type: SET_SHOW_ALL_RESULTS, payload: showAll };\n}\n\nexport function startSearch(query: string): StartSearchAction {\n return { type: START_SEARCH, payload: query };\n}\n\nexport function setSearchResults(\n results: SearchResult[],\n total: number,\n activeResultIndex: number,\n): SetSearchResultsAction {\n return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };\n}\n\nexport function setActiveResultIndex(index: number): SetActiveResultIndexAction {\n return { type: SET_ACTIVE_RESULT_INDEX, payload: index };\n}\n","import { BasePlugin, createBehaviorEmitter, PluginRegistry } from '@embedpdf/core';\nimport {\n MatchFlag,\n PdfDocumentObject,\n SearchAllPagesResult,\n TaskError,\n PdfEngine,\n} from '@embedpdf/models';\nimport { SearchPluginConfig, SearchCapability, SearchState, SearchResultState } from './types';\nimport { LoaderCapability, LoaderEvent, LoaderPlugin } from '@embedpdf/plugin-loader';\nimport {\n startSearchSession,\n stopSearchSession,\n setSearchFlags,\n setShowAllResults,\n startSearch,\n setSearchResults,\n setActiveResultIndex,\n SearchAction,\n} from './actions';\n\nexport class SearchPlugin extends BasePlugin<\n SearchPluginConfig,\n SearchCapability,\n SearchState,\n SearchAction\n> {\n static readonly id = 'search' as const;\n private loader: LoaderCapability;\n private currentDocument?: PdfDocumentObject;\n private engine: PdfEngine;\n\n private readonly searchStop$ = createBehaviorEmitter();\n private readonly searchStart$ = createBehaviorEmitter();\n private readonly searchResult$ = createBehaviorEmitter<SearchAllPagesResult>();\n private readonly searchActiveResultChange$ = createBehaviorEmitter<number>();\n private readonly searchResultState$ = createBehaviorEmitter<SearchResultState>();\n private readonly searchState$ = createBehaviorEmitter<SearchState>();\n\n constructor(id: string, registry: PluginRegistry, engine: PdfEngine) {\n super(id, registry);\n this.engine = engine;\n this.loader = this.registry.getPlugin<LoaderPlugin>('loader')!.provides();\n\n this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this));\n this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this));\n }\n\n private handleDocumentLoaded(doc: PdfDocumentObject): void {\n this.currentDocument = doc;\n if (this.state.active) {\n this.startSearchSession();\n }\n }\n\n private handleLoaderEvent(event: LoaderEvent): void {\n if (event.type === 'error' || (event.type === 'start' && this.currentDocument)) {\n if (this.state.active) {\n this.stopSearchSession();\n }\n this.currentDocument = undefined;\n }\n }\n\n async initialize(config: SearchPluginConfig): Promise<void> {\n this.dispatch(setSearchFlags(config.flags || []));\n this.dispatch(\n setShowAllResults(config.showAllResults !== undefined ? config.showAllResults : true),\n );\n }\n\n override onStoreUpdated(_prevState: SearchState, newState: SearchState): void {\n this.searchResultState$.emit({\n results: newState.results,\n activeResultIndex: newState.activeResultIndex,\n showAllResults: newState.showAllResults,\n active: newState.active,\n });\n this.searchState$.emit(newState);\n }\n\n protected buildCapability(): SearchCapability {\n return {\n startSearch: this.startSearchSession.bind(this),\n stopSearch: this.stopSearchSession.bind(this),\n searchAllPages: this.searchAllPages.bind(this),\n nextResult: this.nextResult.bind(this),\n previousResult: this.previousResult.bind(this),\n goToResult: this.goToResult.bind(this),\n setShowAllResults: (showAll) => this.dispatch(setShowAllResults(showAll)),\n getShowAllResults: () => this.state.showAllResults,\n onSearchResult: this.searchResult$.on,\n onSearchStart: this.searchStart$.on,\n onSearchStop: this.searchStop$.on,\n onActiveResultChange: this.searchActiveResultChange$.on,\n onSearchResultStateChange: this.searchResultState$.on,\n onStateChange: this.searchState$.on,\n getFlags: () => this.state.flags,\n setFlags: (flags) => this.setFlags(flags),\n getState: () => this.state,\n };\n }\n\n private setFlags(flags: MatchFlag[]): void {\n this.dispatch(setSearchFlags(flags));\n if (this.state.active) {\n this.searchAllPages(this.state.query, true);\n }\n }\n\n private notifySearchStart(): void {\n this.searchStart$.emit();\n }\n\n private notifySearchStop(): void {\n this.searchStop$.emit();\n }\n\n private notifyActiveResultChange(index: number): void {\n this.searchActiveResultChange$.emit(index);\n }\n\n private startSearchSession(): void {\n if (!this.currentDocument) {\n return;\n }\n this.dispatch(startSearchSession());\n this.notifySearchStart();\n }\n\n private stopSearchSession(): void {\n if (!this.currentDocument || !this.getState().active) {\n return;\n }\n this.dispatch(stopSearchSession());\n this.notifySearchStop();\n }\n\n private async searchAllPages(\n keyword: string,\n force: boolean = false,\n ): Promise<SearchAllPagesResult> {\n const trimmedKeyword = keyword.trim();\n\n if (this.state.query === trimmedKeyword && !force) {\n return { results: this.state.results, total: this.state.total };\n }\n\n this.dispatch(startSearch(trimmedKeyword));\n\n if (!trimmedKeyword) {\n this.dispatch(setSearchResults([], 0, -1));\n return { results: [], total: 0 };\n }\n if (!this.currentDocument) {\n this.dispatch(setSearchResults([], 0, -1));\n return { results: [], total: 0 };\n }\n\n if (!this.state.active) {\n this.startSearchSession();\n }\n\n return new Promise<SearchAllPagesResult>((resolve) => {\n this.engine.searchAllPages(this.currentDocument!, trimmedKeyword, this.state.flags).wait(\n (results) => {\n const activeResultIndex = results.total > 0 ? 0 : -1;\n this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));\n this.searchResult$.emit(results);\n if (results.total > 0) {\n this.notifyActiveResultChange(0);\n }\n resolve(results);\n },\n (error: TaskError<any>) => {\n console.error('Error during search:', error);\n this.dispatch(setSearchResults([], 0, -1));\n resolve({ results: [], total: 0 });\n },\n );\n });\n }\n\n private nextResult(): number {\n if (this.state.results.length === 0) {\n return -1;\n }\n const nextIndex =\n this.state.activeResultIndex >= this.state.results.length - 1\n ? 0\n : this.state.activeResultIndex + 1;\n return this.goToResult(nextIndex);\n }\n\n private previousResult(): number {\n if (this.state.results.length === 0) {\n return -1;\n }\n const prevIndex =\n this.state.activeResultIndex <= 0\n ? this.state.results.length - 1\n : this.state.activeResultIndex - 1;\n return this.goToResult(prevIndex);\n }\n\n private goToResult(index: number): number {\n if (this.state.results.length === 0 || index < 0 || index >= this.state.results.length) {\n return -1;\n }\n this.dispatch(setActiveResultIndex(index));\n this.notifyActiveResultChange(index);\n return index;\n }\n\n async destroy(): Promise<void> {\n if (this.state.active && this.currentDocument) {\n this.stopSearchSession();\n }\n this.searchResult$.clear();\n this.searchStart$.clear();\n this.searchStop$.clear();\n this.searchActiveResultChange$.clear();\n this.searchResultState$.clear();\n this.searchState$.clear();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { SearchPluginConfig } from './types';\n\nexport const SEARCH_PLUGIN_ID = 'search';\n\nexport const manifest: PluginManifest<SearchPluginConfig> = {\n id: SEARCH_PLUGIN_ID,\n name: 'Search Plugin',\n version: '1.0.0',\n provides: ['search'],\n requires: ['loader'],\n optional: [],\n defaultConfig: {\n enabled: true,\n flags: [],\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport { SearchState } from './types';\nimport {\n START_SEARCH_SESSION,\n STOP_SEARCH_SESSION,\n SET_SEARCH_FLAGS,\n SET_SHOW_ALL_RESULTS,\n START_SEARCH,\n SET_SEARCH_RESULTS,\n SET_ACTIVE_RESULT_INDEX,\n SearchAction,\n} from './actions';\n\nexport const initialState: SearchState = {\n flags: [],\n results: [],\n total: 0,\n activeResultIndex: -1,\n showAllResults: true,\n query: '',\n loading: false,\n active: false,\n};\n\nexport const searchReducer: Reducer<SearchState, SearchAction> = (state = initialState, action) => {\n switch (action.type) {\n case START_SEARCH_SESSION:\n return { ...state, active: true };\n\n case STOP_SEARCH_SESSION:\n return {\n ...state,\n results: [],\n total: 0,\n activeResultIndex: -1,\n query: '',\n loading: false,\n active: false,\n };\n\n case SET_SEARCH_FLAGS:\n return { ...state, flags: action.payload };\n\n case SET_SHOW_ALL_RESULTS:\n return { ...state, showAllResults: action.payload };\n\n case START_SEARCH:\n return { ...state, loading: true, query: action.payload };\n\n case SET_SEARCH_RESULTS:\n return {\n ...state,\n results: action.payload.results,\n total: action.payload.total,\n activeResultIndex: action.payload.activeResultIndex,\n loading: false,\n };\n\n case SET_ACTIVE_RESULT_INDEX:\n return { ...state, activeResultIndex: action.payload };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { SearchPlugin } from './search-plugin';\nimport { manifest, SEARCH_PLUGIN_ID } from './manifest';\nimport { SearchPluginConfig, SearchState } from './types';\nimport { searchReducer, initialState } from './reducer';\nimport { SearchAction } from './actions';\n\nexport const SearchPluginPackage: PluginPackage<\n SearchPlugin,\n SearchPluginConfig,\n SearchState,\n SearchAction\n> = {\n manifest,\n create: (registry, engine) => new SearchPlugin(SEARCH_PLUGIN_ID, registry, engine),\n reducer: searchReducer,\n initialState,\n};\n\nexport * from './search-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState };\n"],"names":["START_SEARCH_SESSION","STOP_SEARCH_SESSION","SET_SEARCH_FLAGS","SET_SHOW_ALL_RESULTS","START_SEARCH","SET_SEARCH_RESULTS","SET_ACTIVE_RESULT_INDEX","setSearchFlags","flags","type","payload","setShowAllResults","showAll","setSearchResults","results","total","activeResultIndex","_SearchPlugin","BasePlugin","constructor","id","registry","engine","super","this","searchStop$","createBehaviorEmitter","searchStart$","searchResult$","searchActiveResultChange$","searchResultState$","searchState$","loader","getPlugin","provides","onDocumentLoaded","handleDocumentLoaded","bind","onLoaderEvent","handleLoaderEvent","doc","currentDocument","state","active","startSearchSession","event","stopSearchSession","initialize","config","dispatch","showAllResults","onStoreUpdated","_prevState","newState","emit","buildCapability","startSearch","stopSearch","searchAllPages","nextResult","previousResult","goToResult","getShowAllResults","onSearchResult","on","onSearchStart","onSearchStop","onActiveResultChange","onSearchResultStateChange","onStateChange","getFlags","setFlags","getState","query","notifySearchStart","notifySearchStop","notifyActiveResultChange","index","keyword","force","trimmedKeyword","trim","Promise","resolve","wait","error","console","length","nextIndex","prevIndex","setActiveResultIndex","destroy","clear","SearchPlugin","SEARCH_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","initialState","loading","SearchPluginPackage","create","reducer","action"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/actions.ts","../src/lib/search-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { MatchFlag, SearchResult } from '@embedpdf/models';\n\n// Action Types\nexport const START_SEARCH_SESSION = 'START_SEARCH_SESSION';\nexport const STOP_SEARCH_SESSION = 'STOP_SEARCH_SESSION';\nexport const SET_SEARCH_FLAGS = 'SET_SEARCH_FLAGS';\nexport const SET_SHOW_ALL_RESULTS = 'SET_SHOW_ALL_RESULTS';\nexport const START_SEARCH = 'START_SEARCH';\nexport const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS';\nexport const APPEND_SEARCH_RESULTS = 'APPEND_SEARCH_RESULTS';\nexport const SET_ACTIVE_RESULT_INDEX = 'SET_ACTIVE_RESULT_INDEX';\n\n// Action Interfaces\nexport interface StartSearchSessionAction extends Action {\n type: typeof START_SEARCH_SESSION;\n}\n\nexport interface StopSearchSessionAction extends Action {\n type: typeof STOP_SEARCH_SESSION;\n}\n\nexport interface SetSearchFlagsAction extends Action {\n type: typeof SET_SEARCH_FLAGS;\n payload: MatchFlag[];\n}\n\nexport interface SetShowAllResultsAction extends Action {\n type: typeof SET_SHOW_ALL_RESULTS;\n payload: boolean;\n}\n\nexport interface StartSearchAction extends Action {\n type: typeof START_SEARCH;\n payload: string;\n}\n\nexport interface SetSearchResultsAction extends Action {\n type: typeof SET_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n total: number;\n activeResultIndex: number;\n };\n}\n\nexport interface AppendSearchResultsAction extends Action {\n type: typeof APPEND_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n };\n}\n\nexport interface SetActiveResultIndexAction extends Action {\n type: typeof SET_ACTIVE_RESULT_INDEX;\n payload: number;\n}\n\n// Union Type for All Actions\nexport type SearchAction =\n | StartSearchSessionAction\n | StopSearchSessionAction\n | SetSearchFlagsAction\n | SetShowAllResultsAction\n | StartSearchAction\n | SetSearchResultsAction\n | AppendSearchResultsAction\n | SetActiveResultIndexAction;\n\n// Action Creators\nexport function startSearchSession(): StartSearchSessionAction {\n return { type: START_SEARCH_SESSION };\n}\n\nexport function stopSearchSession(): StopSearchSessionAction {\n return { type: STOP_SEARCH_SESSION };\n}\n\nexport function setSearchFlags(flags: MatchFlag[]): SetSearchFlagsAction {\n return { type: SET_SEARCH_FLAGS, payload: flags };\n}\n\nexport function setShowAllResults(showAll: boolean): SetShowAllResultsAction {\n return { type: SET_SHOW_ALL_RESULTS, payload: showAll };\n}\n\nexport function startSearch(query: string): StartSearchAction {\n return { type: START_SEARCH, payload: query };\n}\n\nexport function setSearchResults(\n results: SearchResult[],\n total: number,\n activeResultIndex: number,\n): SetSearchResultsAction {\n return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };\n}\n\nexport function appendSearchResults(results: SearchResult[]): AppendSearchResultsAction {\n return { type: APPEND_SEARCH_RESULTS, payload: { results } };\n}\n\nexport function setActiveResultIndex(index: number): SetActiveResultIndexAction {\n return { type: SET_ACTIVE_RESULT_INDEX, payload: index };\n}\n","import { BasePlugin, createBehaviorEmitter, PluginRegistry } from '@embedpdf/core';\nimport {\n MatchFlag,\n PdfDocumentObject,\n SearchAllPagesResult,\n TaskError,\n PdfEngine,\n PdfTask,\n PdfPageSearchProgress,\n PdfTaskHelper,\n} from '@embedpdf/models';\nimport { SearchPluginConfig, SearchCapability, SearchState, SearchResultState } from './types';\nimport { LoaderCapability, LoaderEvent, LoaderPlugin } from '@embedpdf/plugin-loader';\nimport {\n startSearchSession,\n stopSearchSession,\n setSearchFlags,\n setShowAllResults,\n startSearch,\n setSearchResults,\n setActiveResultIndex,\n appendSearchResults,\n SearchAction,\n} from './actions';\n\nexport class SearchPlugin extends BasePlugin<\n SearchPluginConfig,\n SearchCapability,\n SearchState,\n SearchAction\n> {\n static readonly id = 'search' as const;\n private loader: LoaderCapability;\n private currentDocument?: PdfDocumentObject;\n private engine: PdfEngine;\n\n private readonly searchStop$ = createBehaviorEmitter();\n private readonly searchStart$ = createBehaviorEmitter();\n private readonly searchResult$ = createBehaviorEmitter<SearchAllPagesResult>();\n private readonly searchActiveResultChange$ = createBehaviorEmitter<number>();\n private readonly searchResultState$ = createBehaviorEmitter<SearchResultState>();\n private readonly searchState$ = createBehaviorEmitter<SearchState>();\n\n // keep reference to current running task (optional abort handling if your PdfTask supports it)\n private currentTask?: ReturnType<PdfEngine['searchAllPages']>;\n\n constructor(id: string, registry: PluginRegistry, engine: PdfEngine) {\n super(id, registry);\n this.engine = engine;\n this.loader = this.registry.getPlugin<LoaderPlugin>('loader')!.provides();\n\n this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this));\n this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this));\n }\n\n private handleDocumentLoaded(doc: PdfDocumentObject): void {\n this.currentDocument = doc;\n if (this.state.active) {\n this.startSearchSession();\n }\n }\n\n private handleLoaderEvent(event: LoaderEvent): void {\n if (event.type === 'error' || (event.type === 'start' && this.currentDocument)) {\n if (this.state.active) {\n this.stopSearchSession();\n }\n this.currentDocument = undefined;\n }\n }\n\n async initialize(config: SearchPluginConfig): Promise<void> {\n this.dispatch(setSearchFlags(config.flags || []));\n this.dispatch(\n setShowAllResults(config.showAllResults !== undefined ? config.showAllResults : true),\n );\n }\n\n override onStoreUpdated(_prevState: SearchState, newState: SearchState): void {\n this.searchResultState$.emit({\n results: newState.results,\n activeResultIndex: newState.activeResultIndex,\n showAllResults: newState.showAllResults,\n active: newState.active,\n });\n this.searchState$.emit(newState);\n }\n\n protected buildCapability(): SearchCapability {\n return {\n startSearch: this.startSearchSession.bind(this),\n stopSearch: this.stopSearchSession.bind(this),\n searchAllPages: this.searchAllPages.bind(this),\n nextResult: this.nextResult.bind(this),\n previousResult: this.previousResult.bind(this),\n goToResult: this.goToResult.bind(this),\n setShowAllResults: (showAll) => this.dispatch(setShowAllResults(showAll)),\n getShowAllResults: () => this.state.showAllResults,\n onSearchResult: this.searchResult$.on,\n onSearchStart: this.searchStart$.on,\n onSearchStop: this.searchStop$.on,\n onActiveResultChange: this.searchActiveResultChange$.on,\n onSearchResultStateChange: this.searchResultState$.on,\n onStateChange: this.searchState$.on,\n getFlags: () => this.state.flags,\n setFlags: (flags) => this.setFlags(flags),\n getState: () => this.state,\n };\n }\n\n private setFlags(flags: MatchFlag[]): void {\n this.dispatch(setSearchFlags(flags));\n if (this.state.active) {\n this.searchAllPages(this.state.query, true);\n }\n }\n\n private notifySearchStart(): void {\n this.searchStart$.emit();\n }\n\n private notifySearchStop(): void {\n this.searchStop$.emit();\n }\n\n private notifyActiveResultChange(index: number): void {\n this.searchActiveResultChange$.emit(index);\n }\n\n private startSearchSession(): void {\n if (!this.currentDocument) return;\n this.dispatch(startSearchSession());\n this.notifySearchStart();\n }\n\n private stopSearchSession(): void {\n if (!this.currentDocument || !this.state.active) return;\n // optional: abort current task if PdfTask supports it\n try {\n // @ts-expect-error: optional abort if available\n this.currentTask?.abort?.({ type: 'abort', code: 'cancelled', message: 'search stopped' });\n } catch {}\n this.currentTask = undefined;\n\n this.dispatch(stopSearchSession());\n this.notifySearchStop();\n }\n\n private searchAllPages(\n keyword: string,\n force: boolean = false,\n ): PdfTask<SearchAllPagesResult, PdfPageSearchProgress> {\n const trimmedKeyword = keyword.trim();\n\n if (this.state.query === trimmedKeyword && !force) {\n return PdfTaskHelper.resolve<SearchAllPagesResult, PdfPageSearchProgress>({\n results: this.state.results,\n total: this.state.total,\n });\n }\n\n // stop previous task if still running\n if (this.currentTask) {\n try {\n // @ts-expect-error: optional abort if available\n this.currentTask.abort?.({ type: 'abort', code: 'superseded', message: 'new search' });\n } catch {}\n this.currentTask = undefined;\n }\n\n this.dispatch(startSearch(trimmedKeyword));\n\n if (!trimmedKeyword || !this.currentDocument) {\n this.dispatch(setSearchResults([], 0, -1));\n return PdfTaskHelper.resolve<SearchAllPagesResult, PdfPageSearchProgress>({\n results: [],\n total: 0,\n });\n }\n\n if (!this.state.active) {\n this.startSearchSession();\n }\n\n const task = (this.currentTask = this.engine.searchAllPages(\n this.currentDocument!,\n trimmedKeyword,\n this.state.flags,\n ));\n\n task.onProgress((p) => {\n if (p?.results?.length) {\n this.dispatch(appendSearchResults(p.results));\n // set first active result as soon as we have something\n if (this.state.activeResultIndex === -1) {\n this.dispatch(setActiveResultIndex(0));\n this.notifyActiveResultChange(0);\n }\n }\n });\n\n task.wait(\n (results) => {\n this.currentTask = undefined;\n const activeResultIndex = results.total > 0 ? 0 : -1;\n this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));\n this.searchResult$.emit(results);\n if (results.total > 0) {\n this.notifyActiveResultChange(0);\n }\n },\n (error) => {\n this.currentTask = undefined;\n console.error('Error during search:', error);\n this.dispatch(setSearchResults([], 0, -1));\n },\n );\n\n return task;\n }\n\n private nextResult(): number {\n if (this.state.results.length === 0) return -1;\n const nextIndex =\n this.state.activeResultIndex >= this.state.results.length - 1\n ? 0\n : this.state.activeResultIndex + 1;\n return this.goToResult(nextIndex);\n }\n\n private previousResult(): number {\n if (this.state.results.length === 0) return -1;\n const prevIndex =\n this.state.activeResultIndex <= 0\n ? this.state.results.length - 1\n : this.state.activeResultIndex - 1;\n return this.goToResult(prevIndex);\n }\n\n private goToResult(index: number): number {\n if (this.state.results.length === 0 || index < 0 || index >= this.state.results.length) {\n return -1;\n }\n this.dispatch(setActiveResultIndex(index));\n this.notifyActiveResultChange(index);\n return index;\n }\n\n async destroy(): Promise<void> {\n if (this.state.active && this.currentDocument) {\n this.stopSearchSession();\n }\n this.searchResult$.clear();\n this.searchStart$.clear();\n this.searchStop$.clear();\n this.searchActiveResultChange$.clear();\n this.searchResultState$.clear();\n this.searchState$.clear();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { SearchPluginConfig } from './types';\n\nexport const SEARCH_PLUGIN_ID = 'search';\n\nexport const manifest: PluginManifest<SearchPluginConfig> = {\n id: SEARCH_PLUGIN_ID,\n name: 'Search Plugin',\n version: '1.0.0',\n provides: ['search'],\n requires: ['loader'],\n optional: [],\n defaultConfig: {\n enabled: true,\n flags: [],\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport { SearchState } from './types';\nimport {\n START_SEARCH_SESSION,\n STOP_SEARCH_SESSION,\n SET_SEARCH_FLAGS,\n SET_SHOW_ALL_RESULTS,\n START_SEARCH,\n SET_SEARCH_RESULTS,\n APPEND_SEARCH_RESULTS,\n SET_ACTIVE_RESULT_INDEX,\n SearchAction,\n} from './actions';\n\nexport const initialState: SearchState = {\n flags: [],\n results: [],\n total: 0,\n activeResultIndex: -1,\n showAllResults: true,\n query: '',\n loading: false,\n active: false,\n};\n\nexport const searchReducer: Reducer<SearchState, SearchAction> = (state = initialState, action) => {\n switch (action.type) {\n case START_SEARCH_SESSION:\n return { ...state, active: true };\n\n case STOP_SEARCH_SESSION:\n return {\n ...state,\n results: [],\n total: 0,\n activeResultIndex: -1,\n query: '',\n loading: false,\n active: false,\n };\n\n case SET_SEARCH_FLAGS:\n return { ...state, flags: action.payload };\n\n case SET_SHOW_ALL_RESULTS:\n return { ...state, showAllResults: action.payload };\n\n case START_SEARCH:\n return {\n ...state,\n loading: true,\n query: action.payload,\n // clear old results on new search start\n results: [],\n total: 0,\n activeResultIndex: -1,\n };\n\n case APPEND_SEARCH_RESULTS: {\n const newResults = [...state.results, ...action.payload.results];\n const firstHitIndex =\n state.activeResultIndex === -1 && newResults.length > 0 ? 0 : state.activeResultIndex;\n return {\n ...state,\n results: newResults,\n total: newResults.length, // total-so-far\n activeResultIndex: firstHitIndex,\n // keep loading true until final SET_SEARCH_RESULTS\n loading: true,\n };\n }\n\n case SET_SEARCH_RESULTS:\n return {\n ...state,\n results: action.payload.results,\n total: action.payload.total,\n activeResultIndex: action.payload.activeResultIndex,\n loading: false,\n };\n\n case SET_ACTIVE_RESULT_INDEX:\n return { ...state, activeResultIndex: action.payload };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { SearchPlugin } from './search-plugin';\nimport { manifest, SEARCH_PLUGIN_ID } from './manifest';\nimport { SearchPluginConfig, SearchState } from './types';\nimport { searchReducer, initialState } from './reducer';\nimport { SearchAction } from './actions';\n\nexport const SearchPluginPackage: PluginPackage<\n SearchPlugin,\n SearchPluginConfig,\n SearchState,\n SearchAction\n> = {\n manifest,\n create: (registry, engine) => new SearchPlugin(SEARCH_PLUGIN_ID, registry, engine),\n reducer: searchReducer,\n initialState,\n};\n\nexport * from './search-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState };\n"],"names":["START_SEARCH_SESSION","STOP_SEARCH_SESSION","SET_SEARCH_FLAGS","SET_SHOW_ALL_RESULTS","START_SEARCH","SET_SEARCH_RESULTS","APPEND_SEARCH_RESULTS","SET_ACTIVE_RESULT_INDEX","setSearchFlags","flags","type","payload","setShowAllResults","showAll","setSearchResults","results","total","activeResultIndex","setActiveResultIndex","index","_SearchPlugin","BasePlugin","constructor","id","registry","engine","super","this","searchStop$","createBehaviorEmitter","searchStart$","searchResult$","searchActiveResultChange$","searchResultState$","searchState$","loader","getPlugin","provides","onDocumentLoaded","handleDocumentLoaded","bind","onLoaderEvent","handleLoaderEvent","doc","currentDocument","state","active","startSearchSession","event","stopSearchSession","initialize","config","dispatch","showAllResults","onStoreUpdated","_prevState","newState","emit","buildCapability","startSearch","stopSearch","searchAllPages","nextResult","previousResult","goToResult","getShowAllResults","onSearchResult","on","onSearchStart","onSearchStop","onActiveResultChange","onSearchResultStateChange","onStateChange","getFlags","setFlags","getState","query","notifySearchStart","notifySearchStop","notifyActiveResultChange","_b","_a","currentTask","abort","call","code","message","keyword","force","trimmedKeyword","trim","PdfTaskHelper","resolve","task","onProgress","p","length","wait","error","console","nextIndex","prevIndex","destroy","clear","SearchPlugin","SEARCH_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","initialState","loading","SearchPluginPackage","create","reducer","action","newResults","firstHitIndex"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import { BasePlugin, createBehaviorEmitter } from "@embedpdf/core";
2
+ import { PdfTaskHelper } from "@embedpdf/models";
2
3
  const START_SEARCH_SESSION = "START_SEARCH_SESSION";
3
4
  const STOP_SEARCH_SESSION = "STOP_SEARCH_SESSION";
4
5
  const SET_SEARCH_FLAGS = "SET_SEARCH_FLAGS";
5
6
  const SET_SHOW_ALL_RESULTS = "SET_SHOW_ALL_RESULTS";
6
7
  const START_SEARCH = "START_SEARCH";
7
8
  const SET_SEARCH_RESULTS = "SET_SEARCH_RESULTS";
9
+ const APPEND_SEARCH_RESULTS = "APPEND_SEARCH_RESULTS";
8
10
  const SET_ACTIVE_RESULT_INDEX = "SET_ACTIVE_RESULT_INDEX";
9
11
  function startSearchSession() {
10
12
  return { type: START_SEARCH_SESSION };
@@ -24,6 +26,9 @@ function startSearch(query) {
24
26
  function setSearchResults(results, total, activeResultIndex) {
25
27
  return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };
26
28
  }
29
+ function appendSearchResults(results) {
30
+ return { type: APPEND_SEARCH_RESULTS, payload: { results } };
31
+ }
27
32
  function setActiveResultIndex(index) {
28
33
  return { type: SET_ACTIVE_RESULT_INDEX, payload: index };
29
34
  }
@@ -107,66 +112,88 @@ const _SearchPlugin = class _SearchPlugin extends BasePlugin {
107
112
  this.searchActiveResultChange$.emit(index);
108
113
  }
109
114
  startSearchSession() {
110
- if (!this.currentDocument) {
111
- return;
112
- }
115
+ if (!this.currentDocument) return;
113
116
  this.dispatch(startSearchSession());
114
117
  this.notifySearchStart();
115
118
  }
116
119
  stopSearchSession() {
117
- if (!this.currentDocument || !this.getState().active) {
118
- return;
120
+ var _a, _b;
121
+ if (!this.currentDocument || !this.state.active) return;
122
+ try {
123
+ (_b = (_a = this.currentTask) == null ? void 0 : _a.abort) == null ? void 0 : _b.call(_a, { type: "abort", code: "cancelled", message: "search stopped" });
124
+ } catch {
119
125
  }
126
+ this.currentTask = void 0;
120
127
  this.dispatch(stopSearchSession());
121
128
  this.notifySearchStop();
122
129
  }
123
- async searchAllPages(keyword, force = false) {
130
+ searchAllPages(keyword, force = false) {
131
+ var _a, _b;
124
132
  const trimmedKeyword = keyword.trim();
125
133
  if (this.state.query === trimmedKeyword && !force) {
126
- return { results: this.state.results, total: this.state.total };
134
+ return PdfTaskHelper.resolve({
135
+ results: this.state.results,
136
+ total: this.state.total
137
+ });
127
138
  }
128
- this.dispatch(startSearch(trimmedKeyword));
129
- if (!trimmedKeyword) {
130
- this.dispatch(setSearchResults([], 0, -1));
131
- return { results: [], total: 0 };
139
+ if (this.currentTask) {
140
+ try {
141
+ (_b = (_a = this.currentTask).abort) == null ? void 0 : _b.call(_a, { type: "abort", code: "superseded", message: "new search" });
142
+ } catch {
143
+ }
144
+ this.currentTask = void 0;
132
145
  }
133
- if (!this.currentDocument) {
146
+ this.dispatch(startSearch(trimmedKeyword));
147
+ if (!trimmedKeyword || !this.currentDocument) {
134
148
  this.dispatch(setSearchResults([], 0, -1));
135
- return { results: [], total: 0 };
149
+ return PdfTaskHelper.resolve({
150
+ results: [],
151
+ total: 0
152
+ });
136
153
  }
137
154
  if (!this.state.active) {
138
155
  this.startSearchSession();
139
156
  }
140
- return new Promise((resolve) => {
141
- this.engine.searchAllPages(this.currentDocument, trimmedKeyword, this.state.flags).wait(
142
- (results) => {
143
- const activeResultIndex = results.total > 0 ? 0 : -1;
144
- this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));
145
- this.searchResult$.emit(results);
146
- if (results.total > 0) {
147
- this.notifyActiveResultChange(0);
148
- }
149
- resolve(results);
150
- },
151
- (error) => {
152
- console.error("Error during search:", error);
153
- this.dispatch(setSearchResults([], 0, -1));
154
- resolve({ results: [], total: 0 });
157
+ const task = this.currentTask = this.engine.searchAllPages(
158
+ this.currentDocument,
159
+ trimmedKeyword,
160
+ this.state.flags
161
+ );
162
+ task.onProgress((p) => {
163
+ var _a2;
164
+ if ((_a2 = p == null ? void 0 : p.results) == null ? void 0 : _a2.length) {
165
+ this.dispatch(appendSearchResults(p.results));
166
+ if (this.state.activeResultIndex === -1) {
167
+ this.dispatch(setActiveResultIndex(0));
168
+ this.notifyActiveResultChange(0);
155
169
  }
156
- );
170
+ }
157
171
  });
172
+ task.wait(
173
+ (results) => {
174
+ this.currentTask = void 0;
175
+ const activeResultIndex = results.total > 0 ? 0 : -1;
176
+ this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));
177
+ this.searchResult$.emit(results);
178
+ if (results.total > 0) {
179
+ this.notifyActiveResultChange(0);
180
+ }
181
+ },
182
+ (error) => {
183
+ this.currentTask = void 0;
184
+ console.error("Error during search:", error);
185
+ this.dispatch(setSearchResults([], 0, -1));
186
+ }
187
+ );
188
+ return task;
158
189
  }
159
190
  nextResult() {
160
- if (this.state.results.length === 0) {
161
- return -1;
162
- }
191
+ if (this.state.results.length === 0) return -1;
163
192
  const nextIndex = this.state.activeResultIndex >= this.state.results.length - 1 ? 0 : this.state.activeResultIndex + 1;
164
193
  return this.goToResult(nextIndex);
165
194
  }
166
195
  previousResult() {
167
- if (this.state.results.length === 0) {
168
- return -1;
169
- }
196
+ if (this.state.results.length === 0) return -1;
170
197
  const prevIndex = this.state.activeResultIndex <= 0 ? this.state.results.length - 1 : this.state.activeResultIndex - 1;
171
198
  return this.goToResult(prevIndex);
172
199
  }
@@ -234,7 +261,28 @@ const searchReducer = (state = initialState, action) => {
234
261
  case SET_SHOW_ALL_RESULTS:
235
262
  return { ...state, showAllResults: action.payload };
236
263
  case START_SEARCH:
237
- return { ...state, loading: true, query: action.payload };
264
+ return {
265
+ ...state,
266
+ loading: true,
267
+ query: action.payload,
268
+ // clear old results on new search start
269
+ results: [],
270
+ total: 0,
271
+ activeResultIndex: -1
272
+ };
273
+ case APPEND_SEARCH_RESULTS: {
274
+ const newResults = [...state.results, ...action.payload.results];
275
+ const firstHitIndex = state.activeResultIndex === -1 && newResults.length > 0 ? 0 : state.activeResultIndex;
276
+ return {
277
+ ...state,
278
+ results: newResults,
279
+ total: newResults.length,
280
+ // total-so-far
281
+ activeResultIndex: firstHitIndex,
282
+ // keep loading true until final SET_SEARCH_RESULTS
283
+ loading: true
284
+ };
285
+ }
238
286
  case SET_SEARCH_RESULTS:
239
287
  return {
240
288
  ...state,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/actions.ts","../src/lib/search-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { MatchFlag, SearchResult } from '@embedpdf/models';\n\n// Action Types\nexport const START_SEARCH_SESSION = 'START_SEARCH_SESSION';\nexport const STOP_SEARCH_SESSION = 'STOP_SEARCH_SESSION';\nexport const SET_SEARCH_FLAGS = 'SET_SEARCH_FLAGS';\nexport const SET_SHOW_ALL_RESULTS = 'SET_SHOW_ALL_RESULTS';\nexport const START_SEARCH = 'START_SEARCH';\nexport const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS';\nexport const SET_ACTIVE_RESULT_INDEX = 'SET_ACTIVE_RESULT_INDEX';\n\n// Action Interfaces\nexport interface StartSearchSessionAction extends Action {\n type: typeof START_SEARCH_SESSION;\n}\n\nexport interface StopSearchSessionAction extends Action {\n type: typeof STOP_SEARCH_SESSION;\n}\n\nexport interface SetSearchFlagsAction extends Action {\n type: typeof SET_SEARCH_FLAGS;\n payload: MatchFlag[];\n}\n\nexport interface SetShowAllResultsAction extends Action {\n type: typeof SET_SHOW_ALL_RESULTS;\n payload: boolean;\n}\n\nexport interface StartSearchAction extends Action {\n type: typeof START_SEARCH;\n payload: string;\n}\n\nexport interface SetSearchResultsAction extends Action {\n type: typeof SET_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n total: number;\n activeResultIndex: number;\n };\n}\n\nexport interface SetActiveResultIndexAction extends Action {\n type: typeof SET_ACTIVE_RESULT_INDEX;\n payload: number;\n}\n\n// Union Type for All Actions\nexport type SearchAction =\n | StartSearchSessionAction\n | StopSearchSessionAction\n | SetSearchFlagsAction\n | SetShowAllResultsAction\n | StartSearchAction\n | SetSearchResultsAction\n | SetActiveResultIndexAction;\n\n// Action Creators\nexport function startSearchSession(): StartSearchSessionAction {\n return { type: START_SEARCH_SESSION };\n}\n\nexport function stopSearchSession(): StopSearchSessionAction {\n return { type: STOP_SEARCH_SESSION };\n}\n\nexport function setSearchFlags(flags: MatchFlag[]): SetSearchFlagsAction {\n return { type: SET_SEARCH_FLAGS, payload: flags };\n}\n\nexport function setShowAllResults(showAll: boolean): SetShowAllResultsAction {\n return { type: SET_SHOW_ALL_RESULTS, payload: showAll };\n}\n\nexport function startSearch(query: string): StartSearchAction {\n return { type: START_SEARCH, payload: query };\n}\n\nexport function setSearchResults(\n results: SearchResult[],\n total: number,\n activeResultIndex: number,\n): SetSearchResultsAction {\n return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };\n}\n\nexport function setActiveResultIndex(index: number): SetActiveResultIndexAction {\n return { type: SET_ACTIVE_RESULT_INDEX, payload: index };\n}\n","import { BasePlugin, createBehaviorEmitter, PluginRegistry } from '@embedpdf/core';\nimport {\n MatchFlag,\n PdfDocumentObject,\n SearchAllPagesResult,\n TaskError,\n PdfEngine,\n} from '@embedpdf/models';\nimport { SearchPluginConfig, SearchCapability, SearchState, SearchResultState } from './types';\nimport { LoaderCapability, LoaderEvent, LoaderPlugin } from '@embedpdf/plugin-loader';\nimport {\n startSearchSession,\n stopSearchSession,\n setSearchFlags,\n setShowAllResults,\n startSearch,\n setSearchResults,\n setActiveResultIndex,\n SearchAction,\n} from './actions';\n\nexport class SearchPlugin extends BasePlugin<\n SearchPluginConfig,\n SearchCapability,\n SearchState,\n SearchAction\n> {\n static readonly id = 'search' as const;\n private loader: LoaderCapability;\n private currentDocument?: PdfDocumentObject;\n private engine: PdfEngine;\n\n private readonly searchStop$ = createBehaviorEmitter();\n private readonly searchStart$ = createBehaviorEmitter();\n private readonly searchResult$ = createBehaviorEmitter<SearchAllPagesResult>();\n private readonly searchActiveResultChange$ = createBehaviorEmitter<number>();\n private readonly searchResultState$ = createBehaviorEmitter<SearchResultState>();\n private readonly searchState$ = createBehaviorEmitter<SearchState>();\n\n constructor(id: string, registry: PluginRegistry, engine: PdfEngine) {\n super(id, registry);\n this.engine = engine;\n this.loader = this.registry.getPlugin<LoaderPlugin>('loader')!.provides();\n\n this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this));\n this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this));\n }\n\n private handleDocumentLoaded(doc: PdfDocumentObject): void {\n this.currentDocument = doc;\n if (this.state.active) {\n this.startSearchSession();\n }\n }\n\n private handleLoaderEvent(event: LoaderEvent): void {\n if (event.type === 'error' || (event.type === 'start' && this.currentDocument)) {\n if (this.state.active) {\n this.stopSearchSession();\n }\n this.currentDocument = undefined;\n }\n }\n\n async initialize(config: SearchPluginConfig): Promise<void> {\n this.dispatch(setSearchFlags(config.flags || []));\n this.dispatch(\n setShowAllResults(config.showAllResults !== undefined ? config.showAllResults : true),\n );\n }\n\n override onStoreUpdated(_prevState: SearchState, newState: SearchState): void {\n this.searchResultState$.emit({\n results: newState.results,\n activeResultIndex: newState.activeResultIndex,\n showAllResults: newState.showAllResults,\n active: newState.active,\n });\n this.searchState$.emit(newState);\n }\n\n protected buildCapability(): SearchCapability {\n return {\n startSearch: this.startSearchSession.bind(this),\n stopSearch: this.stopSearchSession.bind(this),\n searchAllPages: this.searchAllPages.bind(this),\n nextResult: this.nextResult.bind(this),\n previousResult: this.previousResult.bind(this),\n goToResult: this.goToResult.bind(this),\n setShowAllResults: (showAll) => this.dispatch(setShowAllResults(showAll)),\n getShowAllResults: () => this.state.showAllResults,\n onSearchResult: this.searchResult$.on,\n onSearchStart: this.searchStart$.on,\n onSearchStop: this.searchStop$.on,\n onActiveResultChange: this.searchActiveResultChange$.on,\n onSearchResultStateChange: this.searchResultState$.on,\n onStateChange: this.searchState$.on,\n getFlags: () => this.state.flags,\n setFlags: (flags) => this.setFlags(flags),\n getState: () => this.state,\n };\n }\n\n private setFlags(flags: MatchFlag[]): void {\n this.dispatch(setSearchFlags(flags));\n if (this.state.active) {\n this.searchAllPages(this.state.query, true);\n }\n }\n\n private notifySearchStart(): void {\n this.searchStart$.emit();\n }\n\n private notifySearchStop(): void {\n this.searchStop$.emit();\n }\n\n private notifyActiveResultChange(index: number): void {\n this.searchActiveResultChange$.emit(index);\n }\n\n private startSearchSession(): void {\n if (!this.currentDocument) {\n return;\n }\n this.dispatch(startSearchSession());\n this.notifySearchStart();\n }\n\n private stopSearchSession(): void {\n if (!this.currentDocument || !this.getState().active) {\n return;\n }\n this.dispatch(stopSearchSession());\n this.notifySearchStop();\n }\n\n private async searchAllPages(\n keyword: string,\n force: boolean = false,\n ): Promise<SearchAllPagesResult> {\n const trimmedKeyword = keyword.trim();\n\n if (this.state.query === trimmedKeyword && !force) {\n return { results: this.state.results, total: this.state.total };\n }\n\n this.dispatch(startSearch(trimmedKeyword));\n\n if (!trimmedKeyword) {\n this.dispatch(setSearchResults([], 0, -1));\n return { results: [], total: 0 };\n }\n if (!this.currentDocument) {\n this.dispatch(setSearchResults([], 0, -1));\n return { results: [], total: 0 };\n }\n\n if (!this.state.active) {\n this.startSearchSession();\n }\n\n return new Promise<SearchAllPagesResult>((resolve) => {\n this.engine.searchAllPages(this.currentDocument!, trimmedKeyword, this.state.flags).wait(\n (results) => {\n const activeResultIndex = results.total > 0 ? 0 : -1;\n this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));\n this.searchResult$.emit(results);\n if (results.total > 0) {\n this.notifyActiveResultChange(0);\n }\n resolve(results);\n },\n (error: TaskError<any>) => {\n console.error('Error during search:', error);\n this.dispatch(setSearchResults([], 0, -1));\n resolve({ results: [], total: 0 });\n },\n );\n });\n }\n\n private nextResult(): number {\n if (this.state.results.length === 0) {\n return -1;\n }\n const nextIndex =\n this.state.activeResultIndex >= this.state.results.length - 1\n ? 0\n : this.state.activeResultIndex + 1;\n return this.goToResult(nextIndex);\n }\n\n private previousResult(): number {\n if (this.state.results.length === 0) {\n return -1;\n }\n const prevIndex =\n this.state.activeResultIndex <= 0\n ? this.state.results.length - 1\n : this.state.activeResultIndex - 1;\n return this.goToResult(prevIndex);\n }\n\n private goToResult(index: number): number {\n if (this.state.results.length === 0 || index < 0 || index >= this.state.results.length) {\n return -1;\n }\n this.dispatch(setActiveResultIndex(index));\n this.notifyActiveResultChange(index);\n return index;\n }\n\n async destroy(): Promise<void> {\n if (this.state.active && this.currentDocument) {\n this.stopSearchSession();\n }\n this.searchResult$.clear();\n this.searchStart$.clear();\n this.searchStop$.clear();\n this.searchActiveResultChange$.clear();\n this.searchResultState$.clear();\n this.searchState$.clear();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { SearchPluginConfig } from './types';\n\nexport const SEARCH_PLUGIN_ID = 'search';\n\nexport const manifest: PluginManifest<SearchPluginConfig> = {\n id: SEARCH_PLUGIN_ID,\n name: 'Search Plugin',\n version: '1.0.0',\n provides: ['search'],\n requires: ['loader'],\n optional: [],\n defaultConfig: {\n enabled: true,\n flags: [],\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport { SearchState } from './types';\nimport {\n START_SEARCH_SESSION,\n STOP_SEARCH_SESSION,\n SET_SEARCH_FLAGS,\n SET_SHOW_ALL_RESULTS,\n START_SEARCH,\n SET_SEARCH_RESULTS,\n SET_ACTIVE_RESULT_INDEX,\n SearchAction,\n} from './actions';\n\nexport const initialState: SearchState = {\n flags: [],\n results: [],\n total: 0,\n activeResultIndex: -1,\n showAllResults: true,\n query: '',\n loading: false,\n active: false,\n};\n\nexport const searchReducer: Reducer<SearchState, SearchAction> = (state = initialState, action) => {\n switch (action.type) {\n case START_SEARCH_SESSION:\n return { ...state, active: true };\n\n case STOP_SEARCH_SESSION:\n return {\n ...state,\n results: [],\n total: 0,\n activeResultIndex: -1,\n query: '',\n loading: false,\n active: false,\n };\n\n case SET_SEARCH_FLAGS:\n return { ...state, flags: action.payload };\n\n case SET_SHOW_ALL_RESULTS:\n return { ...state, showAllResults: action.payload };\n\n case START_SEARCH:\n return { ...state, loading: true, query: action.payload };\n\n case SET_SEARCH_RESULTS:\n return {\n ...state,\n results: action.payload.results,\n total: action.payload.total,\n activeResultIndex: action.payload.activeResultIndex,\n loading: false,\n };\n\n case SET_ACTIVE_RESULT_INDEX:\n return { ...state, activeResultIndex: action.payload };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { SearchPlugin } from './search-plugin';\nimport { manifest, SEARCH_PLUGIN_ID } from './manifest';\nimport { SearchPluginConfig, SearchState } from './types';\nimport { searchReducer, initialState } from './reducer';\nimport { SearchAction } from './actions';\n\nexport const SearchPluginPackage: PluginPackage<\n SearchPlugin,\n SearchPluginConfig,\n SearchState,\n SearchAction\n> = {\n manifest,\n create: (registry, engine) => new SearchPlugin(SEARCH_PLUGIN_ID, registry, engine),\n reducer: searchReducer,\n initialState,\n};\n\nexport * from './search-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/actions.ts","../src/lib/search-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { MatchFlag, SearchResult } from '@embedpdf/models';\n\n// Action Types\nexport const START_SEARCH_SESSION = 'START_SEARCH_SESSION';\nexport const STOP_SEARCH_SESSION = 'STOP_SEARCH_SESSION';\nexport const SET_SEARCH_FLAGS = 'SET_SEARCH_FLAGS';\nexport const SET_SHOW_ALL_RESULTS = 'SET_SHOW_ALL_RESULTS';\nexport const START_SEARCH = 'START_SEARCH';\nexport const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS';\nexport const APPEND_SEARCH_RESULTS = 'APPEND_SEARCH_RESULTS';\nexport const SET_ACTIVE_RESULT_INDEX = 'SET_ACTIVE_RESULT_INDEX';\n\n// Action Interfaces\nexport interface StartSearchSessionAction extends Action {\n type: typeof START_SEARCH_SESSION;\n}\n\nexport interface StopSearchSessionAction extends Action {\n type: typeof STOP_SEARCH_SESSION;\n}\n\nexport interface SetSearchFlagsAction extends Action {\n type: typeof SET_SEARCH_FLAGS;\n payload: MatchFlag[];\n}\n\nexport interface SetShowAllResultsAction extends Action {\n type: typeof SET_SHOW_ALL_RESULTS;\n payload: boolean;\n}\n\nexport interface StartSearchAction extends Action {\n type: typeof START_SEARCH;\n payload: string;\n}\n\nexport interface SetSearchResultsAction extends Action {\n type: typeof SET_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n total: number;\n activeResultIndex: number;\n };\n}\n\nexport interface AppendSearchResultsAction extends Action {\n type: typeof APPEND_SEARCH_RESULTS;\n payload: {\n results: SearchResult[];\n };\n}\n\nexport interface SetActiveResultIndexAction extends Action {\n type: typeof SET_ACTIVE_RESULT_INDEX;\n payload: number;\n}\n\n// Union Type for All Actions\nexport type SearchAction =\n | StartSearchSessionAction\n | StopSearchSessionAction\n | SetSearchFlagsAction\n | SetShowAllResultsAction\n | StartSearchAction\n | SetSearchResultsAction\n | AppendSearchResultsAction\n | SetActiveResultIndexAction;\n\n// Action Creators\nexport function startSearchSession(): StartSearchSessionAction {\n return { type: START_SEARCH_SESSION };\n}\n\nexport function stopSearchSession(): StopSearchSessionAction {\n return { type: STOP_SEARCH_SESSION };\n}\n\nexport function setSearchFlags(flags: MatchFlag[]): SetSearchFlagsAction {\n return { type: SET_SEARCH_FLAGS, payload: flags };\n}\n\nexport function setShowAllResults(showAll: boolean): SetShowAllResultsAction {\n return { type: SET_SHOW_ALL_RESULTS, payload: showAll };\n}\n\nexport function startSearch(query: string): StartSearchAction {\n return { type: START_SEARCH, payload: query };\n}\n\nexport function setSearchResults(\n results: SearchResult[],\n total: number,\n activeResultIndex: number,\n): SetSearchResultsAction {\n return { type: SET_SEARCH_RESULTS, payload: { results, total, activeResultIndex } };\n}\n\nexport function appendSearchResults(results: SearchResult[]): AppendSearchResultsAction {\n return { type: APPEND_SEARCH_RESULTS, payload: { results } };\n}\n\nexport function setActiveResultIndex(index: number): SetActiveResultIndexAction {\n return { type: SET_ACTIVE_RESULT_INDEX, payload: index };\n}\n","import { BasePlugin, createBehaviorEmitter, PluginRegistry } from '@embedpdf/core';\nimport {\n MatchFlag,\n PdfDocumentObject,\n SearchAllPagesResult,\n TaskError,\n PdfEngine,\n PdfTask,\n PdfPageSearchProgress,\n PdfTaskHelper,\n} from '@embedpdf/models';\nimport { SearchPluginConfig, SearchCapability, SearchState, SearchResultState } from './types';\nimport { LoaderCapability, LoaderEvent, LoaderPlugin } from '@embedpdf/plugin-loader';\nimport {\n startSearchSession,\n stopSearchSession,\n setSearchFlags,\n setShowAllResults,\n startSearch,\n setSearchResults,\n setActiveResultIndex,\n appendSearchResults,\n SearchAction,\n} from './actions';\n\nexport class SearchPlugin extends BasePlugin<\n SearchPluginConfig,\n SearchCapability,\n SearchState,\n SearchAction\n> {\n static readonly id = 'search' as const;\n private loader: LoaderCapability;\n private currentDocument?: PdfDocumentObject;\n private engine: PdfEngine;\n\n private readonly searchStop$ = createBehaviorEmitter();\n private readonly searchStart$ = createBehaviorEmitter();\n private readonly searchResult$ = createBehaviorEmitter<SearchAllPagesResult>();\n private readonly searchActiveResultChange$ = createBehaviorEmitter<number>();\n private readonly searchResultState$ = createBehaviorEmitter<SearchResultState>();\n private readonly searchState$ = createBehaviorEmitter<SearchState>();\n\n // keep reference to current running task (optional abort handling if your PdfTask supports it)\n private currentTask?: ReturnType<PdfEngine['searchAllPages']>;\n\n constructor(id: string, registry: PluginRegistry, engine: PdfEngine) {\n super(id, registry);\n this.engine = engine;\n this.loader = this.registry.getPlugin<LoaderPlugin>('loader')!.provides();\n\n this.loader.onDocumentLoaded(this.handleDocumentLoaded.bind(this));\n this.loader.onLoaderEvent(this.handleLoaderEvent.bind(this));\n }\n\n private handleDocumentLoaded(doc: PdfDocumentObject): void {\n this.currentDocument = doc;\n if (this.state.active) {\n this.startSearchSession();\n }\n }\n\n private handleLoaderEvent(event: LoaderEvent): void {\n if (event.type === 'error' || (event.type === 'start' && this.currentDocument)) {\n if (this.state.active) {\n this.stopSearchSession();\n }\n this.currentDocument = undefined;\n }\n }\n\n async initialize(config: SearchPluginConfig): Promise<void> {\n this.dispatch(setSearchFlags(config.flags || []));\n this.dispatch(\n setShowAllResults(config.showAllResults !== undefined ? config.showAllResults : true),\n );\n }\n\n override onStoreUpdated(_prevState: SearchState, newState: SearchState): void {\n this.searchResultState$.emit({\n results: newState.results,\n activeResultIndex: newState.activeResultIndex,\n showAllResults: newState.showAllResults,\n active: newState.active,\n });\n this.searchState$.emit(newState);\n }\n\n protected buildCapability(): SearchCapability {\n return {\n startSearch: this.startSearchSession.bind(this),\n stopSearch: this.stopSearchSession.bind(this),\n searchAllPages: this.searchAllPages.bind(this),\n nextResult: this.nextResult.bind(this),\n previousResult: this.previousResult.bind(this),\n goToResult: this.goToResult.bind(this),\n setShowAllResults: (showAll) => this.dispatch(setShowAllResults(showAll)),\n getShowAllResults: () => this.state.showAllResults,\n onSearchResult: this.searchResult$.on,\n onSearchStart: this.searchStart$.on,\n onSearchStop: this.searchStop$.on,\n onActiveResultChange: this.searchActiveResultChange$.on,\n onSearchResultStateChange: this.searchResultState$.on,\n onStateChange: this.searchState$.on,\n getFlags: () => this.state.flags,\n setFlags: (flags) => this.setFlags(flags),\n getState: () => this.state,\n };\n }\n\n private setFlags(flags: MatchFlag[]): void {\n this.dispatch(setSearchFlags(flags));\n if (this.state.active) {\n this.searchAllPages(this.state.query, true);\n }\n }\n\n private notifySearchStart(): void {\n this.searchStart$.emit();\n }\n\n private notifySearchStop(): void {\n this.searchStop$.emit();\n }\n\n private notifyActiveResultChange(index: number): void {\n this.searchActiveResultChange$.emit(index);\n }\n\n private startSearchSession(): void {\n if (!this.currentDocument) return;\n this.dispatch(startSearchSession());\n this.notifySearchStart();\n }\n\n private stopSearchSession(): void {\n if (!this.currentDocument || !this.state.active) return;\n // optional: abort current task if PdfTask supports it\n try {\n // @ts-expect-error: optional abort if available\n this.currentTask?.abort?.({ type: 'abort', code: 'cancelled', message: 'search stopped' });\n } catch {}\n this.currentTask = undefined;\n\n this.dispatch(stopSearchSession());\n this.notifySearchStop();\n }\n\n private searchAllPages(\n keyword: string,\n force: boolean = false,\n ): PdfTask<SearchAllPagesResult, PdfPageSearchProgress> {\n const trimmedKeyword = keyword.trim();\n\n if (this.state.query === trimmedKeyword && !force) {\n return PdfTaskHelper.resolve<SearchAllPagesResult, PdfPageSearchProgress>({\n results: this.state.results,\n total: this.state.total,\n });\n }\n\n // stop previous task if still running\n if (this.currentTask) {\n try {\n // @ts-expect-error: optional abort if available\n this.currentTask.abort?.({ type: 'abort', code: 'superseded', message: 'new search' });\n } catch {}\n this.currentTask = undefined;\n }\n\n this.dispatch(startSearch(trimmedKeyword));\n\n if (!trimmedKeyword || !this.currentDocument) {\n this.dispatch(setSearchResults([], 0, -1));\n return PdfTaskHelper.resolve<SearchAllPagesResult, PdfPageSearchProgress>({\n results: [],\n total: 0,\n });\n }\n\n if (!this.state.active) {\n this.startSearchSession();\n }\n\n const task = (this.currentTask = this.engine.searchAllPages(\n this.currentDocument!,\n trimmedKeyword,\n this.state.flags,\n ));\n\n task.onProgress((p) => {\n if (p?.results?.length) {\n this.dispatch(appendSearchResults(p.results));\n // set first active result as soon as we have something\n if (this.state.activeResultIndex === -1) {\n this.dispatch(setActiveResultIndex(0));\n this.notifyActiveResultChange(0);\n }\n }\n });\n\n task.wait(\n (results) => {\n this.currentTask = undefined;\n const activeResultIndex = results.total > 0 ? 0 : -1;\n this.dispatch(setSearchResults(results.results, results.total, activeResultIndex));\n this.searchResult$.emit(results);\n if (results.total > 0) {\n this.notifyActiveResultChange(0);\n }\n },\n (error) => {\n this.currentTask = undefined;\n console.error('Error during search:', error);\n this.dispatch(setSearchResults([], 0, -1));\n },\n );\n\n return task;\n }\n\n private nextResult(): number {\n if (this.state.results.length === 0) return -1;\n const nextIndex =\n this.state.activeResultIndex >= this.state.results.length - 1\n ? 0\n : this.state.activeResultIndex + 1;\n return this.goToResult(nextIndex);\n }\n\n private previousResult(): number {\n if (this.state.results.length === 0) return -1;\n const prevIndex =\n this.state.activeResultIndex <= 0\n ? this.state.results.length - 1\n : this.state.activeResultIndex - 1;\n return this.goToResult(prevIndex);\n }\n\n private goToResult(index: number): number {\n if (this.state.results.length === 0 || index < 0 || index >= this.state.results.length) {\n return -1;\n }\n this.dispatch(setActiveResultIndex(index));\n this.notifyActiveResultChange(index);\n return index;\n }\n\n async destroy(): Promise<void> {\n if (this.state.active && this.currentDocument) {\n this.stopSearchSession();\n }\n this.searchResult$.clear();\n this.searchStart$.clear();\n this.searchStop$.clear();\n this.searchActiveResultChange$.clear();\n this.searchResultState$.clear();\n this.searchState$.clear();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { SearchPluginConfig } from './types';\n\nexport const SEARCH_PLUGIN_ID = 'search';\n\nexport const manifest: PluginManifest<SearchPluginConfig> = {\n id: SEARCH_PLUGIN_ID,\n name: 'Search Plugin',\n version: '1.0.0',\n provides: ['search'],\n requires: ['loader'],\n optional: [],\n defaultConfig: {\n enabled: true,\n flags: [],\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport { SearchState } from './types';\nimport {\n START_SEARCH_SESSION,\n STOP_SEARCH_SESSION,\n SET_SEARCH_FLAGS,\n SET_SHOW_ALL_RESULTS,\n START_SEARCH,\n SET_SEARCH_RESULTS,\n APPEND_SEARCH_RESULTS,\n SET_ACTIVE_RESULT_INDEX,\n SearchAction,\n} from './actions';\n\nexport const initialState: SearchState = {\n flags: [],\n results: [],\n total: 0,\n activeResultIndex: -1,\n showAllResults: true,\n query: '',\n loading: false,\n active: false,\n};\n\nexport const searchReducer: Reducer<SearchState, SearchAction> = (state = initialState, action) => {\n switch (action.type) {\n case START_SEARCH_SESSION:\n return { ...state, active: true };\n\n case STOP_SEARCH_SESSION:\n return {\n ...state,\n results: [],\n total: 0,\n activeResultIndex: -1,\n query: '',\n loading: false,\n active: false,\n };\n\n case SET_SEARCH_FLAGS:\n return { ...state, flags: action.payload };\n\n case SET_SHOW_ALL_RESULTS:\n return { ...state, showAllResults: action.payload };\n\n case START_SEARCH:\n return {\n ...state,\n loading: true,\n query: action.payload,\n // clear old results on new search start\n results: [],\n total: 0,\n activeResultIndex: -1,\n };\n\n case APPEND_SEARCH_RESULTS: {\n const newResults = [...state.results, ...action.payload.results];\n const firstHitIndex =\n state.activeResultIndex === -1 && newResults.length > 0 ? 0 : state.activeResultIndex;\n return {\n ...state,\n results: newResults,\n total: newResults.length, // total-so-far\n activeResultIndex: firstHitIndex,\n // keep loading true until final SET_SEARCH_RESULTS\n loading: true,\n };\n }\n\n case SET_SEARCH_RESULTS:\n return {\n ...state,\n results: action.payload.results,\n total: action.payload.total,\n activeResultIndex: action.payload.activeResultIndex,\n loading: false,\n };\n\n case SET_ACTIVE_RESULT_INDEX:\n return { ...state, activeResultIndex: action.payload };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { SearchPlugin } from './search-plugin';\nimport { manifest, SEARCH_PLUGIN_ID } from './manifest';\nimport { SearchPluginConfig, SearchState } from './types';\nimport { searchReducer, initialState } from './reducer';\nimport { SearchAction } from './actions';\n\nexport const SearchPluginPackage: PluginPackage<\n SearchPlugin,\n SearchPluginConfig,\n SearchState,\n SearchAction\n> = {\n manifest,\n create: (registry, engine) => new SearchPlugin(SEARCH_PLUGIN_ID, registry, engine),\n reducer: searchReducer,\n initialState,\n};\n\nexport * from './search-plugin';\nexport * from './types';\nexport * from './manifest';\nexport { initialState };\n"],"names":["_a"],"mappings":"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"}
@@ -6,6 +6,7 @@ export declare const SET_SEARCH_FLAGS = "SET_SEARCH_FLAGS";
6
6
  export declare const SET_SHOW_ALL_RESULTS = "SET_SHOW_ALL_RESULTS";
7
7
  export declare const START_SEARCH = "START_SEARCH";
8
8
  export declare const SET_SEARCH_RESULTS = "SET_SEARCH_RESULTS";
9
+ export declare const APPEND_SEARCH_RESULTS = "APPEND_SEARCH_RESULTS";
9
10
  export declare const SET_ACTIVE_RESULT_INDEX = "SET_ACTIVE_RESULT_INDEX";
10
11
  export interface StartSearchSessionAction extends Action {
11
12
  type: typeof START_SEARCH_SESSION;
@@ -33,15 +34,22 @@ export interface SetSearchResultsAction extends Action {
33
34
  activeResultIndex: number;
34
35
  };
35
36
  }
37
+ export interface AppendSearchResultsAction extends Action {
38
+ type: typeof APPEND_SEARCH_RESULTS;
39
+ payload: {
40
+ results: SearchResult[];
41
+ };
42
+ }
36
43
  export interface SetActiveResultIndexAction extends Action {
37
44
  type: typeof SET_ACTIVE_RESULT_INDEX;
38
45
  payload: number;
39
46
  }
40
- export type SearchAction = StartSearchSessionAction | StopSearchSessionAction | SetSearchFlagsAction | SetShowAllResultsAction | StartSearchAction | SetSearchResultsAction | SetActiveResultIndexAction;
47
+ export type SearchAction = StartSearchSessionAction | StopSearchSessionAction | SetSearchFlagsAction | SetShowAllResultsAction | StartSearchAction | SetSearchResultsAction | AppendSearchResultsAction | SetActiveResultIndexAction;
41
48
  export declare function startSearchSession(): StartSearchSessionAction;
42
49
  export declare function stopSearchSession(): StopSearchSessionAction;
43
50
  export declare function setSearchFlags(flags: MatchFlag[]): SetSearchFlagsAction;
44
51
  export declare function setShowAllResults(showAll: boolean): SetShowAllResultsAction;
45
52
  export declare function startSearch(query: string): StartSearchAction;
46
53
  export declare function setSearchResults(results: SearchResult[], total: number, activeResultIndex: number): SetSearchResultsAction;
54
+ export declare function appendSearchResults(results: SearchResult[]): AppendSearchResultsAction;
47
55
  export declare function setActiveResultIndex(index: number): SetActiveResultIndexAction;
@@ -13,6 +13,7 @@ export declare class SearchPlugin extends BasePlugin<SearchPluginConfig, SearchC
13
13
  private readonly searchActiveResultChange$;
14
14
  private readonly searchResultState$;
15
15
  private readonly searchState$;
16
+ private currentTask?;
16
17
  constructor(id: string, registry: PluginRegistry, engine: PdfEngine);
17
18
  private handleDocumentLoaded;
18
19
  private handleLoaderEvent;
@@ -1,5 +1,5 @@
1
1
  import { BasePluginConfig, EventHook } from '@embedpdf/core';
2
- import { MatchFlag, SearchResult, SearchAllPagesResult } from '@embedpdf/models';
2
+ import { MatchFlag, SearchResult, SearchAllPagesResult, PdfTask, PdfPageSearchProgress } from '@embedpdf/models';
3
3
  export interface SearchPluginConfig extends BasePluginConfig {
4
4
  flags?: MatchFlag[];
5
5
  /**
@@ -71,7 +71,7 @@ export interface SearchCapability {
71
71
  * @param keyword - Text to search for
72
72
  * @returns Promise that resolves to all search results or empty result if none found
73
73
  */
74
- searchAllPages: (keyword: string) => Promise<SearchAllPagesResult>;
74
+ searchAllPages: (keyword: string) => PdfTask<SearchAllPagesResult, PdfPageSearchProgress>;
75
75
  /**
76
76
  * Navigate to the next search result
77
77
  * @returns The new active result index
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-search",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -23,21 +23,21 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@embedpdf/models": "1.0.16"
26
+ "@embedpdf/models": "1.0.17"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/react": "^18.2.0",
30
30
  "typescript": "^5.0.0",
31
31
  "@embedpdf/build": "1.0.0",
32
- "@embedpdf/core": "1.0.16",
33
- "@embedpdf/plugin-loader": "1.0.16"
32
+ "@embedpdf/core": "1.0.17",
33
+ "@embedpdf/plugin-loader": "1.0.17"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=16.8.0",
37
37
  "react-dom": ">=16.8.0",
38
38
  "preact": "^10.26.4",
39
- "@embedpdf/core": "1.0.16",
40
- "@embedpdf/plugin-loader": "1.0.16"
39
+ "@embedpdf/core": "1.0.17",
40
+ "@embedpdf/plugin-loader": "1.0.17"
41
41
  },
42
42
  "files": [
43
43
  "dist",