generated at
icon-suggestion
UserScript

アイコンを高速に挿入できる UserScript です。



基本的な使い方
Ctrl+L で icon-suggestion を起動します
ポップアップにはページ内に埋め込まれているアイコンが表示されます
検索ボックス/ポップアップの操作方法
文字入力でアイコンを絞り込み
Tab / Shift+Tab でアイコンを選択
Enter で選択中のアイコンを挿入
ESC で icon-suggestion を終了する


導入方法
1. User Settings > User Script にチェック
2. インストールしたいプロジェクトの 自分のユーザページ に以下のブロックを貼り付ける
install.js
// ref: https://scrapbox.io/customize/icon-suggestion import { registerIconSuggestion } from '/api/code/customize/icon-suggestion/script.js'; registerIconSuggestion();


よくある質問
ページに埋め込まれていないアイコンもポップアップに表示したい
「プリセットアイコン」という機能を使うと実現できます
プリセットアイコンとは:
ページに埋め込まれていなくてもポップアップに表示される特別なアイコンのこと
registerIconSuggestion presetIcons オプションで登録できる
カスタマイズ例:
option.js
import { registerIconSuggestion, Icon, fetchMemberPageIcons, fetchRelatedPageIconsByHashTag, } from '/api/code/customize/icon-suggestion/script.js'; registerIconSuggestion({ presetIcons: [ // `new Icon(projectName, pageTitle)` でアイコンを登録 new Icon('icons', 'done'), // [/icons/done.icon] new Icon('icons', 'check'), // [/icons/check.icon] // `fetchMemberPageIcons(projectName)` を使うと、 // プロジェクトに所属するメンバーのアイコン全てを一括で登録できます。 // 注意: そのプロジェクトにアクセスする権限を持っていないとエラーになります fetchMemberPageIcons('customize'), // customize プロジェクトのメンバーのアイコンを一括で登録 // `fetchRelatedPageIconsByHashTag(projectName, hashTag)` を使うと、 // 指定したプロジェクトのハッシュタグにリンクされている、全てのページのアイコンを一括で登録できます。 // 注意: そのプロジェクトにアクセスする権限を持っていないとエラーになります fetchRelatedPageIconsByHashTag('customize', 'member'), ], });
これで以下のようにページに埋め込まれていないアイコンを表示できます
カスタマイズ例にもある通り、以下のユーティリティが組み込みで提供されています
new Icon(projectName: string, pageTitle: string)
fetchMemberPageIcons(projectName: string)
fetchRelatedPageIconsByHashTag(projectName: string, hashTag: string)

fetchMemberPageIcons ではノイズが多すぎるので、もっとノイズの少ないメンバーのアイコンのリストアップ方法がほしい
参加するユーザが定期的に入れ替わるようなプロジェクトでは、 fetchMemberPageIcons ではノイズが多すぎるかもしれません
古いユーザのアイコンを挿入する機会は殆どないのに、提案一覧に出てきてしまう
解決策として、アクティブなメンバーのページへリンクしたページを作り、そのページから辿れるユーザのみをプリセットアイコンとして登録する、という方法があります
1. /mizdra/active-member のようなページを作る
2. fetchRelatedPageIconsByHashTag('mizdra', 'active-member') でプリセットアイコンを登録する

プリセットアイコンを非表示にし、ページに埋め込まれているアイコンだけポップアップに表示したい
ポップアップの表示中に Ctrl+L を押下すると、ページに埋め込まれているアイコンだけを表示できます
続けてもう一度 Ctrl+L を押下すると、プリセットアイコンとページに埋め込まれているアイコンの両方が表示されるモードに戻ります

最初からページに埋め込まれているアイコンだけ表示した状態で icon-suggestion を起動したい
defaultIsShownPresetIcons オプションを false に設定すると、最初からページに埋め込まれているアイコンだけ表示した状態で起動できます
option.js
import { registerIconSuggestion, Icon } from '/api/code/customize/icon-suggestion/script.js'; registerIconSuggestion({ presetIcons: [ new Icon('icons', 'done'), new Icon('icons', 'check'), ], defaultIsShownPresetIcons: false, });

検索ボックスに入力中の文字列をアイコンとして挿入したい
Alt+Enter もしくは Meta+Enter の押下で入力中の文字列をアイコンとして挿入できます
補足: Meta キーについて
Windows では Windows ロゴのキー、Mac では Command キーに相当します

キーの割当をカスタマイズしたい #ショートカットキー
以下のオプションを registerIconSuggestion に渡すと、キーの割当をカスタマイズできます
isLaunchIconSuggestionKey
isExitIconSuggestionKey
isInsertQueryAsIconKey
カスタマイズ例:
option.js
import { registerIconSuggestion } from '/api/code/customize/icon-suggestion/script.js'; registerIconSuggestion({ // Ctrl+Space で icon-suggestion を起動する isLaunchIconSuggestionKey: (e) => { // 引数で KeyboardEvent を受け取ることができる // ref: https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent return e.key === ' ' && e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey; }, // Escape or Ctrl+G で icon-suggestion を終了する isExitIconSuggestionKey: (e) => { const isEscape = e.key === 'Escape' && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey; const isCtrlG = e.key === 'g' && e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey; return isEscape || isCtrlG; }, // Ctrl+Enter で入力中の文字列をアイコンとして挿入する isInsertQueryAsIconKey: (e) => { return e.key === 'Enter' && e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey; }, });

アイコンの絞り込みのアルゴリズムを変更したい
matcher オプションで変更可能です
option.js
import { registerIconSuggestion, // 曖昧一致による matcher fuzzyMatcher, // 前方一致による matcher forwardMatcher, // 部分一致による matcher partialMatcher, // 前方一致、部分一致、曖昧一致を組み合わせた matcher forwardPartialFuzzyMatcher, } from '/api/code/customize/icon-suggestion/script.js'; registerIconSuggestion({ matcher: forwardMatcher, });
カスタマイズ例にもある通り、以下のユーティリティが組み込みで提供されています
fuzzyMatcher
forwardMatcher
partialMatcher
forwardPartialFuzzyMatcher
matcher オプションのデフォルト値は forwardPartialFuzzyMatcher です

バグを見つけたので報告したい
Twitter で @mizdra にメンションするか、GitHub から Issue を作成して下さい
もちろん 修正 PR も大歓迎です

機能の追加をリクエストしたい
Twitter で @mizdra にメンションするか、GitHub から Issue を作成して下さい。検討します。
もちろん PR も大歓迎です


高度なカスタマイズ (上級者向け)
icon-suggestion では「自由を望む者には可能な限りの自由を」の精神で、icon-suggestion の挙動をプログラマブルにカスタマイズするための API を提供しています。利用には JavaScript を使ったプログラミングの知識がそれなりに要求されます。上級者向けの機能という位置づけであるため、使い方に関する質問は一切受け付けていません。また、これらの API は予告なく変更される可能性があります。

presetIcons オプションに渡すユーティリティを自作したい
PresetIconsItem 型を満たす関数を実装して下さい
組み込みのユーティリティやテストを参考にすると良いです
かなり自由度が高いですが、勿論なんでもできる訳ではありません
scrapbox は CSP で保護されているため、どこかのオリジンにあるデータを fetch してプリセットアイコンを生成...といったことはできません
ハマりがちなので注意して下さい
mizdra 面白いのできたら教えて下さい

matcher を自作したい
Matcher 型を満たす関数を実装して下さい
どう実装すれば良いかは、組み込みの matcher のソースコードなどを見て察して下さい
items 引数で渡ってきた以外のアイコンも返そうと思えば返せる
こういう matcher を書けば常に赤ちゃんをポップアップに表示できる
options.js
import { Icon, forwardPartialFuzzyMatcher, uniqueIcons, } from '/api/code/customize/icon-suggestion/script.js'; export function babyMatcher(options) { return uniqueIcons([ new Icon('mizdra', '赤ちゃん'), ...forwardPartialFuzzyMatcher(options), ]); }
uniqueIcons というユーティリティも提供されています
重複するアイコンを取り除くためにお使い下さい
mizdra 面白いのできたら教えて下さい


🐶🐱雑談コーナー🐱🐶
mizdra 何でも書いて下さい
...


更新履歴
2021/9/20: v5.0.0
オプションを rename: #91
isSuggestionOpenKeyDown isLaunchIconSuggestionKey に rename
isSuggestionCloseKeyDown isExitIconSuggestionKey に rename
isInsertQueryKeyDown isInsertQueryAsIconKey に rename
defaultSuggestPresetIcons defaultIsShownPresetIcons に rename
uniqueIcons を公開: #95
matcher からプリセットアイコンとページに埋め込まれているアイコンを区別できるように: #89
この変更に伴い matcher の型も変更されました
2021/9/19: v4.0.0
検索ボックスにフォーカスされない問題を修正: #73
デフォルトの matcher の挙動を変更: #76
matcher オプションをサポート: #80
組み込み matcher を公開: #81
検索ボックスに入力中の文字列をアイコンとして挿入する方法を変更: #83
defaultSuggestPresetIcons のデフォルト値を true に: #85
非推奨の API を廃止: #86
/mizdra から /customize に移管: #74
2021/7/9: v3.3.1
Enterprise 版で動作しない問題を修正: #70
2021/7/4: v3.3
プロジェクトのホームや、他のプロジェクトのエディタページから遷移してきた後に Ctrl+L を押すと、suggest box が開かない問題を修正: #66
Safari で IME の確定時にアイコンが挿入されてしまう問題を修正: #67
アイコンのプロジェクト名の省略条件を変更: #68
2021/6/5: v3.2
suggest されるアイコンのプロジェクト名ができるだけ省略されるように: #58
アイコンのページタイトルと画像が一致しないことがある問題を修正: #60
2021/6/3: v3.1
曖昧検索を導入しました: #55
Thanks @takker99 !
2021/5/30: v3.0
presetIcons オプションに string 型が渡せなくなりました: #42
string 型を渡している場合は警告が出るようになりました
Icon がexportされるようになりました: #43
fetchMemberPageIcons がexportされるようになりました: #44 #47
fetchRelatedPageIconsByHashTag がexportされるようになりました: #46
2021/5/29: v2.1
isSuggestionCloseKeyDown オプションを追加しました: #37
Ctrl+L でプリセットアイコンの表示・非表示が切り替えられない問題を修正しました: #36
presetIcons に渡せる要素の型 ( PresetIconsItem ) が増えました: #38
2021/5/27: v2.0
ポップアップを開く度に最新のアイコンを suggest するように
以前のバージョンでは suggest されたアイコンはキャッシュされ、Ctrl+R を押すか、リロードするまでアイコンリストが更新されませんでした
本バージョンから、ポップアップを開く度に最新のアイコンリストが表示されるようになります
isSuggestionReloadKeyDown オプションが廃止されました
アイコンリストの手動更新が不要になったため
キーワードにマッチするアイコンが無い場合に Enter を押すと、 [入力したキーワード.icon] が入力されるようになりました
presetIcons オプションでプリセットアイコンを登録できるようになりました
好きなアイコンをプリセットとして登録しておくと、suggest box表示中に Ctrl+L を押した際に suggest されます
Firefox でアイコンの挿入ができない問題を修正
2020/6: v1


リポジトリ


ソースコード
script.js
var n,u$1,i$1,t$1,o$2,r$1={},f$1=[],e$1=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i ;function c$1(n,l){for(var u in l)n[u]=l[u];return n}function s$1(n){ var l=n.parentNode;l&&l.removeChild(n)}function a$1(n,l,u){ var i,t,o,r=arguments,f={};for(o in l)"key"==o?i=l[o]:"ref"==o?t=l[o]:f[o]=l[o] ;if(arguments.length>3)for(u=[u],o=3;o<arguments.length;o++)u.push(r[o]) ;if(null!=u&&(f.children=u), "function"==typeof n&&null!=n.defaultProps)for(o in n.defaultProps)void 0===f[o]&&(f[o]=n.defaultProps[o]) ;return v$1(n,f,i,t,null)}function v$1(l,u,i,t,o){var r={type:l,props:u,key:i, ref:t,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null, constructor:void 0,__v:null==o?++n.__v:o};return null!=n.vnode&&n.vnode(r),r} function y$1(n){return n.children}function p$1(n,l){this.props=n,this.context=l} function d$1(n,l){if(null==l)return n.__?d$1(n.__,n.__.__k.indexOf(n)+1):null ;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e ;return"function"==typeof n.type?d$1(n):null}function _(n){var l,u ;if(null!=(n=n.__)&&null!=n.__c){ for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){ n.__e=n.__c.base=u.__e;break}return _(n)}}function k$1(l){ (!l.__d&&(l.__d=!0)&&u$1.push(l)&&!b$1.__r++||t$1!==n.debounceRendering)&&((t$1=n.debounceRendering)||i$1)(b$1) }function b$1(){for(var n;b$1.__r=u$1.length;)n=u$1.sort((function(n,l){ return n.__v.__b-l.__v.__b})),u$1=[],n.some((function(n){var l,u,i,t,o,r ;n.__d&&(o=(t=(l=n).__v).__e, (r=l.__P)&&(u=[],(i=c$1({},t)).__v=t.__v+1,I(r,t,i,l.__n,void 0!==r.ownerSVGElement,null!=t.__h?[o]:null,u,null==o?d$1(t):o,t.__h), T(u,t),t.__e!=o&&_(t)))}))}function m$1(n,l,u,i,t,o,e,c,s,a){ var h,p,_,k,b,m,w,A=i&&i.__k||f$1,P=A.length ;for(u.__k=[],h=0;h<l.length;h++)if(null!=(k=u.__k[h]=null==(k=l[h])||"boolean"==typeof k?null:"string"==typeof k||"number"==typeof k||"bigint"==typeof k?v$1(null,k,null,null,k):Array.isArray(k)?v$1(y$1,{ children:k},null,null,null):k.__b>0?v$1(k.type,k.props,k.key,null,k.__v):k)){ if(k.__=u, k.__b=u.__b+1,null===(_=A[h])||_&&k.key==_.key&&k.type===_.type)A[h]=void 0;else for(p=0;p<P;p++){ if((_=A[p])&&k.key==_.key&&k.type===_.type){A[p]=void 0;break}_=null} I(n,k,_=_||r$1,t,o,e,c,s,a), b=k.__e,(p=k.ref)&&_.ref!=p&&(w||(w=[]),_.ref&&w.push(_.ref,null,k), w.push(p,k.__c||b,k)), null!=b?(null==m&&(m=b),"function"==typeof k.type&&null!=k.__k&&k.__k===_.__k?k.__d=s=g$1(k,s,n):s=x$1(n,k,_,A,b,s), a||"option"!==u.type?"function"==typeof u.type&&(u.__d=s):n.value=""):s&&_.__e==s&&s.parentNode!=n&&(s=d$1(_)) } for(u.__e=m,h=P;h--;)null!=A[h]&&("function"==typeof u.type&&null!=A[h].__e&&A[h].__e==u.__d&&(u.__d=d$1(i,h+1)), L$1(A[h],A[h]));if(w)for(h=0;h<w.length;h++)z(w[h],w[++h],w[++h])} function g$1(n,l,u){var i,t ;for(i=0;i<n.__k.length;i++)(t=n.__k[i])&&(t.__=n,l="function"==typeof t.type?g$1(t,l,u):x$1(u,t,t,n.__k,t.__e,l)) ;return l}function w$2(n,l){ return l=l||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some((function(n){ w$2(n,l)})):l.push(n)),l}function x$1(n,l,u,i,t,o){var r,f,e ;if(void 0!==l.__d)r=l.__d, l.__d=void 0;else if(null==u||t!=o||null==t.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(t), r=null;else{for(f=o,e=0;(f=f.nextSibling)&&e<i.length;e+=2)if(f==t)break n ;n.insertBefore(t,o),r=o}return void 0!==r?r:t.nextSibling} function A$2(n,l,u,i,t){var o ;for(o in u)"children"===o||"key"===o||o in l||C$1(n,o,null,u[o],i) ;for(o in l)t&&"function"!=typeof l[o]||"children"===o||"key"===o||"value"===o||"checked"===o||u[o]===l[o]||C$1(n,o,l[o],u[o],i) }function P$1(n,l,u){ "-"===l[0]?n.setProperty(l,u):n[l]=null==u?"":"number"!=typeof u||e$1.test(l)?u:u+"px" }function C$1(n,l,u,i,t){var o ;n:if("style"===l)if("string"==typeof u)n.style.cssText=u;else{ if("string"==typeof i&&(n.style.cssText=i=""), i)for(l in i)u&&l in u||P$1(n.style,l,"") ;if(u)for(l in u)i&&u[l]===i[l]||P$1(n.style,l,u[l]) }else if("o"===l[0]&&"n"===l[1])o=l!==(l=l.replace(/Capture$/,"")), l=l.toLowerCase()in n?l.toLowerCase().slice(2):l.slice(2), n.l||(n.l={}),n.l[l+o]=u, u?i||n.addEventListener(l,o?H$1:$$1,o):n.removeEventListener(l,o?H$1:$$1,o);else if("dangerouslySetInnerHTML"!==l){ if(t)l=l.replace(/xlink[H:h]/,"h").replace(/sName$/,"s");else if("href"!==l&&"list"!==l&&"form"!==l&&"tabIndex"!==l&&"download"!==l&&l in n)try{ n[l]=null==u?"":u;break n}catch(n){} "function"==typeof u||(null!=u&&(!1!==u||"a"===l[0]&&"r"===l[1])?n.setAttribute(l,u):n.removeAttribute(l)) }}function $$1(l){this.l[l.type+!1](n.event?n.event(l):l)}function H$1(l){ this.l[l.type+!0](n.event?n.event(l):l)}function I(l,u,i,t,o,r,f,e,s){ var a,v,h,d,_,k,b,g,w,x,A,P=u.type;if(void 0!==u.constructor)return null ;null!=i.__h&&(s=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=n.__b)&&a(u);try{ n:if("function"==typeof P){ if(g=u.props,w=(a=P.contextType)&&t[a.__c],x=a?w?w.props.value:a.__:t, i.__c?b=(v=u.__c=i.__c).__=v.__E:("prototype"in P&&P.prototype.render?u.__c=v=new P(g,x):(u.__c=v=new p$1(g,x), v.constructor=P, v.render=M$1),w&&w.sub(v),v.props=g,v.state||(v.state={}),v.context=x, v.__n=t,h=v.__d=!0, v.__h=[]),null==v.__s&&(v.__s=v.state),null!=P.getDerivedStateFromProps&&(v.__s==v.state&&(v.__s=c$1({},v.__s)), c$1(v.__s,P.getDerivedStateFromProps(g,v.__s))), d=v.props,_=v.state,h)null==P.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componentWillMount(), null!=v.componentDidMount&&v.__h.push(v.componentDidMount);else{ if(null==P.getDerivedStateFromProps&&g!==d&&null!=v.componentWillReceiveProps&&v.componentWillReceiveProps(g,x), !v.__e&&null!=v.shouldComponentUpdate&&!1===v.shouldComponentUpdate(g,v.__s,x)||u.__v===i.__v){ v.props=g, v.state=v.__s,u.__v!==i.__v&&(v.__d=!1),v.__v=u,u.__e=i.__e,u.__k=i.__k, u.__k.forEach((function(n){n&&(n.__=u)})),v.__h.length&&f.push(v);break n} null!=v.componentWillUpdate&&v.componentWillUpdate(g,v.__s,x), null!=v.componentDidUpdate&&v.__h.push((function(){v.componentDidUpdate(d,_,k) }))} v.context=x,v.props=g,v.state=v.__s,(a=n.__r)&&a(u),v.__d=!1,v.__v=u,v.__P=l, a=v.render(v.props,v.state,v.context), v.state=v.__s,null!=v.getChildContext&&(t=c$1(c$1({},t),v.getChildContext())), h||null==v.getSnapshotBeforeUpdate||(k=v.getSnapshotBeforeUpdate(d,_)), A=null!=a&&a.type===y$1&&null==a.key?a.props.children:a, m$1(l,Array.isArray(A)?A:[A],u,i,t,o,r,f,e,s), v.base=u.__e,u.__h=null,v.__h.length&&f.push(v),b&&(v.__E=v.__=null),v.__e=!1 }else null==r&&u.__v===i.__v?(u.__k=i.__k, u.__e=i.__e):u.__e=j$1(i.__e,u,i,t,o,r,f,s);(a=n.diffed)&&a(u)}catch(l){ u.__v=null,(s||null!=r)&&(u.__e=e,u.__h=!!s,r[r.indexOf(e)]=null),n.__e(l,u,i)}} function T(l,u){n.__c&&n.__c(u,l),l.some((function(u){try{ l=u.__h,u.__h=[],l.some((function(n){n.call(u)}))}catch(l){n.__e(l,u.__v)}}))} function j$1(n,l,u,i,t,o,e,c){var a,v,h,y,p=u.props,d=l.props,_=l.type,k=0 ;if("svg"===_&&(t=!0), null!=o)for(;k<o.length;k++)if((a=o[k])&&(a===n||(_?a.localName==_:3==a.nodeType))){ n=a,o[k]=null;break}if(null==n){if(null===_)return document.createTextNode(d) ;n=t?document.createElementNS("http://www.w3.org/2000/svg",_):document.createElement(_,d.is&&d), o=null,c=!1}if(null===_)p===d||c&&n.data===d||(n.data=d);else{ if(o=o&&f$1.slice.call(n.childNodes),v=(p=u.props||r$1).dangerouslySetInnerHTML, h=d.dangerouslySetInnerHTML,!c){ if(null!=o)for(p={},y=0;y<n.attributes.length;y++)p[n.attributes[y].name]=n.attributes[y].value ;(h||v)&&(h&&(v&&h.__html==v.__html||h.__html===n.innerHTML)||(n.innerHTML=h&&h.__html||"")) } if(A$2(n,d,p,t,c),h)l.__k=[];else if(k=l.props.children,m$1(n,Array.isArray(k)?k:[k],l,u,i,t&&"foreignObject"!==_,o,e,n.firstChild,c), null!=o)for(k=o.length;k--;)null!=o[k]&&s$1(o[k]) ;c||("value"in d&&void 0!==(k=d.value)&&(k!==n.value||"progress"===_&&!k)&&C$1(n,"value",k,p.value,!1), "checked"in d&&void 0!==(k=d.checked)&&k!==n.checked&&C$1(n,"checked",k,p.checked,!1)) }return n}function z(l,u,i){try{"function"==typeof l?l(u):l.current=u}catch(l){ n.__e(l,i)}}function L$1(l,u,i){var t,o,r ;if(n.unmount&&n.unmount(l),(t=l.ref)&&(t.current&&t.current!==l.__e||z(t,null,u)), i||"function"==typeof l.type||(i=null!=(o=l.__e)), l.__e=l.__d=void 0,null!=(t=l.__c)){if(t.componentWillUnmount)try{ t.componentWillUnmount()}catch(l){n.__e(l,u)}t.base=t.__P=null} if(t=l.__k)for(r=0;r<t.length;r++)t[r]&&L$1(t[r],u,i);null!=o&&s$1(o)} function M$1(n,l,u){return this.constructor(n,u)}function N(l,u,i){var t,o,e ;n.__&&n.__(l,u), o=(t="function"==typeof i)?null:i&&i.__k||u.__k,e=[],I(u,l=(!t&&i||u).__k=a$1(y$1,null,[l]),o||r$1,r$1,void 0!==u.ownerSVGElement,!t&&i?[i]:o?null:u.firstChild?f$1.slice.call(u.childNodes):null,e,!t&&i?i:o?o.__e:u.firstChild,t), T(e,l)}function q(n,l){var u={__c:l="__cC"+o$2++,__:n,Consumer:function(n,l){ return n.children(l)},Provider:function(n){var u,i ;return this.getChildContext||(u=[], (i={})[l]=this,this.getChildContext=function(){return i },this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(k$1) },this.sub=function(n){u.push(n);var l=n.componentWillUnmount ;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)} }),n.children}};return u.Provider.__=u.Consumer.contextType=u}n={ __e:function(n,l){for(var u,i,t;l=l.__;)if((u=l.__c)&&!u.__)try{ if((i=u.constructor)&&null!=i.getDerivedStateFromError&&(u.setState(i.getDerivedStateFromError(n)), t=u.__d), null!=u.componentDidCatch&&(u.componentDidCatch(n),t=u.__d),t)return u.__E=u }catch(l){n=l}throw n},__v:0},p$1.prototype.setState=function(n,l){var u ;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=c$1({},this.state), "function"==typeof n&&(n=n(c$1({},u),this.props)), n&&c$1(u,n),null!=n&&this.__v&&(l&&this.__h.push(l),k$1(this)) },p$1.prototype.forceUpdate=function(n){ this.__v&&(this.__e=!0,n&&this.__h.push(n),k$1(this))},p$1.prototype.render=y$1, u$1=[], i$1="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout, b$1.__r=0,o$2=0;function o$1(_,o,e,n$1,t){var f={} ;for(var l in o)"ref"!=l&&(f[l]=o[l]);var s,u,a={type:_,props:f,key:e, ref:o&&o.ref,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null, constructor:void 0,__v:++n.__v,__source:n$1,__self:t} ;if("function"==typeof _&&(s=_.defaultProps))for(u in s)void 0===f[u]&&(f[u]=s[u]) ;return n.vnode&&n.vnode(a),a} var t,u,r,o=0,i=[],c=n.__b,f=n.__r,e=n.diffed,a=n.__c,v=n.unmount ;function m(t,r){n.__h&&n.__h(u,t,o||r),o=0;var i=u.__H||(u.__H={__:[],__h:[]}) ;return t>=i.__.length&&i.__.push({}),i.__[t]}function l(n){return o=1,p(w$1,n)} function p(n,r,o){var i=m(t++,2) ;return i.t=n,i.__c||(i.__=[o?o(r):w$1(void 0,r),function(n){ var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({})) }],i.__c=u),i.__}function y(r,o){var i=m(t++,3) ;!n.__s&&k(i.__H,o)&&(i.__=r,i.__H=o,u.__H.__h.push(i))}function s(n){ return o=5,d((function(){return{current:n}}),[])}function d(n,u){var r=m(t++,7) ;return k(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A$1(n,t){ return o=8,d((function(){return n}),t)}function F$1(n){ var r=u.context[n.__c],o=m(t++,9) ;return o.__c=n,r?(null==o.__&&(o.__=!0,r.sub(u)),r.props.value):n.__} function x(){i.forEach((function(t){if(t.__P)try{ t.__H.__h.forEach(g),t.__H.__h.forEach(j),t.__H.__h=[]}catch(u){ t.__H.__h=[],n.__e(u,t.__v)}})),i=[]}n.__b=function(n){u=null,c&&c(n) },n.__r=function(n){f&&f(n),t=0;var r=(u=n.__c).__H ;r&&(r.__h.forEach(g),r.__h.forEach(j),r.__h=[])},n.diffed=function(t){e&&e(t) ;var o=t.__c ;o&&o.__H&&o.__H.__h.length&&(1!==i.push(o)&&r===n.requestAnimationFrame||((r=n.requestAnimationFrame)||function(n){ var t,u=function(){clearTimeout(r),b&&cancelAnimationFrame(t),setTimeout(n) },r=setTimeout(u,100);b&&(t=requestAnimationFrame(u))})(x)),u=void 0 },n.__c=function(t,u){u.some((function(t){try{ t.__h.forEach(g),t.__h=t.__h.filter((function(n){return!n.__||j(n)}))}catch(r){ u.some((function(n){n.__h&&(n.__h=[])})),u=[],n.__e(r,t.__v)}})),a&&a(t,u) },n.unmount=function(t){v&&v(t);var u=t.__c;if(u&&u.__H)try{u.__H.__.forEach(g) }catch(t){n.__e(t,u.__v)}};var b="function"==typeof requestAnimationFrame ;function g(n){var t=u;"function"==typeof n.__c&&n.__c(),u=t}function j(n){ var t=u;n.__c=n.__(),u=t}function k(n,t){ return!n||n.length!==t.length||t.some((function(t,u){return t!==n[u]}))} function w$1(n,t){return"function"==typeof t?t(n):t} function useDocumentEventListener(type,listener,options){y((()=>{ document.addEventListener(type,listener,options) ;return()=>document.removeEventListener(type,listener,options) }),[listener,options,type])}class Icon{constructor(projectName,pageTitle){ this.projectName=projectName;this.pageTitle=pageTitle} getShortPagePath(currentProjectName){ if(this.projectName===currentProjectName)return this.pageTitle ;return`/${this.projectName}/${this.pageTitle}`}get fullPagePath(){ return`/${this.projectName}/${this.pageTitle}`}get imgAlt(){ return this.pageTitle}get imgTitle(){return this.pageTitle}get imgSrc(){ return`/api/pages/${this.projectName}/${encodeURIComponent(this.pageTitle)}/icon` }getNotation(currentProjectName){ return`[${this.getShortPagePath(currentProjectName)}.icon]`}equals(target){ return this.fullPagePath===target.fullPagePath}} function iconLinkElementToIcon(currentProjectName,iconLinkElement){ const imgElement=iconLinkElement.querySelector("img.icon") ;if(!imgElement)throw new Error(`.icon.link の子要素 img.icon がありません。iconLinkElement.innnerHTML: ${iconLinkElement.innerHTML}`) ;const isCurrentProjectIcon=iconLinkElement.pathname.startsWith(`/${currentProjectName}/`) ;const projectName=isCurrentProjectIcon?currentProjectName:iconLinkElement.pathname.slice(1,iconLinkElement.pathname.indexOf("/",1)) ;return new Icon(projectName,imgElement.alt)} function hasDuplicatedPageTitle(icon,suggestedIcons){ for(const suggestedIcon of suggestedIcons){ if(suggestedIcon.equals(icon))continue ;if(suggestedIcon.pageTitle===icon.pageTitle)return true}return false} function scanEmbeddedIcons(projectName,editor){ const iconLinkElements=Array.from(editor.querySelectorAll("a.link.icon")) ;return iconLinkElements.map((iconLinkElement=>iconLinkElementToIcon(projectName,iconLinkElement))) }function calcCursorPosition(cursor){const top=+cursor.style.top.slice(0,-2) ;const left=+cursor.style.left.slice(0,-2);return{styleTop:top,styleLeft:left}} function insertText(textInput,text){textInput.focus();textInput.value=text ;const uiEvent=document.createEvent("UIEvent") ;uiEvent.initEvent("input",true,false);textInput.dispatchEvent(uiEvent)} function getEditor(){const editor=document.querySelector(".editor") ;if(editor)return editor;throw new Error(".editor が存在しません")} const ScrapboxContext=q({scrapbox:window.scrapbox,editor:getEditor()}) ;function useScrapbox(){ const{scrapbox:scrapbox,editor:editor}=F$1(ScrapboxContext) ;const[layout,setLayout]=l(scrapbox.Layout) ;const[projectName,setProjectName]=l(scrapbox.Project.name);y((()=>{ if(scrapbox.addListener){const onLayoutChanged=()=>setLayout(scrapbox.Layout) ;const onProjectChanged=()=>setProjectName(scrapbox.Project.name) ;scrapbox.addListener("layout:changed",onLayoutChanged) ;scrapbox.addListener("project:changed",onProjectChanged);return()=>{ scrapbox.removeListener("layout:changed",onLayoutChanged) ;scrapbox.removeListener("project:changed",onProjectChanged)}}else{ const observer=new MutationObserver((()=>{setLayout(scrapbox.Layout) ;setProjectName(scrapbox.Project.name)})) ;observer.observe(document.querySelector("title"),{childList:true}) ;return()=>observer.disconnect()}}),[scrapbox]) ;const cursor=editor.querySelector(".cursor") ;const textInput=editor.querySelector("#text-input") ;if(!cursor)throw new Error(".cursor が存在しません") ;if(!textInput)throw new Error("#text-input が存在しません");return{layout:layout, projectName:projectName,editor:editor,cursor:cursor,textInput:textInput}} function uniqueBy(arr,fn){const result=[];const keys=new Set ;for(const el of arr){const key=fn(el);if(!keys.has(key)){keys.add(key) ;result.push(el)}}return result}function uniqueIcons(icons){ return uniqueBy(icons,(icon=>icon.fullPagePath))}function isComposing(e){ return e.isComposing||e.key==="Enter"&&e.which===229}function C(n,t){ for(var e in t)n[e]=t[e];return n}function S(n,t){ for(var e in n)if("__source"!==e&&!(e in t))return!0 ;for(var r in t)if("__source"!==r&&n[r]!==t[r])return!0;return!1}function E(n){ this.props=n} (E.prototype=new p$1).isPureReactComponent=!0,E.prototype.shouldComponentUpdate=function(n,t){ return S(this.props,n)||S(this.state,t)};var w=n.__b;n.__b=function(n){ n.type&&n.type.__f&&n.ref&&(n.props.ref=n.ref,n.ref=null),w&&w(n)};var A=n.__e ;n.__e=function(n,t,e){ if(n.then)for(var r,u=t;u=u.__;)if((r=u.__c)&&r.__c)return null==t.__e&&(t.__e=e.__e, t.__k=e.__k),r.__c(n,t);A(n,t,e)};var O=n.unmount;function L(){ this.__u=0,this.t=null,this.__b=null}function U(n){var t=n.__.__c ;return t&&t.__e&&t.__e(n)}function F(){this.u=null,this.o=null} n.unmount=function(n){var t=n.__c ;t&&t.__R&&t.__R(),t&&!0===n.__h&&(n.type=null),O&&O(n) },(L.prototype=new p$1).__c=function(n,t){var e=t.__c,r=this ;null==r.t&&(r.t=[]),r.t.push(e);var u=U(r.__v),o=!1,i=function(){ o||(o=!0,e.__R=null,u?u(l):l())};e.__R=i;var l=function(){if(!--r.__u){ if(r.state.__e){var n=r.state.__e;r.__v.__k[0]=function n(t,e,r){ return t&&(t.__v=null,t.__k=t.__k&&t.__k.map((function(t){return n(t,e,r) })),t.__c&&t.__c.__P===e&&(t.__e&&r.insertBefore(t.__e,t.__d), t.__c.__e=!0,t.__c.__P=r)),t}(n,n.__c.__P,n.__c.__O)}var t;for(r.setState({ __e:r.__b=null});t=r.t.pop();)t.forceUpdate()}},f=!0===t.__h ;r.__u++||f||r.setState({__e:r.__b=r.__v.__k[0]}),n.then(i,i) },L.prototype.componentWillUnmount=function(){this.t=[] },L.prototype.render=function(n,t){if(this.__b){if(this.__v.__k){ var e=document.createElement("div"),r=this.__v.__k[0].__c ;this.__v.__k[0]=function n(t,e,r){ return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach((function(n){ "function"==typeof n.__c&&n.__c() })),t.__c.__H=null),null!=(t=C({},t)).__c&&(t.__c.__P===r&&(t.__c.__P=e), t.__c=null),t.__k=t.__k&&t.__k.map((function(t){return n(t,e,r)}))),t }(this.__b,e,r.__O=r.__P)}this.__b=null}var u=t.__e&&a$1(y$1,null,n.fallback) ;return u&&(u.__h=null),[a$1(y$1,null,t.__e?null:n.children),u]} ;var M=function(n,t,e){ if(++e[1]===e[0]&&n.o.delete(t),n.props.revealOrder&&("t"!==n.props.revealOrder[0]||!n.o.size))for(e=n.u;e;){ for(;e.length>3;)e.pop()();if(e[1]<e[0])break;n.u=e=e[2]}} ;(F.prototype=new p$1).__e=function(n){var t=this,e=U(t.__v),r=t.o.get(n) ;return r[0]++,function(u){var o=function(){ t.props.revealOrder?(r.push(u),M(t,n,r)):u()};e?e(o):o()} },F.prototype.render=function(n){this.u=null,this.o=new Map ;var t=w$2(n.children);n.revealOrder&&"b"===n.revealOrder[0]&&t.reverse() ;for(var e=t.length;e--;)this.o.set(t[e],this.u=[1,0,this.u]);return n.children },F.prototype.componentDidUpdate=F.prototype.componentDidMount=function(){ var n=this;this.o.forEach((function(t,e){M(n,e,t)}))} ;var W="undefined"!=typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,P=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,V=function(n){ return("undefined"!=typeof Symbol&&"symbol"==typeof Symbol()?/fil|che|rad/i:/fil|che|ra/i).test(n) } ;p$1.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach((function(n){ Object.defineProperty(p$1.prototype,n,{configurable:!0,get:function(){ return this["UNSAFE_"+n]},set:function(t){Object.defineProperty(this,n,{ configurable:!0,writable:!0,value:t})}})}));var H=n.event;function Z(){} function Y(){return this.cancelBubble}function $(){return this.defaultPrevented} n.event=function(n){ return H&&(n=H(n)),n.persist=Z,n.isPropagationStopped=Y,n.isDefaultPrevented=$, n.nativeEvent=n};var G={configurable:!0,get:function(){return this.class} },J=n.vnode;n.vnode=function(n){var t=n.type,e=n.props,r=e ;if("string"==typeof t){for(var u in r={},e){var o=e[u] ;"value"===u&&"defaultValue"in e&&null==o||("defaultValue"===u&&"value"in e&&null==e.value?u="value":"download"===u&&!0===o?o="":/ondoubleclick/i.test(u)?u="ondblclick":/^onchange(textarea|input)/i.test(u+t)&&!V(e.type)?u="oninput":/^on(Ani|Tra|Tou|BeforeInp)/.test(u)?u=u.toLowerCase():P.test(u)?u=u.replace(/[A-Z0-9]/,"-$&").toLowerCase():null===o&&(o=void 0), r[u]=o)} "select"==t&&r.multiple&&Array.isArray(r.value)&&(r.value=w$2(e.children).forEach((function(n){ n.props.selected=-1!=r.value.indexOf(n.props.value) }))),"select"==t&&null!=r.defaultValue&&(r.value=w$2(e.children).forEach((function(n){ n.props.selected=r.multiple?-1!=r.defaultValue.indexOf(n.props.value):r.defaultValue==n.props.value }))),n.props=r} t&&e.class!=e.className&&(G.enumerable="className"in e,null!=e.className&&(r.class=e.className), Object.defineProperty(r,"className",G)),n.$$typeof=W,J&&J(n)};var K=n.__r ;n.__r=function(n){K&&K(n),n.__c} ;"object"==typeof performance&&"function"==typeof performance.now?performance.now.bind(performance):function(){ return Date.now()};function useResolvedElement(subscriber,refOrElement){var _ref ;var ref=null;var refElement=s(null);var callbackRefElement=s(null) ;var refCallback=A$1((function(element){callbackRefElement.current=element ;callSubscriber()}),[]);var lastReportedElementRef=s(null);var cleanupRef=s() ;var callSubscriber=function callSubscriber(){var element=null ;if(callbackRefElement.current){element=callbackRefElement.current }else if(refElement.current){element=refElement.current }else if(refOrElement instanceof HTMLElement){element=refOrElement} if(lastReportedElementRef.current===element){return}if(cleanupRef.current){ cleanupRef.current();cleanupRef.current=null} lastReportedElementRef.current=element;if(element){ cleanupRef.current=subscriber(element)}} ;if(refOrElement&&!(refOrElement instanceof HTMLElement)){ref=refOrElement} y((function(){if(ref){refElement.current=ref.current}callSubscriber() }),[ref,(_ref=ref)==null?void 0:_ref.current,refOrElement]);return refCallback} function useResizeObserver(opts){if(opts===void 0){opts={}} var onResize=opts.onResize;var onResizeRef=s(undefined) ;onResizeRef.current=onResize;var resizeObserverRef=s();var _useState=l({ width:undefined,height:undefined}),size=_useState[0],setSize=_useState[1] ;var didUnmount=s(false);y((function(){return function(){didUnmount.current=true }}),[]);var previous=s({width:undefined,height:undefined}) ;var refCallback=useResolvedElement((function(element){ if(!resizeObserverRef.current){ resizeObserverRef.current=new ResizeObserver((function(entries){ if(!Array.isArray(entries)){return}if(!entries.length){return} var entry=entries[0];var newWidth=Math.round(entry.contentRect.width) ;var newHeight=Math.round(entry.contentRect.height) ;if(previous.current.width!==newWidth||previous.current.height!==newHeight){ var newSize={width:newWidth,height:newHeight};if(onResizeRef.current){ onResizeRef.current(newSize)}else{previous.current.width=newWidth ;previous.current.height=newHeight;if(!didUnmount.current){setSize(newSize)}}} }))}resizeObserverRef.current.observe(element);return function(){ if(resizeObserverRef.current){resizeObserverRef.current.unobserve(element)}} }),opts.ref);return d((function(){return{ref:refCallback,width:size.width, height:size.height}}),[refCallback,size?size.width:null,size?size.height:null])} function calcPopupMenuStyle(cursorPosition){return{top:cursorPosition.styleTop}} function calcTriangleStyle(cursorPosition,isEmpty){return{ left:cursorPosition.styleLeft,...isEmpty?{borderTopColor:"#555"}:{}}} function calcButtonContainerStyle(editorWidth,buttonContainerWidth,cursorPosition,isEmpty){ const translateX=cursorPosition.styleLeft/editorWidth*100 ;const minTranslateX=20/buttonContainerWidth*100 ;const maxTranslateX=100-minTranslateX;return{left:cursorPosition.styleLeft, transform:`translateX(-${Math.max(minTranslateX,Math.min(translateX,maxTranslateX))}%)`, ...isEmpty?{color:"#eee",fontSize:"11px",display:"inline-block",padding:"0 5px", cursor:"not-allowed",backgroundColor:"#555"}:{}}} function calcSearchInputStyle(editorWidth,cursorPosition){ const translateX=cursorPosition.styleLeft/editorWidth*100;return{ position:"absolute",top:cursorPosition.styleTop,left:cursorPosition.styleLeft, transform:`translateX(-${translateX}%)`}} function PopupMenuButton({children:children,selected:selected}){ return o$1("div",Object.assign({className:selected?"button selected":"button"},{ children:children}),void 0)} const DEFAULT_IS_CLOSE_POPUP_KEY=e=>e.key==="Escape"&&!e.ctrlKey&&!e.shiftKey&&!e.altKey ;function PopupMenu({open:open,emptyMessage:emptyMessage,cursorPosition:cursorPosition,icons:icons,onSelect:onSelect,onClose:onClose,isClosePopupKey:isClosePopupKey=DEFAULT_IS_CLOSE_POPUP_KEY}){ const{editor:editor}=useScrapbox() ;const{ref:ref,width:buttonContainerWidth=0}=useResizeObserver() ;const isEmpty=d((()=>icons.length===0),[icons.length]) ;const[selectedIndex,setSelectedIndex]=l(null) ;const{width:editorWidth=0}=useResizeObserver({ref:editor});y((()=>{ setSelectedIndex(isEmpty?null:0)}),[isEmpty,icons]) ;const handleKeydown=A$1((e=>{if(!open)return;if(isComposing(e))return ;const isTab=e.key==="Tab"&&!e.ctrlKey&&!e.shiftKey&&!e.altKey ;const isShiftTab=e.key==="Tab"&&!e.ctrlKey&&e.shiftKey&&!e.altKey ;const isEnter=e.key==="Enter"&&!e.ctrlKey&&!e.shiftKey&&!e.altKey ;const isClose=isClosePopupKey(e);if(isTab||isShiftTab||isEnter||isClose){ e.preventDefault();e.stopPropagation()}if(isEmpty||selectedIndex===null){ if(isClose)onClose?.()}else{ if(isTab)setSelectedIndex((selectedIndex+1)%icons.length) ;if(isShiftTab)setSelectedIndex((selectedIndex-1+icons.length)%icons.length) ;if(isEnter)onSelect?.(icons[selectedIndex],selectedIndex) ;if(isClose)onClose?.()} }),[isEmpty,isClosePopupKey,icons,onClose,onSelect,open,selectedIndex]) ;useDocumentEventListener("keydown",handleKeydown,{capture:true}) ;const popupMenuStyle=calcPopupMenuStyle(cursorPosition) ;const triangleStyle=calcTriangleStyle(cursorPosition,isEmpty) ;const buttonContainerStyle=calcButtonContainerStyle(editorWidth,buttonContainerWidth,cursorPosition,isEmpty) ;const iconListElement=icons.map(((icon,i)=>{ const label=hasDuplicatedPageTitle(icon,icons)?`${icon.pageTitle} (${icon.projectName})`:icon.pageTitle ;return o$1(PopupMenuButton,Object.assign({selected:selectedIndex===i},{ children:o$1("span",{children:[o$1("img",{alt:icon.imgAlt,title:icon.imgTitle, style:"width: 1.3em; height: 1.3em; object-fit: contain;",src:icon.imgSrc },void 0)," ",o$1("span",Object.assign({"data-testid":"suggested-icon-label"},{ children:label}),void 0)]},void 0)}),icon.fullPagePath)}));return o$1(y$1,{ children:open&&o$1("div",Object.assign({className:"popup-menu", style:popupMenuStyle,"data-testid":"popup-menu"},{ children:[o$1("div",Object.assign({ref:ref,className:"button-container", style:buttonContainerStyle,"data-testid":"button-container"},{ children:icons.length===0?emptyMessage??"アイテムは空です":iconListElement }),void 0),o$1("div",{className:"triangle",style:triangleStyle},void 0)] }),void 0)},void 0)} const SearchInput=({defaultQuery:defaultQuery,cursorPosition:cursorPosition,onInput:onInput,onBlur:onBlur})=>{ const{editor:editor}=useScrapbox();const ref=s() ;const{width:editorWidth=0}=useResizeObserver({ref:editor}) ;const searchInputStyle=calcSearchInputStyle(editorWidth,cursorPosition) ;y((()=>{if(!ref.current)return;const input=ref.current ;requestAnimationFrame((()=>input.focus()))}),[]);const handleInput=A$1((e=>{ if(e.currentTarget)onInput?.(e.currentTarget.value)}),[onInput]) ;return o$1("form",Object.assign({className:"form-inline"},{ children:o$1("input",{ref:ref,className:"form-control",style:searchInputStyle, value:defaultQuery,default:true,onInput:handleInput,onBlur:onBlur, "data-testid":"search-input"},void 0)}),void 0)} ;function SearchablePopupMenu({open:open,emptyMessage:emptyMessage,cursorPosition:cursorPosition,matcher:matcher,onSelect:onSelect,onClose:onClose,onInputQuery:onInputQuery,isExitIconSuggestionKey:isExitIconSuggestionKey}){ const[query,setQuery]=l("") ;const matchedIcons=d((()=>matcher(query)),[matcher,query]);y((()=>{ if(open===false)setQuery("")}),[open]);const handleSelect=A$1(((_icon,index)=>{ onSelect?.(matchedIcons[index])}),[matchedIcons,onSelect]) ;const handleClose=A$1((()=>{onClose?.()}),[onClose]) ;const handleInputQuery=A$1((query=>{setQuery(query);onInputQuery?.(query) }),[onInputQuery]);return o$1("div",{children:[o$1(PopupMenu,{open:open, emptyMessage:emptyMessage,icons:matchedIcons,cursorPosition:cursorPosition, onSelect:handleSelect,onClose:handleClose, isClosePopupKey:isExitIconSuggestionKey},void 0),open&&o$1(SearchInput,{ defaultQuery:query,cursorPosition:cursorPosition,onInput:handleInputQuery, onBlur:handleClose},void 0)]},void 0)} const DEFAULT_IS_LAUNCH_ICON_SUGGESTION_KEY=e=>e.key==="l"&&e.ctrlKey&&!e.shiftKey&&!e.altKey&&!e.metaKey ;const DEFAULT_IS_INSERT_QUERY_AS_ICON_KEY=e=>{ if(e.key==="Enter"&&!e.ctrlKey&&!e.shiftKey&&e.altKey&&!e.metaKey)return true ;if(e.key==="Enter"&&!e.ctrlKey&&!e.shiftKey&&!e.altKey&&e.metaKey)return true ;return false} ;const App=({isLaunchIconSuggestionKey:isLaunchIconSuggestionKey=DEFAULT_IS_LAUNCH_ICON_SUGGESTION_KEY,isExitIconSuggestionKey:isExitIconSuggestionKey,isInsertQueryAsIconKey:isInsertQueryAsIconKey=DEFAULT_IS_INSERT_QUERY_AS_ICON_KEY,presetIcons:presetIcons=[],defaultIsShownPresetIcons:defaultIsShownPresetIcons=true,matcher:matcher=forwardPartialFuzzyMatcher})=>{ const{textInput:textInput,cursor:cursor,editor:editor,layout:layout,projectName:projectName}=useScrapbox() ;const[open,setOpen]=l(false);const[cursorPosition,setCursorPosition]=l({ styleTop:0,styleLeft:0});const[embeddedIcons,setEmbeddedIcons]=l([]) ;const[isShownPresetIcons,setIsShownPresetIcons]=l(defaultIsShownPresetIcons) ;const composedMatcher=A$1((query=>{ const composedIcons=uniqueIcons(isShownPresetIcons?[...embeddedIcons,...presetIcons]:embeddedIcons) ;return matcher({query:query,composedIcons:composedIcons, presetIcons:presetIcons,embeddedIcons:embeddedIcons}) }),[embeddedIcons,matcher,presetIcons,isShownPresetIcons]) ;const[query,setQuery]=l("");const handleSelect=A$1((icon=>{setOpen(false) ;insertText(textInput,icon.getNotation(projectName))}),[projectName,textInput]) ;const handleClose=A$1((()=>{setOpen(false);textInput.focus()}),[textInput]) ;const handleLaunchIconSuggestionKeyDown=A$1((e=>{if(layout!=="page")return ;e.preventDefault();e.stopPropagation();if(!open){ setCursorPosition(calcCursorPosition(cursor));textInput.blur() ;const newEmbeddedIcons=scanEmbeddedIcons(projectName,editor) ;setEmbeddedIcons(newEmbeddedIcons);setOpen(true) ;setIsShownPresetIcons(defaultIsShownPresetIcons)}else{ setIsShownPresetIcons((isShownPresetIcons=>!isShownPresetIcons))} }),[cursor,defaultIsShownPresetIcons,editor,open,layout,projectName,textInput]) ;const handleInsertQueryAsIconKeyDown=A$1((e=>{if(layout!=="page")return ;if(!open)return;e.preventDefault();e.stopPropagation();setOpen(false) ;insertText(textInput,`[${query}.icon]`)}),[layout,open,textInput,query]) ;const handleKeydown=A$1((e=>{if(isComposing(e))return ;if(isLaunchIconSuggestionKey(e)){handleLaunchIconSuggestionKeyDown(e) }else if(isInsertQueryAsIconKey(e)){handleInsertQueryAsIconKeyDown(e)} }),[isLaunchIconSuggestionKey,isInsertQueryAsIconKey,handleLaunchIconSuggestionKeyDown,handleInsertQueryAsIconKeyDown]) ;useDocumentEventListener("keydown",handleKeydown,{capture:true}) ;return o$1(SearchablePopupMenu,{open:open,emptyMessage:"キーワードにマッチするアイコンがありません", cursorPosition:cursorPosition,matcher:composedMatcher,onSelect:handleSelect, onClose:handleClose,onInputQuery:setQuery, isExitIconSuggestionKey:isExitIconSuggestionKey},void 0)} ;function Warning({children:children}){return o$1("div",Object.assign({style:{ background:"black",padding:"2em"}},{children:[o$1("h2",Object.assign({style:{ fontSize:"xx-large",color:"yellow"}},{children:["⚠️ ",o$1("a",Object.assign({ href:"https://scrapbox.io/customize/icon-suggestion"},{ children:"icon-suggestion"}),void 0)," による警告"] }),void 0),o$1("section",Object.assign({style:{fontSize:"large",color:"white"} },{children:children}),void 0)]}),void 0)}function RenamedOptionsWarning(){ const tdStyle={padding:"8px 8px",border:"1px solid #fff"};return o$1(Warning,{ children:[o$1("p",{children:"icon-suggestion のアップデートにより、いくつかのオプションの名前が変更されました。" },void 0),o$1("table",Object.assign({style:{margin:"15px 0"}},{ children:[o$1("thead",{children:[o$1("th",Object.assign({style:tdStyle},{ children:"古いオプション名"}),void 0),o$1("th",Object.assign({style:tdStyle},{ children:"新しいオプション名"}),void 0)]},void 0),o$1("tbody",{children:[o$1("tr",{ children:[o$1("td",Object.assign({style:tdStyle},{children:o$1("code",{ children:"isSuggestionOpenKeyDown"},void 0)}),void 0),o$1("td",Object.assign({ style:tdStyle},{children:o$1("code",{children:"isLaunchIconSuggestionKey" },void 0)}),void 0)]},void 0),o$1("tr",{children:[o$1("td",Object.assign({ style:tdStyle},{children:o$1("code",{children:"isSuggestionCloseKeyDown" },void 0)}),void 0),o$1("td",Object.assign({style:tdStyle},{ children:o$1("code",{children:"isExitIconSuggestionKey"},void 0)}),void 0)] },void 0),o$1("tr",{children:[o$1("td",Object.assign({style:tdStyle},{ children:o$1("code",{children:"isInsertQueryKeyDown"},void 0) }),void 0),o$1("td",Object.assign({style:tdStyle},{children:o$1("code",{ children:"isInsertQueryAsIconKey"},void 0)}),void 0)]},void 0),o$1("tr",{ children:[o$1("td",Object.assign({style:tdStyle},{children:o$1("code",{ children:"defaultSuggestPresetIcons"},void 0)}),void 0),o$1("td",Object.assign({ style:tdStyle},{children:o$1("code",{children:"defaultIsShownPresetIcons" },void 0)}),void 0)]},void 0)]},void 0)]}),void 0),o$1("p",{ children:"今後は古い名前のオプションはご利用頂けませんので、新しい名前のオプションを利用して下さい。 この警告は当該オプションを置き換えるまで表示され続けます。" },void 0),o$1("p",{children:["アップデートの詳細については ",o$1("a",Object.assign({ href:"https://scrapbox.io/customize/icon-suggestion"},{ children:"icon-suggestion"}),void 0)," ","を参照して下さい。"]},void 0)]},void 0)} async function evaluatePresetIconItemToPagePaths(presetIconItem){ if(presetIconItem instanceof Icon)return[presetIconItem] ;if(Array.isArray(presetIconItem)){ const promises=presetIconItem.map(evaluatePresetIconItemToPagePaths) ;return(await Promise.all(promises)).flat()} if(presetIconItem instanceof Promise){ return evaluatePresetIconItemToPagePaths(await presetIconItem)} const presetIconItems=await presetIconItem() ;const promises=presetIconItems.map(evaluatePresetIconItemToPagePaths) ;return(await Promise.all(promises)).flat()} async function evaluatePresetIconItemsToIcons(presetIconItems){ const nestedPagePaths=await Promise.all(presetIconItems.map(evaluatePresetIconItemToPagePaths)) ;return nestedPagePaths.flat()}async function registerIconSuggestion(options){ const container=document.createElement("div") ;const editor=options?.editor??getEditor();editor.appendChild(container) ;const warningMessageContainer=document.createElement("div") ;document.querySelector(".app")?.prepend(warningMessageContainer) ;if(options?.isSuggestionOpenKeyDown!==undefined||options?.isSuggestionCloseKeyDown!==undefined||options?.isInsertQueryKeyDown!==undefined||options?.defaultSuggestPresetIcons!==undefined){ N(o$1(RenamedOptionsWarning,{},void 0),warningMessageContainer);return} const presetIcons=options?.presetIcons?await evaluatePresetIconItemsToIcons(options.presetIcons):undefined ;N(o$1(App,{isLaunchIconSuggestionKey:options?.isLaunchIconSuggestionKey, isExitIconSuggestionKey:options?.isExitIconSuggestionKey, isInsertQueryAsIconKey:options?.isInsertQueryAsIconKey,presetIcons:presetIcons, defaultIsShownPresetIcons:options?.defaultIsShownPresetIcons, matcher:options?.matcher},void 0),container)} async function fetchMemberPageIcons(projectName){ const{origin:origin}=window.location ;const[projectJson,pageJson]=await Promise.all([fetch(`${origin}/api/projects/${projectName}`).then((async res=>res.json())),fetch(`${origin}/api/pages/${projectName}/member`).then((async res=>res.json()))]) ;const relatedPages=pageJson.relatedPages ;if(!projectJson.users||!relatedPages)throw new Error(`You are not a member of \`${projectName}\` project.`) ;const userNames=projectJson.users.map((user=>user.name)) ;const userNamesWithIcon=userNames.filter((userName=>{ const link=relatedPages.links1hop.find((link=>link.title===userName)) ;return link&&link.image!==null})) ;return userNamesWithIcon.map((userName=>new Icon(projectName,userName)))} async function fetchRelatedPageIconsByHashTag(projectName,hashTag){ const{origin:origin}=window.location ;const pageJson=await fetch(`${origin}/api/pages/${projectName}/${encodeURIComponent(hashTag)}`).then((async res=>res.json())) ;if(!pageJson.relatedPages)throw new Error(`You are not a member of \`${projectName}\` project.`) ;const pagesWithIcon=pageJson.relatedPages.links1hop.filter((page=>page.image!==null)) ;return pagesWithIcon.map((page=>new Icon(projectName,page.title)))} const INITPAT=2147483648;const MAXCHAR=65536;const INITSTATE=[INITPAT,0,0,0] ;const isupper=c=>c>=65&&c<=90;const islower=c=>c>=97&&c<=122 ;const tolower=c=>isupper(c)?c+32:c;const toupper=c=>islower(c)?c-32:c ;var asearch=function Asearch(source){const shiftpat=[];let epsilon=0 ;let acceptpat=0;let mask=INITPAT;for(let i=0;i<MAXCHAR;i++){shiftpat[i]=0} for(let i of unpack(source)){if(i===32){epsilon|=mask}else{shiftpat[i]|=mask ;shiftpat[toupper(i)]|=mask;shiftpat[tolower(i)]|=mask;mask=mask>>>1}} acceptpat=mask;function getState(state=INITSTATE,str=""){let i0=state[0] ;let i1=state[1];let i2=state[2];let i3=state[3];for(let c of unpack(str)){ mask=shiftpat[c];i3=i3&epsilon|(i3&mask)>>>1|i2>>>1|i2 ;i2=i2&epsilon|(i2&mask)>>>1|i1>>>1|i1;i1=i1&epsilon|(i1&mask)>>>1|i0>>>1|i0 ;i0=i0&epsilon|(i0&mask)>>>1;i1|=i0>>>1;i2|=i1>>>1;i3|=i2>>>1} return[i0,i1,i2,i3]}function unpack(str){const bytes=[] ;for(let c of str.split("")){const code=c.charCodeAt(0);bytes.push(code)} return bytes}function match(str,ambig=0){const state=getState(INITSTATE,str) ;if(ambig>=INITSTATE.length){ambig=INITSTATE.length-1} return(state[ambig]&acceptpat)!==0}match.source=source;return match} ;function fuzzyMatcher({query:query,composedIcons:composedIcons}){ const maxAambig=Math.min(Math.floor(query.length/3),3) ;const match=asearch(` ${query} `);const newIcons=[] ;for(let ambig=0;ambig<=maxAambig;ambig++){for(const icon of composedIcons){ if(match(icon.pageTitle,ambig))newIcons.push(icon)}}return uniqueIcons(newIcons) }function forwardMatcher({query:query,composedIcons:composedIcons}){ return composedIcons.filter((icon=>icon.pageTitle.toLowerCase().startsWith(query.toLowerCase()))) }function partialMatcher({query:query,composedIcons:composedIcons}){ return composedIcons.filter((icon=>icon.pageTitle.toLowerCase().includes(query.toLowerCase()))) }function forwardPartialFuzzyMatcher(options){ const newIcons=[...forwardMatcher(options),...partialMatcher(options),...fuzzyMatcher(options)] ;return uniqueIcons(newIcons)} export{Icon,fetchMemberPageIcons,fetchRelatedPageIconsByHashTag,forwardMatcher,forwardPartialFuzzyMatcher,fuzzyMatcher,partialMatcher,registerIconSuggestion,uniqueIcons};