Compare commits

...

No commits in common. "main" and "gh-pages" have entirely different histories.

115 changed files with 51109 additions and 1866 deletions

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
site
.DS_Store

0
.nojekyll Normal file
View file

1336
404.html Normal file

File diff suppressed because it is too large Load diff

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 Viktor Shchelochkov <hi@hloth.dev> (https://hloth.dev)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,17 +0,0 @@
# Session.js documentation website
[![image](./screenshot.avif)](https://sessionjs.github.io/docs)
[Visit documentation website](https://sessionjs.github.io/docs)
## Made for Session.js
Use Session messenger programmatically with [Session.js](https://git.hloth.dev/session.js/client): Session bots, custom Session clients, and more.
## Donate
[hloth.dev/donate](https://hloth.dev/donate) · Tor: [hlothdevzkti6suoksy7lcy7hmpxnr3msu5waokzaslsi2mnx5ouu4qd.onion/donate](http://hlothdevzkti6suoksy7lcy7hmpxnr3msu5waokzaslsi2mnx5ouu4qd.onion/donate)
## License
[MIT](./LICENSE)

File diff suppressed because it is too large Load diff

BIN
assets/images/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,18 @@
/*!
* Lunr languages, `Danish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d<a&&(d=a)}}function n(){var e,r;if(f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Z--0-9-",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hy=function(){this.pipeline.reset(),this.pipeline.add(e.hy.trimmer,e.hy.stopWordFilter)},e.hy.wordCharacters="[A-Za-z԰-֏ff-ﭏ]",e.hy.trimmer=e.trimmerSupport.generateTrimmer(e.hy.wordCharacters),e.Pipeline.registerFunction(e.hy.trimmer,"trimmer-hy"),e.hy.stopWordFilter=e.generateStopWordFilter("դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում".split(" ")),e.Pipeline.registerFunction(e.hy.stopWordFilter,"stopWordFilter-hy"),e.hy.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}(),e.Pipeline.registerFunction(e.hy.stemmer,"stemmer-hy")}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n<p.length;n++)r?a.push(new e.Token(p[n],{position:[f,p[n].length],index:a.length})):a.push(p[n]),f+=p[n].length;l=c+1}return a},e.ja.stemmer=function(){return function(e){return e}}(),e.Pipeline.registerFunction(e.ja.stemmer,"stemmer-ja"),e.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Z--0-9-",e.ja.trimmer=e.trimmerSupport.generateTrimmer(e.ja.wordCharacters),e.Pipeline.registerFunction(e.ja.trimmer,"trimmer-ja"),e.ja.stopWordFilter=e.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),e.Pipeline.registerFunction(e.ja.stopWordFilter,"stopWordFilter-ja"),e.jp=e.ja,e.Pipeline.registerFunction(e.jp.stemmer,"stemmer-jp"),e.Pipeline.registerFunction(e.jp.trimmer,"trimmer-jp"),e.Pipeline.registerFunction(e.jp.stopWordFilter,"stopWordFilter-jp")}});

View file

@ -0,0 +1 @@
module.exports=require("./lunr.ja");

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.kn=function(){this.pipeline.reset(),this.pipeline.add(e.kn.trimmer,e.kn.stopWordFilter,e.kn.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.kn.stemmer))},e.kn.wordCharacters="ಀ-಄ಅ-ಔಕ-ಹಾ-ೌ಼-ಽೕ-ೖೝ-ೞೠ-ೡೢ-ೣ೤೥೦-೯ೱ-ೳ",e.kn.trimmer=e.trimmerSupport.generateTrimmer(e.kn.wordCharacters),e.Pipeline.registerFunction(e.kn.trimmer,"trimmer-kn"),e.kn.stopWordFilter=e.generateStopWordFilter("ಮತ್ತು ಈ ಒಂದು ರಲ್ಲಿ ಹಾಗೂ ಎಂದು ಅಥವಾ ಇದು ರ ಅವರು ಎಂಬ ಮೇಲೆ ಅವರ ತನ್ನ ಆದರೆ ತಮ್ಮ ನಂತರ ಮೂಲಕ ಹೆಚ್ಚು ನ ಆ ಕೆಲವು ಅನೇಕ ಎರಡು ಹಾಗು ಪ್ರಮುಖ ಇದನ್ನು ಇದರ ಸುಮಾರು ಅದರ ಅದು ಮೊದಲ ಬಗ್ಗೆ ನಲ್ಲಿ ರಂದು ಇತರ ಅತ್ಯಂತ ಹೆಚ್ಚಿನ ಸಹ ಸಾಮಾನ್ಯವಾಗಿ ನೇ ಹಲವಾರು ಹೊಸ ದಿ ಕಡಿಮೆ ಯಾವುದೇ ಹೊಂದಿದೆ ದೊಡ್ಡ ಅನ್ನು ಇವರು ಪ್ರಕಾರ ಇದೆ ಮಾತ್ರ ಕೂಡ ಇಲ್ಲಿ ಎಲ್ಲಾ ವಿವಿಧ ಅದನ್ನು ಹಲವು ರಿಂದ ಕೇವಲ ದ ದಕ್ಷಿಣ ಗೆ ಅವನ ಅತಿ ನೆಯ ಬಹಳ ಕೆಲಸ ಎಲ್ಲ ಪ್ರತಿ ಇತ್ಯಾದಿ ಇವು ಬೇರೆ ಹೀಗೆ ನಡುವೆ ಇದಕ್ಕೆ ಎಸ್ ಇವರ ಮೊದಲು ಶ್ರೀ ಮಾಡುವ ಇದರಲ್ಲಿ ರೀತಿಯ ಮಾಡಿದ ಕಾಲ ಅಲ್ಲಿ ಮಾಡಲು ಅದೇ ಈಗ ಅವು ಗಳು ಎ ಎಂಬುದು ಅವನು ಅಂದರೆ ಅವರಿಗೆ ಇರುವ ವಿಶೇಷ ಮುಂದೆ ಅವುಗಳ ಮುಂತಾದ ಮೂಲ ಬಿ ಮೀ ಒಂದೇ ಇನ್ನೂ ಹೆಚ್ಚಾಗಿ ಮಾಡಿ ಅವರನ್ನು ಇದೇ ಯ ರೀತಿಯಲ್ಲಿ ಜೊತೆ ಅದರಲ್ಲಿ ಮಾಡಿದರು ನಡೆದ ಆಗ ಮತ್ತೆ ಪೂರ್ವ ಆತ ಬಂದ ಯಾವ ಒಟ್ಟು ಇತರೆ ಹಿಂದೆ ಪ್ರಮಾಣದ ಗಳನ್ನು ಕುರಿತು ಯು ಆದ್ದರಿಂದ ಅಲ್ಲದೆ ನಗರದ ಮೇಲಿನ ಏಕೆಂದರೆ ರಷ್ಟು ಎಂಬುದನ್ನು ಬಾರಿ ಎಂದರೆ ಹಿಂದಿನ ಆದರೂ ಆದ ಸಂಬಂಧಿಸಿದ ಮತ್ತೊಂದು ಸಿ ಆತನ ".split(" ")),e.kn.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.kn.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var n=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(n).split("|")},e.Pipeline.registerFunction(e.kn.stemmer,"stemmer-kn"),e.Pipeline.registerFunction(e.kn.stopWordFilter,"stopWordFilter-kn")}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){e.multiLanguage=function(){for(var t=Array.prototype.slice.call(arguments),i=t.join("-"),r="",n=[],s=[],p=0;p<t.length;++p)"en"==t[p]?(r+="\\w",n.unshift(e.stopWordFilter),n.push(e.stemmer),s.push(e.stemmer)):(r+=e[t[p]].wordCharacters,e[t[p]].stopWordFilter&&n.unshift(e[t[p]].stopWordFilter),e[t[p]].stemmer&&(n.push(e[t[p]].stemmer),s.push(e[t[p]].stemmer)));var o=e.trimmerSupport.generateTrimmer(r);return e.Pipeline.registerFunction(o,"lunr-multi-trimmer-"+i),n.unshift(o),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,n),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,s))}}}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,18 @@
/*!
* Lunr languages, `Norwegian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a<s&&(a=s)}}function i(){var e,r,n;if(w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sa=function(){this.pipeline.reset(),this.pipeline.add(e.sa.trimmer,e.sa.stopWordFilter,e.sa.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sa.stemmer))},e.sa.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿ꣠-꣱ꣲ-ꣷ꣸-ꣻ꣼-ꣽꣾ-ꣿᆰ0-ᆰ9",e.sa.trimmer=e.trimmerSupport.generateTrimmer(e.sa.wordCharacters),e.Pipeline.registerFunction(e.sa.trimmer,"trimmer-sa"),e.sa.stopWordFilter=e.generateStopWordFilter('तथा अयम्‌ एकम्‌ इत्यस्मिन्‌ तथा तत्‌ वा अयम्‌ इत्यस्य ते आहूत उपरि तेषाम्‌ किन्तु तेषाम्‌ तदा इत्यनेन अधिकः इत्यस्य तत्‌ केचन बहवः द्वि तथा महत्वपूर्णः अयम्‌ अस्य विषये अयं अस्ति तत्‌ प्रथमः विषये इत्युपरि इत्युपरि इतर अधिकतमः अधिकः अपि सामान्यतया ठ इतरेतर नूतनम्‌ द न्यूनम्‌ कश्चित्‌ वा विशालः द सः अस्ति तदनुसारम् तत्र अस्ति केवलम्‌ अपि अत्र सर्वे विविधाः तत्‌ बहवः यतः इदानीम्‌ द दक्षिण इत्यस्मै तस्य उपरि नथ अतीव कार्यम्‌ सर्वे एकैकम्‌ इत्यादि। एते सन्ति उत इत्थम्‌ मध्ये एतदर्थं . स कस्य प्रथमः श्री. करोति अस्मिन् प्रकारः निर्मिता कालः तत्र कर्तुं समान अधुना ते सन्ति स एकः अस्ति सः अर्थात् तेषां कृते . स्थितम् विशेषः अग्रिम तेषाम्‌ समान स्रोतः ख म समान इदानीमपि अधिकतया करोतु ते समान इत्यस्य वीथी सह यस्मिन् कृतवान्‌ धृतः तदा पुनः पूर्वं सः आगतः किम्‌ कुल इतर पुरा मात्रा स विषये उ अतएव अपि नगरस्य उपरि यतः प्रतिशतं कतरः कालः साधनानि भूत तथापि जात सम्बन्धि अन्यत्‌ ग अतः अस्माकं स्वकीयाः अस्माकं इदानीं अन्तः इत्यादयः भवन्तः इत्यादयः एते एताः तस्य अस्य इदम् एते तेषां तेषां तेषां तान् तेषां तेषां तेषां समानः सः एकः च तादृशाः बहवः अन्ये च वदन्ति यत् कियत् कस्मै कस्मै यस्मै यस्मै यस्मै यस्मै न अतिनीचः किन्तु प्रथमं सम्पूर्णतया ततः चिरकालानन्तरं पुस्तकं सम्पूर्णतया अन्तः किन्तु अत्र वा इह इव श्रद्धाय अवशिष्यते परन्तु अन्ये वर्गाः सन्ति ते सन्ति शक्नुवन्ति सर्वे मिलित्वा सर्वे एकत्र"'.split(" ")),e.sa.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.sa.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var i=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(i).split("|")},e.Pipeline.registerFunction(e.sa.stemmer,"stemmer-sa"),e.Pipeline.registerFunction(e.sa.stopWordFilter,"stopWordFilter-sa")}});

View file

@ -0,0 +1 @@
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var r;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(t){r=t,this.cursor=0,this.limit=t.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var t=r;return r=null,t},in_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e>s||e<i)return this.cursor++,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e<i)return this.cursor--,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor+s)!=i.charCodeAt(s))return!1;return this.cursor+=t,!0},eq_s_b:function(t,i){if(this.cursor-this.limit_backward<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor-t+s)!=i.charCodeAt(s))return!1;return this.cursor-=t,!0},find_among:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=l;m<_.s_size;m++){if(n+l==u){f=-1;break}if(f=r.charCodeAt(n+l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=_.s_size-1-l;m>=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});

View file

@ -0,0 +1,18 @@
/*!
* Lunr languages, `Swedish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o<a&&(o=a)}}function t(){var e,r=w.limit_backward;if(w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});

View file

@ -0,0 +1 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="஀-உஊ-ஏஐ-ஙச-ட஠-னப-யர-ஹ஺-ிீ-௉ொ-௏ௐ-௙௚-௟௠-௩௪-௯௰-௹௺-௿a-zA-Z--0-9-",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}});

View file

@ -0,0 +1 @@
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.te=function(){this.pipeline.reset(),this.pipeline.add(e.te.trimmer,e.te.stopWordFilter,e.te.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.te.stemmer))},e.te.wordCharacters="ఀ-ఄఅ-ఔక-హా-ౌౕ-ౖౘ-ౚౠ-ౡౢ-ౣ౦-౯౸-౿఼ఽ్ౝ౷౤౥",e.te.trimmer=e.trimmerSupport.generateTrimmer(e.te.wordCharacters),e.Pipeline.registerFunction(e.te.trimmer,"trimmer-te"),e.te.stopWordFilter=e.generateStopWordFilter("అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం".split(" ")),e.te.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.te.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.te.stemmer,"stemmer-te"),e.Pipeline.registerFunction(e.te.stopWordFilter,"stopWordFilter-te")}});

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});

View file

@ -0,0 +1 @@
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}});

View file

@ -0,0 +1,206 @@
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function () {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
// (c) 2008 Taku Kudo <taku@chasen.org>
// TinySegmenter is freely distributable under the terms of a new BSD licence.
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
function TinySegmenter() {
var patterns = {
"[一二三四五六七八九十百千万億兆]":"M",
"[一-龠々〆ヵヶ]":"H",
"[ぁ-ん]":"I",
"[ァ-ヴーア-ン゙ー]":"K",
"[a-zA-Z--]":"A",
"[0-9-]":"N"
}
this.chartype_ = [];
for (var i in patterns) {
var regexp = new RegExp(i);
this.chartype_.push([regexp, patterns[i]]);
}
this.BIAS__ = -332
this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378};
this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920};
this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266};
this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352};
this.BP2__ = {"BO":60,"OO":-1762};
this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965};
this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146};
this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699};
this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973};
this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682};
this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"":-669};
this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990};
this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832};
this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649};
this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393};
this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841};
this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68};
this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591};
this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685};
this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156};
this.TW1__ = {"につい":-4681,"東京都":2026};
this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216};
this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287};
this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865};
this.UC1__ = {"A":484,"K":93,"M":645,"O":-505};
this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646};
this.UC3__ = {"A":-1370,"I":2311};
this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646};
this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831};
this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387};
this.UP1__ = {"O":-214};
this.UP2__ = {"B":69,"O":935};
this.UP3__ = {"B":189};
this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422};
this.UQ2__ = {"BH":216,"BI":113,"OK":1759};
this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212};
this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135};
this.UW2__ = {",":-829,"、":-829,"":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568};
this.UW3__ = {",":4889,"1":-800,"":-1723,"、":4889,"々":-2311,"":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278};
this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637};
this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"":-514,"":-32768,"「":363,"イ":241,"ル":451,"ン":-343};
this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"":-270,"":306,"ル":-673,"ン":-496};
return this;
}
TinySegmenter.prototype.ctype_ = function(str) {
for (var i in this.chartype_) {
if (str.match(this.chartype_[i][0])) {
return this.chartype_[i][1];
}
}
return "O";
}
TinySegmenter.prototype.ts_ = function(v) {
if (v) { return v; }
return 0;
}
TinySegmenter.prototype.segment = function(input) {
if (input == null || input == undefined || input == "") {
return [];
}
var result = [];
var seg = ["B3","B2","B1"];
var ctype = ["O","O","O"];
var o = input.split("");
for (i = 0; i < o.length; ++i) {
seg.push(o[i]);
ctype.push(this.ctype_(o[i]))
}
seg.push("E1");
seg.push("E2");
seg.push("E3");
ctype.push("O");
ctype.push("O");
ctype.push("O");
var word = seg[3];
var p1 = "U";
var p2 = "U";
var p3 = "U";
for (var i = 4; i < seg.length - 3; ++i) {
var score = this.BIAS__;
var w1 = seg[i-3];
var w2 = seg[i-2];
var w3 = seg[i-1];
var w4 = seg[i];
var w5 = seg[i+1];
var w6 = seg[i+2];
var c1 = ctype[i-3];
var c2 = ctype[i-2];
var c3 = ctype[i-1];
var c4 = ctype[i];
var c5 = ctype[i+1];
var c6 = ctype[i+2];
score += this.ts_(this.UP1__[p1]);
score += this.ts_(this.UP2__[p2]);
score += this.ts_(this.UP3__[p3]);
score += this.ts_(this.BP1__[p1 + p2]);
score += this.ts_(this.BP2__[p2 + p3]);
score += this.ts_(this.UW1__[w1]);
score += this.ts_(this.UW2__[w2]);
score += this.ts_(this.UW3__[w3]);
score += this.ts_(this.UW4__[w4]);
score += this.ts_(this.UW5__[w5]);
score += this.ts_(this.UW6__[w6]);
score += this.ts_(this.BW1__[w2 + w3]);
score += this.ts_(this.BW2__[w3 + w4]);
score += this.ts_(this.BW3__[w4 + w5]);
score += this.ts_(this.TW1__[w1 + w2 + w3]);
score += this.ts_(this.TW2__[w2 + w3 + w4]);
score += this.ts_(this.TW3__[w3 + w4 + w5]);
score += this.ts_(this.TW4__[w4 + w5 + w6]);
score += this.ts_(this.UC1__[c1]);
score += this.ts_(this.UC2__[c2]);
score += this.ts_(this.UC3__[c3]);
score += this.ts_(this.UC4__[c4]);
score += this.ts_(this.UC5__[c5]);
score += this.ts_(this.UC6__[c6]);
score += this.ts_(this.BC1__[c2 + c3]);
score += this.ts_(this.BC2__[c3 + c4]);
score += this.ts_(this.BC3__[c4 + c5]);
score += this.ts_(this.TC1__[c1 + c2 + c3]);
score += this.ts_(this.TC2__[c2 + c3 + c4]);
score += this.ts_(this.TC3__[c3 + c4 + c5]);
score += this.ts_(this.TC4__[c4 + c5 + c6]);
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
score += this.ts_(this.UQ1__[p1 + c1]);
score += this.ts_(this.UQ2__[p2 + c2]);
score += this.ts_(this.UQ3__[p3 + c3]);
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
var p = "O";
if (score > 0) {
result.push(word);
word = "";
p = "B";
}
p1 = p2;
p2 = p3;
p3 = p;
word += seg[i];
}
result.push(word);
return result;
}
lunr.TinySegmenter = TinySegmenter;
};
}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"version":3,"sources":["src/templates/assets/stylesheets/palette/_scheme.scss","../../../../src/templates/assets/stylesheets/palette.scss","src/templates/assets/stylesheets/palette/_accent.scss","src/templates/assets/stylesheets/palette/_primary.scss","src/templates/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"AA2BA,cAGE,6BAME,sDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CACA,mDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CAGA,mDAAA,CACA,gDAAA,CAGA,0BAAA,CACA,mCAAA,CAGA,iCAAA,CACA,kCAAA,CACA,mCAAA,CACA,mCAAA,CACA,kCAAA,CACA,iCAAA,CACA,+CAAA,CACA,6DAAA,CACA,gEAAA,CACA,4DAAA,CACA,4DAAA,CACA,6DAAA,CAGA,6CAAA,CAGA,+CAAA,CAGA,uDAAA,CACA,6DAAA,CACA,2DAAA,CAGA,iCAAA,CAGA,yDAAA,CACA,iEAAA,CAGA,mDAAA,CACA,mDAAA,CAGA,qDAAA,CACA,uDAAA,CAGA,8DAAA,CAKA,8DAAA,CAKA,0DAAA,CAvEA,iBCeF,CD6DE,kHAEE,YC3DJ,CDkFE,yDACE,4BChFJ,CD+EE,2DACE,4BC7EJ,CD4EE,gEACE,4BC1EJ,CDyEE,2DACE,4BCvEJ,CDsEE,yDACE,4BCpEJ,CDmEE,0DACE,4BCjEJ,CDgEE,gEACE,4BC9DJ,CD6DE,0DACE,4BC3DJ,CD0DE,2OACE,4BC/CJ,CDsDA,+FAGE,iCCpDF,CACF,CC/CE,2BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD2CN,CCrDE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDkDN,CC5DE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDyDN,CCnEE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDgEN,CC1EE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDuEN,CCjFE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD8EN,CCxFE,kCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDqFN,CC/FE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD4FN,CCtGE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDmGN,CC7GE,6BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD0GN,CCpHE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDiHN,CC3HE,4BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCD2HN,CClIE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDkIN,CCzIE,6BACE,yBAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDyIN,CChJE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDgJN,CCvJE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDoJN,CEzJE,4BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsJN,CEjKE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8JN,CEzKE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsKN,CEjLE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8KN,CEzLE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsLN,CEjME,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8LN,CEzME,mCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsMN,CEjNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8MN,CEzNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsNN,CEjOE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8NN,CEzOE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsON,CEjPE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiPN,CEzPE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyPN,CEjQE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiQN,CEzQE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyQN,CEjRE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8QN,CEzRE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsRN,CEjSE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BF0RN,CE1SE,kCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BFmSN,CEpRE,sEACE,4BFuRJ,CExRE,+DACE,4BF2RJ,CE5RE,iEACE,4BF+RJ,CEhSE,gEACE,4BFmSJ,CEpSE,iEACE,4BFuSJ,CE9RA,8BACE,mDAAA,CACA,4DAAA,CACA,0DAAA,CACA,oDAAA,CACA,2DAAA,CAGA,4BF+RF,CE5RE,yCACE,+BF8RJ,CE3RI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCF+RN,CG3MI,mCD1EA,+CACE,8CFwRJ,CErRI,qDACE,8CFuRN,CElRE,iEACE,mCFoRJ,CACF,CGtNI,sCDvDA,uCACE,oCFgRJ,CACF,CEvQA,8BACE,kDAAA,CACA,4DAAA,CACA,wDAAA,CACA,oDAAA,CACA,6DAAA,CAGA,4BFwQF,CErQE,yCACE,+BFuQJ,CEpQI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCFwQN,CEjQE,yCACE,6CFmQJ,CG5NI,0CDhCA,8CACE,gDF+PJ,CACF,CGjOI,0CDvBA,iFACE,6CF2PJ,CACF,CGzPI,sCDKA,uCACE,6CFuPJ,CACF","file":"palette.css"}

1396
constants/index.html Normal file

File diff suppressed because it is too large Load diff

1484
deleting-messages/index.html Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,19 +0,0 @@
# Accept conversation request
Conversation requests are purely visibility messages for now. Unaccepted conversation does not actually imply any limitations on recipient. Session clients will use that information to hide conversations or move them to main conversations list, but that's it. When you send message to conversation that hasn't been accepted yet, clients will typically assume that you've accepted it, even without calling this method. However, you can send "conversation accepted" message to someone without sending chat message using this method.
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
session.acceptConversationRequest({
from: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b'
})
```
## Events about accepted conversation requests
See [events page](./events.md#messagerequestapproved)

View file

@ -1,17 +0,0 @@
# Session client constants
You can use some Session client constatnts from `@session.js/consts` such as `CONVERSATION.MAX_VOICE_MESSAGE_DURATION` which should help you define limits for your client.
Here is a full list of constants defined in that module:
- DURATION
- TTL_DEFAULT
- SWARM_POLLING_TIMEOUT
- PROTOCOLS
- CONVERSATION
- MAX_ATTACHMENT_FILESIZE_BYTES
- VALIDATION
- DEFAULT_RECENT_REACTS
- REACT_LIMIT
- MAX_USERNAME_BYTES
- FEATURE_RELEASE_TIMESTAMPS

View file

@ -1,54 +0,0 @@
# Deleting messages
Deleting messages in Session means deleting message from swarm (when recipient hasn't polled it yet so they won't be able to ever see it) and broadcasting UnsendMessage which instructs Session clients to remove polled message locally.
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
const { timestamp, messageHash } = await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Hello world!'
})
// ... Some time later...
await session.deleteMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
timestamp: timestamp,
hash: messageHash
})
```
You can delete many messages at once in a batch request to save traffic and performance
```ts
await session.deleteMessages([
{
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
timestamp: timestamp1,
hash: messageHash1
},
{
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
timestamp: timestamp2,
hash: messageHash2
},
{
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
timestamp: timestamp3,
hash: messageHash3
},
])
```
!!! Info "See also"
- [How do you delete messages in Session?](./principles/messages.md#how-do-you-delete-messages-in-session)
## Events about deleted messages
See [events page](./events.md#messagedeleted)

View file

@ -1,50 +0,0 @@
# Error handling
Session.js validates and handles a lot of errors for you, wrapping them in special different classes, so you can easily handle them on your abstract level.
However, you absolutely should always handle errors when calling any method in Session.js. At the very least, to not crash your entire production server with unhandled thrown error.
To handle errors correctly, install [@session.js/errors](https://www.npmjs.com/package/@session.js/errors):
```
bun add @session.js/errors
```
All errors extend from SessionJsError class, which itself extends from Error class.
Example of handling errors:
```ts
import { Session, ready } from '@session.js/client'
import {
SessionValidationError,
SessionValidationErrorCode,
SessionJsError
} from '@session.js/errors'
await ready
const session = new Session()
try {
session.setMnemonic('invalid mnemonic') // <- throws SessionValidationError, which extends from generic Error class
} catch(e) {
if(e instanceof SessionValidationError) {
if(e.code === SessionValidationErrorCode.InvalidMnemonic) {
console.error('You entered invalid mnemonic!') // <- `e` will have code property with one of SessionValidationErrorCode enums
} else {
// some other SessionValidationError error
console.error(e.code)
}
} else if(e instanceof SessionJsError) {
// another error not related to validation, but related to Session.js
console.error(e.code)
} else if(e instanceof Error) {
// unknown error that was thrown by javascript, not Session.js
console.error(e.message)
} else {
// generally all errors in JavaScript extend from Error class, but
// it is possible to throw primitive values like `throw "primitive string"`
throw e
}
}
```

View file

@ -1,319 +0,0 @@
# Events
You can listen to a variety of events to trigger parts of your application that are responsible to react on them.
```ts
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
const onMessage = msg => { /**/ }
session.on('message', onMessage)
// alias: session.addEventListener('message', onMessage)
session.off('message', onMessage)
// alias: session.removeEventListener('message', onMessage)
```
## `message`
New message received in DM or closed group. For advanced users: this is only emitted for DataMessage i.e. VisibleMessage i.e. message that was sent by user to the chat. This does not include service messages and other events sent by Session clients. Look at this like on a message bubble.
```ts
type PrivateMessage = {
type: 'private'
}
type ClosedGroupMessage = {
type: 'group'
groupId: string
}
type Message = (PrivateMessage | ClosedGroupMessage) & {
id: string
from: string
text?: string
attachments: MessageAttachment[]
replyToMessage?: {
timestamp: number
author: string
text?: string
attachments?: QuotedAttachment[]
}
timestamp: number
getEnvelope: () => EnvelopePlus
getContent: () => SignalService.Content
getReplyToMessage: () => Message['replyToMessage']
}
session.on('message', (message: Message) => {
console.log(
'From:', msg.from,
'Is from closed group:', msg.type === 'group',
'Group id:', msg.type === 'group' ? msg.groupId : 'Not group',
'Text:', msg.text ?? 'No text',
)
})
```
To reply to this message, you can use getReplyToMessage() method:
```ts
session.sendMessage({
to: message.from,
text: 'reply!',
replyToMessage: message.getReplyToMessage()
})
```
## `syncMessage`
This event is intended to let your instance know that the message was sent from your Session ID to another Session ID. This is useful when a person uses many devices and this event lets your client know that they sent message from another device.
**This event will be triggered on the instance that used sendMessage**
```ts
export type SyncMessage = Omit<Message, 'from'> & { to: string }
// interface is the same as above, but instead of `from` field we have `to`
// which indicates Session ID that the user sent message to
session.on('syncMessage', (message: SyncMessage) => {
console.log(
'To:', msg.to,
'Is to closed group:', msg.type === 'group',
'Group id:', msg.type === 'group' ? msg.groupId : 'Not group',
'Text:', msg.text ?? 'No text',
)
})
```
## `syncDisplayName`
**This event will be triggered on the instance that used [setDisplayName](./profile.md#display-name)**
One of instances changed this Session ID assosiated profile display name.
```ts
session.on('syncDisplayName', newDisplayName => {
console.log('My new display name is', newDisplayName)
})
```
## `syncAvatar`
**This event will be triggered on the instance that used [setAvatar](./profile.md#avatar)**
One of instances changed this Session ID assosiated profile display name.
```ts
session.on('syncDisplayName', newAvatar => {
const newAvatarFile = await session.getFile(newAvatar) // => File
console.log('My new avatar is', newAvatarFile)
})
```
## `messageDeleted`
**This event will be triggered on the instance that used [deleteMessage](./deleting-messages.md)**
Message has been deleted.
```ts
type MessageDeleted = {
/** Timestamp of deleted message sent in that message constructor. Lookup message by timestamp in saved messages */
timestamp: number,
/** Sender of message that deleted it */
from: string
}
session.on('messageDeleted', (messageDeleted: MessageDeleted) => {
console.log(
'Message with timestamp', messageDeleted.timestamp,
'sent by', messageDeleted.from,
'was deleted'
)
})
```
## `messageRead`
Message has been read.
```ts
type MessageReadEvent = {
/** Timestamp of read message sent in this message constructor. Lookup message by timestamp among locally saved messages */
timestamp: number,
/** Session ID of conversation where message was read */
conversation: string
}
session.on('messageRead', (messageRead: MessageReadEvent) => {
console.log(
'Message with timestamp', messageRead.timestamp,
'was read in conversation', messageRead.conversation
)
})
```
## `messageTypingIndicator`
Typing indicator appeared or disappeared.
```ts
type MessageTypingIndicator = {
/** If true, you should countdown from 20 and then treat it like recipient stopped typing */
isTyping: boolean
/** Session ID of conversation where typing indicator appeared or disappeared */
conversation: string
}
session.on('messageTypingIndicator', (typingIndicator: MessageTypingIndicator) => {
console.log(
'Typing indicator', typingIndicator.isTyping ? 'appeared' : 'disappeared',
'in conversation', typingIndicator.conversation
)
})
```
## `screenshotTaken`
**This event will be triggered on the instance that used [notifyScreenshotTaken](./screenshot-taken-notification.md)**
"Screenshot taken" message was sent in conversation.
```ts
type ScreenshotTakenNotification = {
/** Timestamp when screenshot was taken */
timestamp: number
/** Session ID of conversation where notification appeared */
conversation: string
}
session.on('screenshotTaken', (notification: ScreenshotTakenNotification) => {
console.log(
'"Screenshot taken" notification appeared at', notification.timestamp,
'in conversation', notification.conversation
)
})
```
## `mediaSaved`
**This event will be triggered on the instance that used [notifyMediaSaved](./media-saved-notification.md)**
"Attachment downloaded" message was sent in conversation.
```ts
type MediaSavedNotification = {
/** Message's timestamp which has attachment that was downloaded */
timestamp: number,
/** Session ID of conversation where notification appeared */
conversation: string
}
session.on('mediaSaved', (notification: MediaSavedNotification) => {
console.log(
'"Attachment downloaded" notification appeared about',
'downloading attachment in message with timestamp',
notification.timestamp,
'in conversation', notification.conversation
)
})
```
## `messageRequestApproved`
"Conversation request accepted" message was sent in conversation.
```ts
type Profile = {
/** Name, displayed instead of your Session ID. Acts like nickname. All unicode characters are accepted except for `ᅭ` (0xffd2) which is reserved by Session for mentions. Max length: 64 characters */
displayName: string
/** Image, displayed near display name in Session clients. Acts like profile picture. */
avatar?: {
/** URL to avatar, uploaded to Session file server */
url: string
/** 32 bytes key used for avatar encryption */
key: Uint8Array
}
}
type MessageRequestResponse = {
profile: Profile,
conversation: string
}
session.on('messageRequestApproved', (message: MessageRequestResponse) => {
console.log(
'Your conversation request was accepted by',
message.conversation,
message.profile.displayName
)
})
```
## `call`
Call message was sent in conversation. Calls are not supported by Session.js yet.
```ts
type Call = {
uuid: string
type: SignalService.CallMessage.Type
from: string
}
session.on('call', (call: Call) => {
console.log(
'You have received call-related message',
call.from,
call.type
)
})
```
## `reactionAdded`
**This event will be triggered on the instance that used [addReaction](./reactions.md)**
Reaction was added on a message.
```ts
type ReactionMessage = {
messageTimestamp: number
messageAuthor: string
reactionFrom: string
/** Emoji as string. Any unicode character(s) may be in this field, length is practically unlimited, validation is not performed by the @session.js/client library. You should probably only display the reaction, if it's a single valid emoji */
emoji: string
}
session.on('reactionAdded', (reaction: ReactionMessage) => {
console.log(
'New reaction added on message with timestamp',
reaction.messageTimestamp,
'sent by', reaction.messageAuthor,
'—', reaction.reactionFrom,
'reacted with', reaction.emoji
)
})
```
## `reactionRemoved`
**This event will be triggered on the instance that used [removeReaction](./reactions.md)**
Reaction was added on a message.
```ts
type ReactionMessage = {
messageTimestamp: number
messageAuthor: string
reactionFrom: string
/** Emoji as string. Any unicode character(s) may be in this field, length is practically unlimited, validation is not performed by the @session.js/client library. You should probably only display the reaction, if it's a single valid emoji */
emoji: string
}
session.on('reactionRemoved', (reaction: ReactionMessage) => {
console.log(
'Reaction removed from message with timestamp',
reaction.messageTimestamp,
'sent by', reaction.messageAuthor,
'—', reaction.reactionFrom,
'reaction was', reaction.emoji
)
})
```

View file

@ -1,114 +0,0 @@
# Files and attachments
This article explains how to send and download attachments with Session.js
!!! Info "See also"
- [How files work in Session?](./principles/files.md)
## Sending
Attachments are passed as [File](https://developer.mozilla.org/en-US/docs/Web/API/File) interface, available both in browser and Bun. You must specify file name and content type in constructor.
You're fully responsible for validation of files content, type, name and file size. Keep in mind that Sesison file server will throw error if you're trying to upload files more than 10 MB.
### Sending local file as attachment
This only works in server environment, because browsers won't let you access user file system, at least not as simple to be shown in this guide.
```ts
import path from 'path'
import { Session, ready } from '@session.js/client'
await ready
const filename = '/Users/kitty/Desktop/image.jpg'
const buffer = await fs.readFile(filename)
const file = new File([buffer], path.basename(filename), { type: 'image/jpeg' })
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Image from file',
attachments: [file]
})
```
### Sending file downloaded from URL
This will most likely work both in browser and server environments, unless domain that you're fetching has no [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) allowing your host to fetch the resourse.
```ts
import { Session, ready } from '@session.js/client'
await ready
const imageData = await fetch('https://picsum.photos/100/100').then(res => res.arrayBuffer())
const file = new File([imageData], 'image.jpeg', { type: 'image/jpeg' })
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Image from URL',
attachments: [file]
})
```
### Sending file selected on the web page
This will only work in browser environment, because server has no [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) interfaces, such as `window` or `document`.
```ts
import { Session, ready } from '@session.js/client'
await ready
// This will try to find <input type="file"></input> on page and read selected files from it
const file = document.querySelector('input[type=file]').files[0]
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Image from browser',
attachments: [file]
})
```
## Voice messages
Voice messages are a special kind of attachments. They are usually sent as mp3 files with special flag set in message constructor. Session.js allows you to pass voice message to message in a special field:
```ts
import { Session, ready } from '@session.js/client'
await ready
const filename = '/Users/kitty/Desktop/voice-message.mp3'
const buffer = await fs.readFile(filename)
const file = new File([buffer], path.basename(filename), { type: 'audio/mpeg' })
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
voiceMessage: file
})
```
## Receiving
When you receive file in message, it will have url pointer and key to decrypt. Session.js provides a useful utility getFile which downloads that file from url pointer using provided network, decrypts and validates, returning you a [File](https://developer.mozilla.org/en-US/docs/Web/API/File) with name and content type.
```ts
session.on('message', message => {
message.attachments.forEach(attachment => {
const file = await session.getFile(attachment)
console.log('Attachment name', file.name)
console.log('Attachment size', file.size)
console.log('Attachment type', file.type)
})
})
```

View file

@ -1,116 +0,0 @@
# Getting started
Friendly reminder: this package can't be used and won't work with Node.js.
## Installation
By using this software, you are agreeing to abide by [Terms of use](https://git.hloth.dev/session.js/client/blob/main/TERMS.md). Shortly: no abuse and spam, you're solely responsible for your actions with this software.
1. First install bun: https://bun.sh/
2. Create a new Bun project in any directory, using `bun init` or manually
3. Install session.js: `bun add @session.js/client`
Make sure to await for initialization of library before calling any methods:
```ts
import { ready } from '@session.js/client'
await ready
// ...
```
## Quick start
### Sending messages
```ts
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const recipient = '054830367d369d94605247999a375dbd0a0f65fdec5de1535612bcb6d4de452c69'
const session = new Session()
session.setMnemonic(mnemonic, 'My username')
const response = await session.sendMessage({
to: recipient,
text: 'Hello world'
})
console.log('Sent message with id', response.messageHash)
```
!!! Info "See also"
- [How to use instance with random mnemonic?](./mnemonic.md#generate-random-mnemonic)
### Sending images or files
Attach image from URL to your message:
```ts
const imageData = await fetch('https://picsum.photos/100/100').then(res => res.arrayBuffer())
const file = new File([imageData], 'image.jpg', { type: 'image/jpeg' })
await session.sendMessage({
to: recipient,
text: 'Image downloaded by URL:',
attachments: [file]
})
```
Attach file from your file system to your message:
```ts
import path from 'path'
// <...>
const filename = '/Users/kitty/Desktop/image.jpg'
const buffer = await fs.readFile(filename)
const file = new File([buffer], path.basename(filename), { type: 'image/jpeg' })
await session.sendMessage({
to: recipient,
text: 'Image from file:',
attachments: [file]
})
```
### Polling messages
Check [polling page](./polling.md) for more info and examples on polling.
```ts
import { Session, Poller, ready } from '@session.js/client'
import { SnodeNamespaces, type Message } from '@session.js/types'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const session = new Session()
session.setMnemonic(mnemonic, 'Display name')
const poller = new Poller() // polls every 3 seconds
session.addPoller(poller)
session.on('message', (msg: Message) => {
console.log('Received new message!',
'From:', msg.from,
'Is from closed group:', msg.type === 'group',
'Group id:', msg.type === 'group' ? msg.groupId : 'Not group',
'Text:', msg.text ?? 'No text',
)
// If you want to access more properties and experiment with them, use getEnvelope and getContent
msg.getContent() // => SignalService.Content <- useful message payload
msg.getCnvelope() // => EnvelopePlus <- message metadata
// If you want to download attachments, use:
msg.attachments.forEach(async attachment => console.log(await session.getFile(attachment)))
})
```
## Examples
You can find fully complete examples in [examples repository](https://git.hloth.dev/session.js/examples/)
- [Simple example](https://git.hloth.dev/session.js/examples/tree/main/simple)
- [Browser](https://git.hloth.dev/session.js/examples/tree/main/browser-simple)

View file

@ -1,66 +0,0 @@
Session.js is JavaScript library for programmatic usage of [Session messenger by OXEN](https://getsession.org). Supports server and browser environment with built-in proxy network module. Shipped with TypeScript definitions. Tested with bun:test. It's aimed for [Bun](https://bun.sh) users — a modern runtime for JavaScript and alternative to Node.js. But it can also be used on most platforms and runtimes thanks to external modules system and platform-agnostic architecture with vanilla [noble](https://paulmillr.com/noble/) cryptography instead of WASM-compiled libsodium and bytebuffer.
Session.js allows you to create:
- Highly optimized Session bots (hundreds of bots in a single app)
- Custom Session clients (web-based and native with JS backend)
- Automation tools for Session
## Features
- On-demand polling — you decide when to get new messages and whether instance should poll them (and poll settings like frequency) or work just for sending
- Per-instance storage and network settings — you can attach persistant storage to instance or use in-memory storage for throwaway one-time instances
- Session.js can be used in browser, keeping private keys on client-side and doing network requests on server-side. See this in action with [my full-featured Session Web client](https://git.hloth.dev/hloth/session-web)!
## Getting started
Jump to [getting started](./getting-started.md) page to start using Session.js!
## Roadmap
- [X] Messages
- [X] Automatic snodes fetching
- [X] Automatic swarms selection
- [ ] Manual snode/swarm control
- [X] Data retrieving from swarms
- [X] Messages polling
- [X] Messages types
- [X] Regular chat message
- [X] Text
- [X] Attachments
- [X] Images
- [X] Files
- [X] Voice messages
- [X] Quotes
- [ ] Web links previews
- [X] Service messages
- [X] Sync message
- [X] Configuration message
- Uses legacy constructor for now
- [X] Read message (ReadReceipt)
- [X] Typing message
- [X] Message request response
- [X] Screenshot / media saved (DataExtraction)
- [X] Delete message (Unsend)
- [X] Call message
- Just event to display placeholder warning about unsupported feature
- [X] Reactions
- [ ] Closed chats
- [ ] Open groups (SOGS)
- [ ] Expirable messages
- [ ] Calls
- [ ] Messages editing (SOGS)
- [X] Profile editing
- [X] Display name
- [X] Avatar
- [X] Syncing between devices
- [X] ONS resolving
</details>
## License
All code in Session.js (including any submodules) was written by Viktor Shchelochkov aka hloth and licensed under [MIT license](https://git.hloth.dev/session.js/client/blob/main/LICENSE.md)
## Funding
You can donate here: [hloth.dev/donate](https://hloth.dev/donate)

View file

@ -1,35 +0,0 @@
# Mark message as read
Session.js allows you to mark message as read in 1-1 conversations. You should only call this method if user explicitly agreed to share read indicators with recipient(s).
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
session.on('message', message => {
session.markMessagesAsRead({
from: message.from,
messagesTimestamps: [message.timestamp],
readAt: Date.now() // optional
})
})
```
You can mark multiple messages as read at once
```ts
session.on('message', message => {
session.markMessagesAsRead({
from: message.from,
messagesTimestamps: [message1.timestamp, message2.timestamp, message3.timestamp],
// we haven't provided readAt, so it will fallback to current time
})
})
```
## Events about read messages
See [events page](./events.md#messageread)

View file

@ -1,31 +0,0 @@
# Media saved notification
Session allows you to send "media saved" notification. Clients send this message upon user interaction.
!!! Info "See also"
- [What happens when you click to "download media" button in Session?](./principles/files.md#what-happens-when-you-click-to-download-media-button-in-session)
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
let messageTimestamp: number
session.on('message', message => {
messageTimestamp = message.timestamp
})
// ... Some time later ...
await session.notifyMediaSaved({
conversation: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
savedMessageTimestamp: messageTimestamp
})
```
## Events about taken notifications
See [events page](./events.md#screenshottaken)

View file

@ -1,53 +0,0 @@
# Mnemonic encoding & decoding
Use [@session.js/mnemonic](https://www.npmjs.com/package/@session.js/mnemonic) for operations related to mnemonic.
```
bun add @session.js/mnemonic
```
```ts
import { encode, decode } from '@session.js/mnemonic'
const seed = decode('love love love love love love love love love love love love')
console.log('Account seed', seed)
const mnemonic = encode(seed)
console.log('Encoded mnemonic', mnemonic) // => love love love love love love love love love love love love
```
## Generate random mnemonic
To create a new Session instance with random mnemonic, you have to use two packages: @session.js/mnemonic and @session.js/keypair
```
bun add @session.js/mnemonic @session.js/keypair
```
Now generate random seed and encode it to get random mnemonic
```ts
import { generateSeedHex } from '@session.js/keypair'
import { encode } from '@session.js/mnemonic'
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = encode(generateSeedHex())
console.log('Mnemonic', mnemonic)
const session = new Session()
session.setMnemonic(mnemonic)
```
### Add your own mnemonic language
You generally really shouldn't do that, because you have to find a secure compatible words dictionary first that will work with the system. This is how you add language to mnemonic encoder/decoder:
```ts
import { decode, mnemonicLanguages, addMnemonicLanguage } from '@session.js/mnemonic'
mnemonicLanguages.russian = addMnemonicLanguage({
prefixLen: 3,
words: [/* ... */]
})
decode('любовь любовь любовь любовь любовь любовь любовь любовь любовь любовь любовь любовь любовь', 'russian')
```

View file

@ -1,17 +0,0 @@
# Bun local network
Default network that uses Bun's capabilities to fetch Session servers. It is intended to be used in the same process in the same environment as @session.js/client.
If you're looking for network that works on proxy server (to host instance part on client side and do requests to Session servers via server side), use [bun remote network](./bun-remote.md). One such case is browser Session client, because browsers do not support connecting to Session servers.
## Use with Session.js
Simply **do not provide any network to `network` option in Session class constructor** and this will be the default. You can optionally provide it as:
```ts
import { Session, ready } from '@session.js/client'
import { BunNetwork } from '@session.js/bun-network'
await ready
new Session({ network: new BunNetwork() })
```

View file

@ -1,50 +0,0 @@
# Bun remote network
This module wraps bun local network but exports two files: for browser enviornment and server environment. Don't worry, modern bundlers such as webpack, rollup and bun should automatically pick up right parts of code for each environment.
If you just want to run everything on one machine (both session instance and making requests to Session network), use [bun local network](./bun-local.md)
## Use with Session.js
Start by installing `@session.js/bun-network-remote` both on client-side and server-side. The package itself only does validation and connects client-side and server-side and all network management is bundled in another dependency `@session.js/bun-network` just like in [local connector](./bun-local.md).
Install it both in browser project and server proxy project:
```
bun add @session.js/bun-network-remote
```
### Client-side (where Session client runs)
```ts
import { Session, ready } from '@session.js/client'
import { BunNetworkRemoteClient } from '@session.js/bun-network-remote'
await ready
new Session({
network: new BunNetworkRemoteClient({
proxy: 'https://my-proxy.example.org:12345/'
// this endpoint must be accessible in your environment
// i.e. if you're building Session client in browser, make sure
// that my-proxy.example.org has a valid SSL certificate, CORS and SSL settings
})
})
```
Client-side part will send POST requests to this URL with JSON body.
### Server-side (proxy server)
```ts
// Runtime must be Bun.sh
// Web server can be anything: Express, Fastify, Elysia, Bun's web server, etc...
// Validation is done internally and throws @session.js/error RuntimeValidation errors
import { Elysia } from 'elysia'
import { BunNetworkRemoteServer } from '@session.js/bun-network-remote'
const network = new BunNetworkRemoteServer()
new Elysia()
.post('/', ({ body }) => network.onRequest(body))
.listen(12345)
```

View file

@ -1,67 +0,0 @@
# Network
You can pick existing network connector or [write your own](#creating-new-network-connector)
## Overview
<table>
<tr>
<td> Network type </td> <td> Supports onion routing </td> <td> Description </td>
</tr>
<tr>
<td><a href="./bun-local">Bun (local)</a></td>
<td>❌</td>
<td> This network type is default and simpliest. It is intended to be used in the same process that @session.js/client instances run in. It's ideal if you just want to start and doing everything on server in one project without browser or other parts. </td>
</tr>
<tr>
<td><a href="./bun-remote">Bun (remote) for proxies</a></td>
<td>❌</td>
<td> This network might be useful if you're building client in environment that does not allow you sending requests to Session nodes with self-signed certificates. This option is ideal for browser clients, because it handles all network connection on backend proxy that forwards client-side encrypted data to snodes. Check out simple <a href="https://git.hloth.dev/session.js/examples">browser example here</a>. </td>
</tr>
</table>
## Creating new network connector
To implement your own network, write class that implements Network interface from `@session.js/types/network` with onRequest method. It must cover all RequestTypes from `@session.js/types/network/request`. Take a look at this example:
```ts
import type { Network } from '@session.js/types'
import {
RequestType,
type RequestGetSwarmsBody,
type RequestPollBody,
type RequestStoreBody,
type RequestUploadAttachment
} from '@session.js/types/network/request'
export class MyNetwork implements Network {
onRequest(type: RequestType, body: object): Promise<object> {
switch(type) {
case RequestType.Store:
return // typeof ResponseStore
case RequestType.GetSnodes:
return // typeof ResponseGetSnodes
case RequestType.GetSwarms:
return // typeof ResponseGetSwarms
case RequestType.Poll:
return // typeof ResponsePoll
case RequestType.UploadAttachment:
return // typeof ResponseUploadAttachment
case RequestType.DownloadAttachment:
return // typeof ArrayBuffer
default:
throw new Error('Invalid request type')
}
}
}
```
This is just an example in documentation, always develop against actual up-to-date RequestTypes enum in types package.

View file

@ -1,17 +0,0 @@
# Oxen Name System (ONS)
ONS is a system of usernames that links you to registered Session ID mapping and allows you to buy mapping for a few other lokinet products. For more info on ONS, go to [What is ONS?](./principles/users.md#what-is-ons)
## ONS resolving
Use [@session.js/ons](https://www.npmjs.com/package/@session.js/ons). This is a utility module that does not depend on any other packages published in @session scope.
```
bun add @session.js/ons
```
```ts
import { resolve } from '@session.js/mnemonic'
await resolve('hloth') // => 057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b
```

View file

@ -1,91 +0,0 @@
# Polling
Session.js allows you to poll messages on-demand and polling is opt-in, meaning you have to enable it in order to start receiving updates and new messages.
## Quick start
By default, if you don't provide `interval` in options to Poller class constructor, it will poll new messages each 2.5 seconds.
```ts
import { Session, Poller, ready } from '@session.js/client'
import { SnodeNamespaces, type Message } from '@session.js/types'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const session = new Session()
session.setMnemonic(mnemonic, 'Display name')
const poller = new Poller() // polls every 2.5 seconds
session.addPoller(poller)
session.on('message', (msg: Message) => {
console.log('Received new message!',
'From:', msg.from,
'Is from closed group:', msg.type === 'group',
'Group id:', msg.type === 'group' ? msg.groupId : 'Not group',
'Text:', msg.text ?? 'No text',
)
// If you want to access more properties and experiment with them, use getEnvelope and getContent
msg.getContent() // => SignalService.Content <- useful message payload
msg.getCnvelope() // => EnvelopePlus <- message metadata
// If you want to download attachments, use:
msg.attachments.forEach(async attachment => console.log(await session.getFile(attachment)))
})
```
You can even attach multiple pollers to instance, for example, to configure interval of polling different namespaces:
```ts
// Poll DMs each 5 seconds
const dmMessagesPoller = new Poller({ interval: 5000, namespaces: new Set([SnodeNamespaces.UserMessages]) })
// Poll user profile each 60 seconds
const profilePoller = new Poller({ interval: 60000, namespaces: new Set([SnodeNamespaces.UserProfile]) })
session.addPoller(dmMessagesPoller)
session.addPoller(profilePoller)
session.on('message', () => { /*...*/ })
session.on('syncDisplayName', (displayName) => {
console.log('Synced display name', displayName)
})
```
## Controlled polling on demand
To disable default interval of 2500 ms, pass `interval: null` to Poller constructor
```ts
const poller = new Poller({ interval: null })
session.addPoller(poller)
// ... Some time later ...
const messages = await poller.poll()
console.log('Received messages', messages)
```
## Enabling/disabling polling
You can use methods `startPolling`, `stopPolling` and `setInterval` on Poller instance to control it after it's alreay added to instance.
```ts
const poller = new Poller({ interval: 5000 })
session.addPoller(poller)
// ... Some time later ...
poller.stopPolling()
// ... Some time later ...
poller.setInterval(2500) // poll every 2.5 seconds
poller.startPolling()
// ... Some time later ...
poller.setInterval(null) // manual polling
poller.poll()
```

View file

@ -1,15 +0,0 @@
# Files in Session
This article explains how attachments and files work in Session messenger.
## How to send an attachment with message in Session?
Session limits size of your attachments to 10 MB and uses special file server hosted by Oxen foundation that is used by all clients to upload and download encrypted files. Attachments always should have digest, key and size values that are checked by Session clients upon receiving and decrypting file. Files can have content-type, width, height, name, caption optional fields that Session clients will use to display information about file.
[@session.js/client](https://www.npmjs.com/package/@session.js/client) will handle that encryption logic for you, wrapping it to just attaching File interface to sendMessage method's options and getFile method.
## What happens when you click to "download media" button in Session?
Though there is no practical and respectful to user's privacy way for Session file server to know when you download media from conversation, your Session client will send "Media saved by you" message in conversation letting your recipient know you've downloaded attachment from their message. This is done locally upon interaction with download button.
[@session.js/client](https://www.npmjs.com/package/@session.js/client) allows you to download attachments without sending this message and, if you're building your own client, send these kind of messages to conversation with simple methods.

View file

@ -1,54 +0,0 @@
# Messages in Session
This article explains core principles behind Session's messages.
## How does messaging works in Session with its decentralization?
Just like PGP emails back in the day, Session and similar messengers use end-to-end encryption. Session uses your private key (decoded from mnemonic) to encrypt data of your message to base64 string which is sent to swarms. That way, swarms hosted by other people in network never receive your private key.
Swarm is a storage server for messages that is specifically designed to store encrypted messages. They are tied to pools of Session IDs, so your inbox might be on one swarm, while your recipient might be on another swarm. There are obviously many swarms available for a specific Session ID, you should choose random one to provide security. Swarms sync messages between each other, so you shouldn't store your message to all of them, just pick one of available. So before sending a message you must find a swarm that serves the specified Session ID.
To find swarm that serves for a specific Session ID, you should use a dedicated method `get_swarm` in request to Session Service Node, which returns list of available swarms. But even before that, you should get a list of service nodes that work right now and can return you a list of available swarms for specified Session ID. To get list of service nodes in Session network, you must pick one of Seed Nodes which is official Oxen foundation servers that serve as directory list of servers in decentralized network.
There are three seed nodes hosted by Oxen foundation (developers of Session):
- seed1.getsession.org
- seed2.getsession.org
- seed3.getsession.org
You can pick any of them to request service nodes list and preferrably add mechanism that switches from seed1 to seed2 etc when one is unavailable.
All requests to swarms, service nodes, and seed nodes are made using JSON RPC format. All of them have their own self-signed certificate. For seed nodes, you should implement "certificate pinning", i.e. hardcode seeds servers certificates data directly in your code for maximum security. For service nodes and swarms, you will receive their certificates data in list requests.
[@session.js/client](https://git.hloth.dev/session.js/client) handles all that logic for you. You can simply pass Session ID and message and it will send the message for you. Additionally, there is getSwarm method that does everything described above but returns swarm's ip address and port for your custom logic.
## How does storing messages on Swarms work?
As said previously, you have to find swarm for specific Session ID. Do not mistake it with your own swarm: when you want to send message to recipient, you should find and use recipient's swarm. Since Session is built on top of Signal protocol, it uses Signal's protobuf schema and Signal's messages classes to serialize message data and encrypt it locally using private key. Then it uses `store` method to save message in swarm storage.
[@session.js/client](https://git.hloth.dev/session.js/client) allows you to create any number of instances in single JavaScript file that can send as many messages as you want with a simple yet flexible API.
## How does messages polling work?
Similar to messages storing, to poll messages Session client would first find working service node using seed nodes, then ask for swarm for that specific Session ID (pubkey) and make frequent JSON RPC requests with `retrieve` method to get messages. To keep track of new messages, you'll typically use last hashes parameter. While messages in Session do have a unique identifier that is unique across all clients — hash, it looks like it either had been added too late or borrowed from Signal, because many interactions that refer to specific message (such as reply to previously sent message, messages deletion etc) use timestamp instead of hash. You'll mostly use messages hashes only for polling-related logic.
[@session.js/client](https://git.hloth.dev/session.js/client) wraps polling into a simple interface, at the same time allowing you to customize polling as you want with all encryption and low-level logic encapsulated and processed by the library.
## How do you delete messages in Session?
Since Session clients mostly strive to keep everything local, Session has come up with a smart decision to create "unsend" messages which are [control messages](#control-messages) that instruct Session clients to remove specific message from local database and stop showing it to that client's user. Session clients usually also send request with `delete` method to swarms to delete the message in their storage, in case recipient hasn't polled the message yet.
## How long do messages are stored in Session?
Swarms usually keep messages for 14 days, but some messages can be sent with expiring config.
## Control messages
All events in Session are called Messages, specifically they are sent in VisibleMessage class which, when deserialized, has one of these properties:
- DataMessage — chat bubble message. Reaction added/removed events are also sent as DataMessage, with reaction property and empty string body.
- DataMessage with syncTarget set (sent to your own swarm) — used by Session clients to sync between logged devices, basically tells that we have sent message to someone specified in syncTarget field
- UnsendMessage — delete message
- SharedConfigMessage — syncs profile including display name and avatar with all clients. Earlier, Session clients used ConfigurationMessage but now they'll display that one of your devices runs legacy outdated version if they receive ConfigurationMessage. Parameters are generated using libsession-util library written in c/c++
- ReadReceiptMessage — recipient seen your message
- TypingIndicatorMessage — recipient has started or stopped typing
- ConversationRequestMessage — response to yours (or someone else's) conversation request
- DataExtractionMessage — recipient saved attachment in your conversation or took screenshot

View file

@ -1,52 +0,0 @@
# Users in Session
This article explains core principles behind Session's accounts.
## How accounts in Session messenger work?
In Session, there are no "accounts" in terms of persistant entities. Instead, there are inboxes where you receive your messages and can assosiate display name, avatar and ONS (link to Session ID) with. Technically, no one including you own your inbox. You can manage your inbox when you have access to it, and you have access when you have mnemonic (which is essentially a private key that is used to decrypt messages in that inbox).
## What is Session ID?
Session ID is your inbox address which is [x25519 32 bytes public key aka Curve25519](https://en.wikipedia.org/wiki/Curve25519). It is always prepended with `05`, which makes it 66 characters long (32 bytes -> 64 characters + `05` prefix).
Using @session.js/mnemonic and @session.js/keypair you can quickly generate random seeds, convert them to keypairs used by Session, get x25519 public key from it and encode to mnemonic that can be used in Session client.
```ts
import { generateSeedHex, getKeysFromSeed } from '@session.js/keypair'
import { encode } from '@session.js/mnemonic'
const seedHex = generateSeedHex() // generate random 16 bytes seed that should be kept secure
const keys = getKeysFromSeed(seedHex) // derive public and private x25519 and ed25519 keys
const sessionId = keys.x25519.publicKey // Session ID is x25519 public key
const mnemonic = encode(seedHex) // mnemonic is 13 words for accessing your Session
```
## How to register in Session?
Since there are no accounts, you can't register. Instead, your device generates a random private key (which can be displayed as encoded mnemonic), which is then converted to public key (which can be displayed as hex which is your Session ID). Public key allow another person to encrypt message, private key allows you to decrypt message. Obviously, you share public key (Session ID) so that other people can write you messages and never share private key (so that no one can read your messages except you).
[@session.js/client](https://git.hloth.dev/session.js/client) handles all encryption logic for you.
## How to delete account in Session?
Since there are no accounts, you can't delete it. Moreover, as stated above, you can't even own it. You just hope that theoretically no one will ever guess your private key (or mnemonic) to read your messages and write messages from your inbox.
However, you can delete all data that is assosiated with your inbox. Read [how messages work in Session](./messages.md)
## What is ONS?
As said above, a person must have your public key (Session ID) to send you a message. Session IDs are hard to remember, as they're always 66 characters long and consist only of hex characters (a-f, 0-9). There is [Session Vanity ID generator](https://session-id.pages.dev/) which can get you somewhere about first 5 desired characters, but the rest 61 characters are still random. As you might have guessed, this generator just iterates over random private keys and derives public keys (Session ID) until a match is found, and, if we were able to generate all 66 characters, that would mean we can compromise any known Session ID's private key.
Usernames are a popular way to access each other's chats without remembering whole address. They are unique and simply act as a link to full address. Session has its own usernames system called Oxen Name System (ONS) which allows you to buy a mapping to your Session ID (plus a few other integrated lokinet projects) for 7 OXEN which at time of writing this article is about 1$. Payments are processed inside of Oxen blockchain, which makes it secure. ONS deserves whole another article, so for now just keep in mind that you can buy username in Session which simply acts like a link to your Session ID.
[@session.js/ons](https://git.hloth.dev/session.js/ons) handles resolving ONS->Session ID encryption logic for you, so you just have to provide ONS and you'll receive Session ID.
Alternatively, there is [https://ons.sessionbots.directory/](https://ons.sessionbots.directory/) which is a registry of ONS names with local client-side quick search among all registered ONS names in Session network.
## How Session profiles work?
As previously discussed, there are no accounts in Session, so you can't get profile by account ID like in Telegram or any other centralized messenger or social media. Moreover, for privacy, Session clients shouldn't show profile display name and avatar unless user accepts conversation request or explicitly agrees to share profile with recipient. Instead of fetching it everytime, profiles in Session are saved locally in database for contacts.
Profile data comes with each visible chat message and with conversation request accepted message. So each time Session client sends a message to another user or accepts a request to talk, this message also contains your display name and avatar — that's how they're updated in local databases of other clients.
To be clear: **there is no way to get avatar or display name of specific Session ID unless they send that data inside of encrypted chat message bubble.** Until Session client received display name and avatar in either of these messages, it should display just Session ID.

View file

@ -1,42 +0,0 @@
# Profile customization
Session allows you to set display name and avatar for your Session ID. This article explains how to customize your profile using Session.js
!!! Info "See also"
- [How Session profiles work?](./principles/users.md#how-session-profiles-work)
!!! warning
Session.js currently does not support syncing profile between devices, you will likely run into problems if you try to use up-to-date official Session clients and Session.js at the same time. This is because they've switched from ConfigurationMessage to SharedDataConfig message which is generated in libsession-util code which is written in C/C++. Help is needed to resolve this issue, from someone who knows both C and JS
## Display name
Initially you can set display name in setMnemonic method which takes display name as optional second argument.
```ts
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const displayName = 'My Session bot'
const session = new Session()
session.setMnemonic(mnemonic, displayName)
```
or you can change it later:
```ts
await session.setDisplayName('My new Session bot name')
```
## Avatar
Just like regular attachments, avatars size is limited to 10 mb. It is recommended to use widely-supported image formats, such as JPEG and PNG to avoid compatability issues with other clients. Session.js does not perform any validation.
```ts
const filename = '/Users/kitty/Desktop/avatar.jpeg'
const avatar = await Bun.file(filename).bytes()
await session.setAvatar(avatar)
```

View file

@ -1,32 +0,0 @@
# Reactions
Session allows you to react on a message with any existing emoji. Technically, you can react with any number of unicode characters, but some clients will not display a reaction if it's not a single valid emoji.
## Add reaction
```ts
import { Session, ready } from '@session.js/client'
await ready
session.on('message', message => {
session.addReaction({
messageTimestamp: message.timestamp,
messageAuthor: message.from,
emoji: '👽'
})
})
```
## Remove reaction
```ts
session.removeReaction({
messageTimestamp: message.timestamp,
messageAuthor: message.from,
emoji: '👽'
})
```
## Events about added/removed reaction
See [events page](./events.md#reactionadded)

View file

@ -1,19 +0,0 @@
# Screenshot taken notification
Session allows you to send "screenshot taken" notification. Usually clients will use platform's capabilities to track when screenshot was taken and call this method. On some platforms this is impossible.
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
await session.notifyScreenshotTaken({
conversation: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b'
})
```
## Events about taken notifications
See [events page](./events.md#screenshottaken)

View file

@ -1,102 +0,0 @@
# Sending messages
Sending messages with Session.js requires setting up [storage](./storage/index.md) and [network](./network/index.md). This article explains how to send messages in Session programmatically, including examples of sending attachments and quotes (replies).
## Quick start
If you're using Bun server runtime and willing to use non-persistant in-memory storage, go ahead with this simple template:
```ts
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const displayName = 'My Session bot'
const session = new Session()
session.setMnemonic(mnemonic, displayName)
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Hello, world!'
})
```
## Getting sent message
Sometimes you want to save the result of sendMessage method to use later for methods such as [deleteMessage](./deleting-messages.md).
```ts
type ReturnTypeOfSendMessage = {
messageHash: string,
syncMessageHash: string,
timestamp: number
}
const { messageHash, timestamp } = await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Hello, world!'
})
console.log('Message hash', messageHash)
// mostly used for polling
console.log('Message timestamp', timestamp)
// used for referencing to this message in other methods
```
!!! Info "See also"
- [How messages work in Session?](./principles/messages.md)
- [What is sync message?](./principles/messages.md#control-messages)
## Attachments
Please go to [files and attachments page](./files-and-attachments.md#sending)
## Quotes/replies
Session allows you to quote messages partially to respond to them. Since reply validation would be too complex to perform on each message, everyone agreed that technically you can pass anything in quoted content, though some clients still won't show quoted message unless it really exist in conversation.
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
const { timestamp } = await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Here is the first message!'
})
await session.sendMessage({
to: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b',
text: 'Here is reply!',
replyToMessage: {
timestamp: timestamp,
author: session.getSessionID(),
text: 'Here is the first message!'
}
})
```
When quoting message, you also must pass any attachments sent in that message. As you might've guessed, this becomes duplicative, so there is a special utility `getReplyToMessage()` to make our lifes a bit easier:
```ts
import { Session, ready } from '@session.js/client'
await ready
const session = new Session()
session.setMnemonic('love love love love love love love love love love love love love')
session.on('message', message => {
// Reply to any incoming chat message
await session.sendMessage({
to: message.from,
text: 'Replying to your message',
replyToMessage: message.getReplyToMessage()
})
})
```
To read more about events and `message` structure, go to [events](./events.md) page.

View file

@ -1,193 +0,0 @@
# SOGS
SOGS (Session Open Group Server) is a type of Session communication channel, a community of users (with no limit on number of participants). It's not hosted on Session nodes, in contrast to Session groups, instead it is hosted on SOGS owner's server, but it is onion routed and end-to-end encrypted. If allows flexible management of rights and can be used for public announcements channels and chats.
Looking for a way to host SOGS yourself? Check out [bunsogs](https://git.hloth.dev/hloth/bunsogs/)
## Interacting with SOGS
Use @session.js/sogs package with utilities for SOGS and @session.js/client to interact with SOGS.
### Example: Get info about room
To make request to SOGS you must initialize Session instance. This library handles authorization and encryption in connection to SOGS for you.
```
bun add @session.js/client
```
```ts
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const displayName = 'My Session bot'
const session = new Session()
session.setMnemonic(mnemonic, displayName)
// Example SOGS link: https://sogs.hloth.dev/sessionjs?public_key=8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945
const sogsUrl = 'https://sogs.hloth.dev'
const sogsRoom = 'sessionjs'
const sogsPublicKey = '8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945'
await session.sendSogsRequest({
host: sogsUrl,
serverPk: sogsPublicKey,
endpoint: '/room/' + sogsRoom,
method: 'GET',
blind: false
})
/*
->
{
active_users: 1,
active_users_cutoff: 604800,
admins: [ "15b8543369273587555a8bd935156a76bbf9752f1dac4a8d998c2d6ddc712eb921" ],
created: 1723208687.896,
description: "Channel about Session.js framework",
image_id: 3,
info_updates: 5,
message_sequence: 34,
moderators: [],
name: "Session.js announcements",
token: "sessionjs",
pinned_messages: [],
read: true,
write: false,
upload: false,
moderator: false,
admin: false,
}
*/
```
### Example: Get messages
To decrypt message, you can use `decryptSogsMessageData` method from @session.js/sogs which handles decryption for you
```
bun add @session.js/client @session.js/sogs
```
```ts
import { Session, ready } from '@session.js/client'
import { decryptSogsMessageData } from '@session.js/sogs'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const displayName = 'My Session bot'
const session = new Session()
session.setMnemonic(mnemonic, displayName)
// Example SOGS link: https://sogs.hloth.dev/sessionjs?public_key=8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945
const sogsUrl = 'https://sogs.hloth.dev'
const sogsRoom = 'sessionjs'
const sogsPublicKey = '8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945'
const messages = await session.sendSogsRequest({
host: sogsUrl,
serverPk: sogsPublicKey,
endpoint: '/room/' + sogsRoom + '/messages/recent',
method: 'GET',
blind: false
})
const latestMessage = messages[messages.length - 1]
if(!latestMessage) {
throw new Error('This room has no messages')
}
const message = decryptSogsMessageData(latestMessage.data)
console.log(message)
// -> (this is example)
/*
SignalService.Content {
dataMessage: DataMessage {
attachments: [],
preview: [],
body: "Hello!",
timestamp: Long {
low: 675798965,
high: 404,
unsigned: true
<...>
}
profile: LokiProfile {
displayName: "My Bot",
profilePicture: "",
<...>
},
<...>
}
<...>
}
*/
```
### Example: Send messages
❌ DO NOT use this to send spam ❌
🔪 SERIOUSLY 🔪🔪🔪🔪
```ts
import { Session, ready } from '@session.js/client'
import { decryptSogsMessageData } from '@session.js/sogs'
import { VisibleMessage } from '@session.js/schema'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const displayName = 'My Session bot'
const session = new Session()
session.setMnemonic(mnemonic, displayName)
// Example SOGS link: https://sogs.hloth.dev/sessionjs?public_key=8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945
const sogsUrl = 'https://sogs.hloth.dev'
const sogsRoom = 'sessionjs'
const sogsPublicKey = '8948f2d9046a40e7dbc0a4fd7c29d8a4fe97df1fa69e64f0ab6fc317afb9c945'
// Use blinding to hide your Session ID from others
// Blinding uses ID unique to each SOGS so that no one knows your Session ID
// (at least in theory, see https://git.hloth.dev/hloth/blinded-id-converter-website)
const blind = true
const msg = new VisibleMessage({
body: reply,
profile: session.getMyProfile(),
timestamp: session.getNowWithNetworkOffset(),
expirationType: null,
expireTimer: null,
identifier: crypto.randomUUID(),
attachments: [],
preview: [],
quote: undefined
})
const { data, signature } = session.encodeSogsMessage({
serverPk: sogsPublicKey,
message: msg
blind
})
const requestBody = JSON.stringify({ data, signature })
const messages = await session.sendSogsRequest({
host: sogsUrl,
serverPk: sogsPublicKey,
endpoint: '/room/' + sogsRoom + '/message',
method: 'POST',
body: requestBody
blind
})
// -> (this is example)
/*
{
id: 9,
session_id: "15f0240ef446562d2afad24a4cf24eaa1fee45655dc461de01309a5bcd5e24e943",
posted: 1735849081.0190141,
seqno: 9,
data: "ChoKBkhlbGxvITin8avFwjKqBggKBk15IEJvdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
signature: "cIk52ceTRCMcfNi71V3FsphPPf4w9/jOZSUBAnZSgsCWnJMLx+xxXaL0OY6+LXwTin6GilFw71rZG1ax6czrAQ==",
reactions: {},
}
*/
```

View file

@ -1,24 +0,0 @@
# Persistant file-based key=value storage with fs
Simple persistant storage that stores everything in memory and periodically syncs it with locally stored file in key=value format.
## Install
```
bun add @session.js/file-keyval-storage
```
## Use with Session.js
This type of storage only works in server environments, because it uses fs module to access user's file system. `filePath` is optional and defaults to ./storage.db
```ts
import { Session } from '@session.js/client'
import { FileKeyvalStorage } from '@session.js/file-keyval-storage'
new Session({
storage: new FileKeyvalStorage({
filePath: 'some-file-path.db'
})
})
```

View file

@ -1,14 +0,0 @@
# In-memory storage
Default storage. It's not persistant, so it's ideal for one-time instances.
## Use with Session.js
You don't need to provide it to Session instance constructor, because it is used by default. You can optionally provide it as:
```ts
import { Session } from '@session.js/client'
import { InMemoryStorage } from '@session.js/client/storage'
new Session({ storage: new InMemoryStorage() })
```

View file

@ -1,49 +0,0 @@
# Storage
You can use any existing storage adapter or [write your own](#creating-new-storage-adapter)
## Overview
<table>
<tr>
<td> Storage type </td> <td> Description </td>
</tr>
<tr>
<td><a href="./in-memory">In-memory</a></td>
<td><b>Default</b> storage that stores data in memory, that is reset after this process exits or tab is closed. Ideal for short living one-time bots or testing. It is not persistant.</td>
</tr>
<tr>
<td><a href="./file-keyval">Persistant file-based key=value storage with `fs`</a></td>
<td>Simple storage that stores everything in memory and periodically syncs it with locally stored file in key=value format. `filePath` is optional and defaults to `./storage.db` </td>
</tr>
</table>
## Creating new storage adapter
To implement your own storage, write class that implements Storage interface from `@session.js/types/storage`. Take a look at this example with in-memory storage
```ts
import type { Storage } from '@session.js/types'
export class MyInMemoryStorage implements Storage {
storage: Map<string, string> = new Map()
get(key: string) {
return this.storage.get(key) ?? null
}
set(key: string, value: string) {
this.storage.set(key, value)
}
delete(key: string) {
this.storage.delete(key)
}
has(key: string) {
return this.storage.has(key)
}
}
```

View file

@ -1,30 +0,0 @@
# Typing indicator
Session.js allows you to show/hide typing indicator in 1-1 conversations. You should only call this method if user explicitly agreed to share typing state with recipient(s).
```ts
import { Session, ready } from '@session.js/client'
await ready
const mnemonic = 'love love love love love love love love love love love love love'
const session = new Session()
session.setMnemonic(mnemonic)
await session.showTypingIndicator({
conversation: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b'
})
```
Typing indicators last for 20 seconds, after that clients will hide it until the next showTypingIndicator call.
Hide typing indicator early:
```ts
await session.hideTypingIndicator({
conversation: '057aeb66e45660c3bdfb7c62706f6440226af43ec13f3b6f899c1dd4db1b8fce5b'
})
```
## Events about typing indicators
See [events page](./events.md#messagetypingindicator)

1421
error-handling/index.html Normal file

File diff suppressed because it is too large Load diff

1906
events/index.html Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1636
getting-started/index.html Normal file

File diff suppressed because it is too large Load diff

1489
index.html Normal file

File diff suppressed because it is too large Load diff

1463
mark-as-read/index.html Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,84 +0,0 @@
site_name: Session.js Docs
site_url: https://sessionjs.github.io/docs
repo_url: https://git.hloth.dev/session.js/docs
repo_name: sessionjs/client
theme:
name: material
logo: assets/logo.jpeg
palette:
- scheme: default
primary: green
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
primary: green
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.tabs
- navigation.tabs.sticky
- navigation.indexes
copyright: Created by Viktor Shchelochkov aka <a href="https://hloth.dev" target="_blank" rel="noreferrer">hloth.dev</a>
extra:
social:
- icon: material/pencil
link: https://git.hloth.dev/session.js/docs
name: Edit documentation on GitHub
- icon: fontawesome/brands/github
link: https://git.hloth.dev/session.js
name: Session.js on GitHub
- icon: fontawesome/brands/telegram
link: https://t.me/sessionjs
name: Session.js and other stuff Telegram channel
markdown_extensions:
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
- admonition
- pymdownx.details
plugins:
- search
- mkdocs-simple-hooks:
hooks:
on_post_build: "docs.hooks:copy_get"
extra_css:
- css/custom.css
nav:
- Home:
- Home: index.md
- Getting started: getting-started.md
- Documentation:
- Sending messages: sending.md
- Polling messages: polling.md
- Events: events.md
- Storage:
- storage/index.md
- In-memory: storage/in-memory.md
- File-based persistant: storage/file-keyval.md
- Network:
- network/index.md
- Bun local: network/bun-local.md
- Bun remote: network/bun-remote.md
- Files and attachments: files-and-attachments.md
- Reactions: reactions.md
- Deleting messages: deleting-messages.md
- Set name and avatar: profile.md
- Mark message as read: mark-as-read.md
- Show or hide typing indicator: typing-indicator.md
- Accept conversation request: accept-conversation-request.md
- Send "screenshot taken" message: screenshot-taken-notification.md
- Send "media saved" message: media-saved-notification.md
- SOGS: sogs.md
- Error handling: error-handling.md
- Constants: constants.md
- How Session Works:
- Accounts in Session: principles/users.md
- Messages in Session: principles/messages.md
- Files in Session: principles/files.md
- Utilities:
- Mnemonic: mnemonic.md
- Oxen Name System (ONS): ons.md

1503
mnemonic/index.html Normal file

File diff suppressed because it is too large Load diff

1449
network/bun-local/index.html Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1458
network/index.html Normal file

File diff suppressed because it is too large Load diff

1444
ons/index.html Normal file

File diff suppressed because it is too large Load diff

1547
polling/index.html Normal file

File diff suppressed because it is too large Load diff

1462
principles/files/index.html Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more