1 Commits

Author SHA1 Message Date
anian 69fea8aa39 新增对PJAX的支持 2026-07-18 15:34:11 +08:00
5 changed files with 101 additions and 44 deletions
+9
View File
@@ -1,3 +1,12 @@
# anian-plugin-search
> 基于原作者v1.7.1代码修改
#### v1.7.1-1
1. 新增对PJAX的支持
# plugin-search-widget # plugin-search-widget
Halo 2.0 的通用搜索组件插件。 Halo 2.0 的通用搜索组件插件。
+1 -1
View File
@@ -16,7 +16,7 @@ repositories {
} }
dependencies { dependencies {
implementation platform('run.halo.tools.platform:plugin:2.17.0-SNAPSHOT') implementation platform('run.halo.tools.platform:plugin:2.20.11')
compileOnly 'run.halo.app:api' compileOnly 'run.halo.app:api'
testImplementation 'run.halo.app:api' testImplementation 'run.halo.app:api'
+1 -1
View File
@@ -1 +1 @@
version=1.0.0-SNAPSHOT version=1.7.1-1
+89 -42
View File
@@ -181,51 +181,55 @@ export class SearchForm extends LitElement {
renderListItem(hit: HaloDocument, index: number, listIcon: string) { renderListItem(hit: HaloDocument, index: number, listIcon: string) {
return html` return html`
<li <li
@click="${() => this.handleOpenLink(hit)}"
@mouseenter=${() => { @mouseenter=${() => {
this.selectedIndex = index; this.selectedIndex = index;
}} }}
class="shadow-sm flex items-center space-x-3 rounded-base cursor-pointer p-3 bg-hit [&_mark]:text-primary [&_mark]:font-semibold [&_mark]:bg-transparent ${
index === this.selectedIndex
? '!bg-primary [&_mark]:!text-white [&_mark]:underline'
: ''
}"
data-index=${index} data-index=${index}
> >
<span <a
class="flex-none shrink ${listIcon} ${ href=${hit.permalink}
this.selectedIndex === index ? 'text-white' : 'text-muted' @click="${(event: MouseEvent) => this.handleOpenLink(hit, event)}"
}" class="shadow-sm flex items-center space-x-3 rounded-base cursor-pointer p-3 bg-hit no-underline text-inherit [&_mark]:text-primary [&_mark]:font-semibold [&_mark]:bg-transparent ${
></span> index === this.selectedIndex
<div class="flex-1 space-y-1.5 min-w-0"> ? '!bg-primary [&_mark]:!text-white [&_mark]:underline'
<h2
class="text-sm font-medium ${
this.selectedIndex === index ? 'text-white' : 'text-content'
}"
>
${unsafeHTML(hit.title)}
</h2>
${
hit.description
? html`
<p
class="text-xs leading-6 ${
this.selectedIndex === index
? 'text-white/90'
: 'text-muted'
}"
>
${unsafeHTML(hit.description)}
</p>
`
: '' : ''
}
</div>
<span
class="i-lucide-corner-down-left flex-none shrink text-white invisible ${
this.selectedIndex === index ? '!visible' : ''
}" }"
></span> >
<span
class="flex-none shrink ${listIcon} ${
this.selectedIndex === index ? 'text-white' : 'text-muted'
}"
></span>
<div class="flex-1 space-y-1.5 min-w-0">
<h2
class="text-sm font-medium ${
this.selectedIndex === index ? 'text-white' : 'text-content'
}"
>
${unsafeHTML(hit.title)}
</h2>
${
hit.description
? html`
<p
class="text-xs leading-6 ${
this.selectedIndex === index
? 'text-white/90'
: 'text-muted'
}"
>
${unsafeHTML(hit.description)}
</p>
`
: ''
}
</div>
<span
class="i-lucide-corner-down-left flex-none shrink text-white invisible ${
this.selectedIndex === index ? '!visible' : ''
}"
></span>
</a>
</li> </li>
`; `;
} }
@@ -247,7 +251,7 @@ export class SearchForm extends LitElement {
this.fetchHits(value); this.fetchHits(value);
} }
handleClearHistory() { private handleClearHistory() {
localStorage.removeItem(HISTORY_KEY); localStorage.removeItem(HISTORY_KEY);
this.historyHits = []; this.historyHits = [];
} }
@@ -280,14 +284,56 @@ export class SearchForm extends LitElement {
300 300
); );
handleOpenLink(hit: HaloDocument) { handleOpenLink(hit: HaloDocument, event?: MouseEvent) {
const updatedHistory = uniqBy([hit, ...this.historyHits], 'id').slice( const updatedHistory = uniqBy([hit, ...this.historyHits], 'id').slice(
0, 0,
MAX_HISTORY_ITEMS MAX_HISTORY_ITEMS
); );
localStorage.setItem(HISTORY_KEY, JSON.stringify(updatedHistory)); localStorage.setItem(HISTORY_KEY, JSON.stringify(updatedHistory));
this.historyHits = updatedHistory; this.historyHits = updatedHistory;
window.location.href = hit.permalink;
if (event && this.shouldUseNativeNavigation(event)) {
return;
}
event?.preventDefault();
this.navigate(hit.permalink);
queueMicrotask(() => {
this.dispatchEvent(
new CustomEvent('search-widget:navigate', {
bubbles: true,
composed: true,
})
);
});
}
private shouldUseNativeNavigation(event: MouseEvent) {
return (
event.defaultPrevented ||
event.button !== 0 ||
event.metaKey ||
event.ctrlKey ||
event.shiftKey ||
event.altKey
);
}
private navigate(url: string) {
const win = window as Window & {
pjax?: {
loadUrl(url: string): void;
};
};
if (win.pjax) {
win.pjax.loadUrl(url);
return;
}
window.location.href = url;
} }
handleKeydown = (e: KeyboardEvent) => { handleKeydown = (e: KeyboardEvent) => {
@@ -315,11 +361,12 @@ export class SearchForm extends LitElement {
const hit = hits[this.selectedIndex]; const hit = hits[this.selectedIndex];
if (hit) { if (hit) {
this.handleOpenLink(hit); this.handleOpenLink(hit);
e.preventDefault();
} }
} }
}; };
handleScrollIntoSelected() { private handleScrollIntoSelected() {
const selectedElement = this.shadowRoot?.querySelector( const selectedElement = this.shadowRoot?.querySelector(
`[data-index="${this.selectedIndex}"]` `[data-index="${this.selectedIndex}"]`
); );
@@ -64,6 +64,7 @@ export class SearchModal extends LitElement {
? html`<search-form ? html`<search-form
.baseUrl=${this.baseUrl} .baseUrl=${this.baseUrl}
.options=${this.options} .options=${this.options}
@search-widget:navigate=${this.close}
></search-form>` ></search-form>`
: '' : ''
} }