diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2022-07-22 23:27:00 +0200 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2022-07-22 23:27:00 +0200 |
| commit | 45c89b984d3f2b3bf97c8c5ee52e62aa6a4af6dc (patch) | |
| tree | 098417a178a0fe4e054722a84e696d4574c98b16 | |
| parent | 773829d1848f1f18ef587ed5608dd72483c9be53 (diff) | |
| download | mitjafelicijan.com-45c89b984d3f2b3bf97c8c5ee52e62aa6a4af6dc.tar.gz | |
Added front end search
| -rw-r--r-- | assets/general/elasticlunr.min.js | 10 | ||||
| -rwxr-xr-x | template/_includes.html | 3 | ||||
| -rwxr-xr-x | template/_navigation.html | 2 | ||||
| -rw-r--r-- | template/_search.html | 6 | ||||
| -rwxr-xr-x | template/index.html | 4 | ||||
| -rwxr-xr-x | template/post.html | 2 | ||||
| -rwxr-xr-x | template/script.js | 145 | ||||
| -rwxr-xr-x | template/style.css | 145 |
8 files changed, 227 insertions, 90 deletions
diff --git a/assets/general/elasticlunr.min.js b/assets/general/elasticlunr.min.js new file mode 100644 index 0000000..94b20dd --- /dev/null +++ b/assets/general/elasticlunr.min.js | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | /** | ||
| 2 | * elasticlunr - http://weixsong.github.io | ||
| 3 | * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 | ||
| 4 | * | ||
| 5 | * Copyright (C) 2017 Oliver Nightingale | ||
| 6 | * Copyright (C) 2017 Wei Song | ||
| 7 | * MIT Licensed | ||
| 8 | * @license | ||
| 9 | */ | ||
| 10 | !function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u<s.length;u++){var a=s[u];r[a]=this.pipeline.run(t.tokenizer(e[a]))}var l={};for(var c in o){var d=r[c]||r.any;if(d){var f=this.fieldSearch(d,c,o),h=o[c].boost;for(var p in f)f[p]=f[p]*h;for(var p in f)p in l?l[p]+=f[p]:l[p]=f[p]}}var v,g=[];for(var p in l)v={ref:p,score:l[p]},this.documentStore.hasDoc(p)&&(v.doc=this.documentStore.getDoc(p)),g.push(v);return g.sort(function(e,t){return t.score-e.score}),g},t.Index.prototype.fieldSearch=function(e,t,n){var i=n[t].bool,o=n[t].expand,r=n[t].boost,s=null,u={};return 0!==r?(e.forEach(function(e){var n=[e];1==o&&(n=this.index[t].expandToken(e));var r={};n.forEach(function(n){var o=this.index[t].getDocs(n),a=this.idf(n,t);if(s&&"AND"==i){var l={};for(var c in s)c in o&&(l[c]=o[c]);o=l}n==e&&this.fieldSearchStats(u,n,o);for(var c in o){var d=this.index[t].getTermFrequency(n,c),f=this.documentStore.getFieldLength(c,t),h=1;0!=f&&(h=1/Math.sqrt(f));var p=1;n!=e&&(p=.15*(1-(n.length-e.length)/n.length));var v=d*a*h*p;c in r?r[c]+=v:r[c]=v}},this),s=this.mergeScores(s,r,i)},this),s=this.coordNorm(s,u,e.length)):void 0},t.Index.prototype.mergeScores=function(e,t,n){if(!e)return t;if("AND"==n){var i={};for(var o in t)o in e&&(i[o]=e[o]+t[o]);return i}for(var o in t)o in e?e[o]+=t[o]:e[o]=t[o];return e},t.Index.prototype.fieldSearchStats=function(e,t,n){for(var i in n)i in e?e[i].push(t):e[i]=[t]},t.Index.prototype.coordNorm=function(e,t,n){for(var i in e)if(i in t){var o=t[i].length;e[i]=e[i]*o/n}return e},t.Index.prototype.toJSON=function(){var e={};return this._fields.forEach(function(t){e[t]=this.index[t].toJSON()},this),{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),index:e,pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},t.DocumentStore=function(e){this._save=null===e||void 0===e?!0:e,this.docs={},this.docInfo={},this.length=0},t.DocumentStore.load=function(e){var t=new this;return t.length=e.length,t.docs=e.docs,t.docInfo=e.docInfo,t._save=e.save,t},t.DocumentStore.prototype.isDocStored=function(){return this._save},t.DocumentStore.prototype.addDoc=function(t,n){this.hasDoc(t)||this.length++,this.docs[t]=this._save===!0?e(n):null},t.DocumentStore.prototype.getDoc=function(e){return this.hasDoc(e)===!1?null:this.docs[e]},t.DocumentStore.prototype.hasDoc=function(e){return e in this.docs},t.DocumentStore.prototype.removeDoc=function(e){this.hasDoc(e)&&(delete this.docs[e],delete this.docInfo[e],this.length--)},t.DocumentStore.prototype.addFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&(this.docInfo[e]||(this.docInfo[e]={}),this.docInfo[e][t]=n)},t.DocumentStore.prototype.updateFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&this.addFieldLength(e,t,n)},t.DocumentStore.prototype.getFieldLength=function(e,t){return null===e||void 0===e?0:e in this.docs&&t in this.docInfo[e]?this.docInfo[e][t]:0},t.DocumentStore.prototype.toJSON=function(){return{docs:this.docs,docInfo:this.docInfo,length:this.length,save:this._save}},t.stemmer=function(){var e={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},t={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,u="^("+o+")?"+r+o+"("+r+")?$",a="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,c=new RegExp(s),d=new RegExp(a),f=new RegExp(u),h=new RegExp(l),p=/^(.+?)(ss|i)es$/,v=/^(.+?)([^s])s$/,g=/^(.+?)eed$/,m=/^(.+?)(ed|ing)$/,y=/.$/,S=/(at|bl|iz)$/,x=new RegExp("([^aeiouylsz])\\1$"),w=new RegExp("^"+o+i+"[^aeiouwxy]$"),I=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,D=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,_=/^(.+?)e$/,P=/ll$/,k=new RegExp("^"+o+i+"[^aeiouwxy]$"),z=function(n){var i,o,r,s,u,a,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,u=v,s.test(n)?n=n.replace(s,"$1$2"):u.test(n)&&(n=n.replace(u,"$1$2")),s=g,u=m,s.test(n)){var z=s.exec(n);s=c,s.test(z[1])&&(s=y,n=n.replace(s,""))}else if(u.test(n)){var z=u.exec(n);i=z[1],u=h,u.test(i)&&(n=i,u=S,a=x,l=w,u.test(n)?n+="e":a.test(n)?(s=y,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=I,s.test(n)){var z=s.exec(n);i=z[1],n=i+"i"}if(s=b,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+e[o])}if(s=E,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+t[o])}if(s=D,u=F,s.test(n)){var z=s.exec(n);i=z[1],s=d,s.test(i)&&(n=i)}else if(u.test(n)){var z=u.exec(n);i=z[1]+z[2],u=d,u.test(i)&&(n=i)}if(s=_,s.test(n)){var z=s.exec(n);i=z[1],s=d,u=f,a=k,(s.test(i)||u.test(i)&&!a.test(i))&&(n=i)}return s=P,u=d,s.test(n)&&u.test(n)&&(s=y,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return z}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==!0?e:void 0},t.clearStopWords=function(){t.stopWordFilter.stopWords={}},t.addStopWords=function(e){null!=e&&Array.isArray(e)!==!1&&e.forEach(function(e){t.stopWordFilter.stopWords[e]=!0},this)},t.resetStopWords=function(){t.stopWordFilter.stopWords=t.defaultStopWords},t.defaultStopWords={"":!0,a:!0,able:!0,about:!0,across:!0,after:!0,all:!0,almost:!0,also:!0,am:!0,among:!0,an:!0,and:!0,any:!0,are:!0,as:!0,at:!0,be:!0,because:!0,been:!0,but:!0,by:!0,can:!0,cannot:!0,could:!0,dear:!0,did:!0,"do":!0,does:!0,either:!0,"else":!0,ever:!0,every:!0,"for":!0,from:!0,get:!0,got:!0,had:!0,has:!0,have:!0,he:!0,her:!0,hers:!0,him:!0,his:!0,how:!0,however:!0,i:!0,"if":!0,"in":!0,into:!0,is:!0,it:!0,its:!0,just:!0,least:!0,let:!0,like:!0,likely:!0,may:!0,me:!0,might:!0,most:!0,must:!0,my:!0,neither:!0,no:!0,nor:!0,not:!0,of:!0,off:!0,often:!0,on:!0,only:!0,or:!0,other:!0,our:!0,own:!0,rather:!0,said:!0,say:!0,says:!0,she:!0,should:!0,since:!0,so:!0,some:!0,than:!0,that:!0,the:!0,their:!0,them:!0,then:!0,there:!0,these:!0,they:!0,"this":!0,tis:!0,to:!0,too:!0,twas:!0,us:!0,wants:!0,was:!0,we:!0,were:!0,what:!0,when:!0,where:!0,which:!0,"while":!0,who:!0,whom:!0,why:!0,will:!0,"with":!0,would:!0,yet:!0,you:!0,your:!0},t.stopWordFilter.stopWords=t.defaultStopWords,t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(e){if(null===e||void 0===e)throw new Error("token should not be undefined");return e.replace(/^\W+/,"").replace(/\W+$/,"")},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.InvertedIndex=function(){this.root={docs:{},df:0}},t.InvertedIndex.load=function(e){var t=new this;return t.root=e.root,t},t.InvertedIndex.prototype.addToken=function(e,t,n){for(var n=n||this.root,i=0;i<=e.length-1;){var o=e[i];o in n||(n[o]={docs:{},df:0}),i+=1,n=n[o]}var r=t.ref;n.docs[r]?n.docs[r]={tf:t.tf}:(n.docs[r]={tf:t.tf},n.df+=1)},t.InvertedIndex.prototype.hasToken=function(e){if(!e)return!1;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return!1;t=t[e[n]]}return!0},t.InvertedIndex.prototype.getNode=function(e){if(!e)return null;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return null;t=t[e[n]]}return t},t.InvertedIndex.prototype.getDocs=function(e){var t=this.getNode(e);return null==t?{}:t.docs},t.InvertedIndex.prototype.getTermFrequency=function(e,t){var n=this.getNode(e);return null==n?0:t in n.docs?n.docs[t].tf:0},t.InvertedIndex.prototype.getDocFreq=function(e){var t=this.getNode(e);return null==t?0:t.df},t.InvertedIndex.prototype.removeToken=function(e,t){if(e){var n=this.getNode(e);null!=n&&t in n.docs&&(delete n.docs[t],n.df-=1)}},t.InvertedIndex.prototype.expandToken=function(e,t,n){if(null==e||""==e)return[];var t=t||[];if(void 0==n&&(n=this.getNode(e),null==n))return t;n.df>0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e<arguments.length;e++)t=arguments[e],~this.indexOf(t)||this.elements.splice(this.locationFor(t),0,t);this.length=this.elements.length},lunr.SortedSet.prototype.toArray=function(){return this.elements.slice()},lunr.SortedSet.prototype.map=function(e,t){return this.elements.map(e,t)},lunr.SortedSet.prototype.forEach=function(e,t){return this.elements.forEach(e,t)},lunr.SortedSet.prototype.indexOf=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]<u[i]?n++:s[n]>u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o<r.length;o++)i.add(r[o]);return i},lunr.SortedSet.prototype.toJSON=function(){return this.toArray()},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.elasticlunr=t()}(this,function(){return t})}(); \ No newline at end of file | ||
diff --git a/template/_includes.html b/template/_includes.html index d16fa3d..8102a35 100755 --- a/template/_includes.html +++ b/template/_includes.html | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | <!-- user code --> | 1 | <!-- user code --> |
| 2 | 2 | ||
| 3 | <script src="/script.js?v=2022-01-30-01" async></script> | 3 | <script src="/assets/general/elasticlunr.min.js"></script> |
| 4 | <script src="/script.js?v=2022-07-22-02" async></script> | ||
diff --git a/template/_navigation.html b/template/_navigation.html index 85290a3..45a2a9e 100755 --- a/template/_navigation.html +++ b/template/_navigation.html | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | <a href="/books.html">Books</a> | 13 | <a href="/books.html">Books</a> |
| 14 | 14 | ||
| 15 | <a href="/feed.rss" itemprop="url">RSS</a> | 15 | <a href="/feed.rss" itemprop="url">RSS</a> |
| 16 | |||
| 17 | <a class="cursor search-trigger">Search</a> | ||
| 16 | </nav> | 18 | </nav> |
| 17 | </header> | 19 | </header> |
| 18 | </div> | 20 | </div> |
diff --git a/template/_search.html b/template/_search.html new file mode 100644 index 0000000..997b35c --- /dev/null +++ b/template/_search.html | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | <div class="blur hidden"></div> | ||
| 2 | |||
| 3 | <section class="search-form hidden"> | ||
| 4 | <input type="search" placeholder="Search ..."> | ||
| 5 | <ul></ul> | ||
| 6 | </section> | ||
diff --git a/template/index.html b/template/index.html index 8c1cc6e..cb334e1 100755 --- a/template/index.html +++ b/template/index.html | |||
| @@ -55,6 +55,10 @@ | |||
| 55 | 55 | ||
| 56 | {{template "_footer.html"}} | 56 | {{template "_footer.html"}} |
| 57 | 57 | ||
| 58 | {{template "_includes.html"}} | ||
| 59 | |||
| 60 | {{template "_search.html"}} | ||
| 61 | |||
| 58 | </body> | 62 | </body> |
| 59 | 63 | ||
| 60 | </html> | 64 | </html> |
diff --git a/template/post.html b/template/post.html index 564ed09..cf80b22 100755 --- a/template/post.html +++ b/template/post.html | |||
| @@ -69,6 +69,8 @@ | |||
| 69 | 69 | ||
| 70 | {{template "_includes.html"}} | 70 | {{template "_includes.html"}} |
| 71 | 71 | ||
| 72 | {{template "_search.html"}} | ||
| 73 | |||
| 72 | {{template "_libraries.html"}} | 74 | {{template "_libraries.html"}} |
| 73 | 75 | ||
| 74 | </body> | 76 | </body> |
diff --git a/template/script.js b/template/script.js index 0e1291c..3c58403 100755 --- a/template/script.js +++ b/template/script.js | |||
| @@ -25,79 +25,88 @@ window.addEventListener('load', async () => { | |||
| 25 | }); | 25 | }); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | // comments code | 28 | // Search functionality |
| 29 | const commentsEndpoint = 'https://mitjafelicijan.com/comments-api'; | 29 | |
| 30 | const commentsPlaceholder = document.querySelector('.comments'); | 30 | window.index = null; |
| 31 | 31 | ||
| 32 | if (commentsPlaceholder) { | 32 | const response = await fetch('/feed.json'); |
| 33 | const guid = commentsPlaceholder.dataset.guid; | 33 | const feed = await response.json(); |
| 34 | const name = commentsPlaceholder.querySelector('input'); | 34 | |
| 35 | const comment = commentsPlaceholder.querySelector('textarea'); | 35 | window.index = elasticlunr(function () { |
| 36 | const submit = commentsPlaceholder.querySelector('button'); | 36 | this.addField('title'); |
| 37 | const comments = commentsPlaceholder.querySelector('ul'); | 37 | this.addField('body'); |
| 38 | 38 | this.setRef('id'); | |
| 39 | if (guid) { | 39 | }); |
| 40 | await readAndRenderComments(guid, comments); | 40 | |
| 41 | 41 | for (const item of feed.items) { | |
| 42 | submit.addEventListener('click', async() => { | 42 | item.id = item.url; |
| 43 | submit.disabled = true; | 43 | window.index.addDoc({ |
| 44 | await writeComments(guid, name.value, comment.value); | 44 | id: item.url, |
| 45 | 45 | title: item.title, | |
| 46 | submit.disabled = false; | 46 | body: item.content_html, |
| 47 | name.value = ''; | 47 | url: item.url, |
| 48 | comment.value = ''; | 48 | }); |
| 49 | |||
| 50 | await readAndRenderComments(guid, comments); | ||
| 51 | }); | ||
| 52 | } | ||
| 53 | } | 49 | } |
| 54 | 50 | ||
| 55 | async function writeComments(guid, name, comment) { | 51 | const blur = document.querySelector('.blur'); |
| 56 | const response = await fetch(commentsEndpoint, { | 52 | const searchForm = document.querySelector('.search-form'); |
| 57 | method: 'POST', | 53 | const searchResultsList = document.querySelector('.search-form ul'); |
| 58 | headers: { | 54 | |
| 59 | 'Accept': 'application/json', | 55 | function showSearchModal() { |
| 60 | 'Content-Type': 'application/json' | 56 | blur.classList.remove('hidden'); |
| 61 | }, | 57 | searchForm.classList.remove('hidden'); |
| 62 | body: JSON.stringify({ | 58 | |
| 63 | action: 'write', | 59 | // Clear search input. |
| 64 | guid, | 60 | searchForm.querySelector('input').value = ''; |
| 65 | name, | 61 | |
| 66 | comment, | 62 | // We need to clear the list before opening modal. |
| 67 | }) | 63 | searchResultsList.innerHTML = ''; |
| 68 | }); | 64 | |
| 65 | // Focus on search input. | ||
| 66 | searchForm.querySelector('input').focus(); | ||
| 69 | } | 67 | } |
| 70 | 68 | ||
| 71 | async function readAndRenderComments(guid, commentsPlaceholder) { | 69 | document.querySelector('.search-trigger').addEventListener('click', async (evt) => { |
| 72 | const response = await fetch(commentsEndpoint, { | 70 | showSearchModal(); |
| 73 | method: 'POST', | 71 | }); |
| 74 | headers: { | 72 | |
| 75 | 'Accept': 'application/json', | 73 | document.onkeydown = function (e) { |
| 76 | 'Content-Type': 'application/json' | 74 | // Show search modal on F key. |
| 77 | }, | 75 | if (blur.classList.contains('hidden')) { |
| 78 | body: JSON.stringify({ | 76 | if (e.key === 'f') { |
| 79 | action: 'read', | 77 | setTimeout(() => { |
| 80 | guid, | 78 | showSearchModal(); |
| 81 | }) | 79 | }, 100); |
| 82 | }); | 80 | } |
| 81 | } | ||
| 83 | 82 | ||
| 84 | // remove all existing comments from list | 83 | // Hide search modal on escape key. |
| 85 | commentsPlaceholder.innerHTML = ''; | 84 | if (!blur.classList.contains('hidden')) { |
| 86 | 85 | if (e.key === 'Escape') { | |
| 87 | const commentList = await response.json(); | 86 | blur.classList.add('hidden'); |
| 88 | for (const comment of commentList.reverse()) { | 87 | searchForm.classList.add('hidden'); |
| 89 | const date = new Date(comment.date).toLocaleDateString('en-US', { | 88 | } |
| 90 | year: 'numeric', | ||
| 91 | month: 'long', | ||
| 92 | day: 'numeric', | ||
| 93 | hour: 'numeric', | ||
| 94 | minute: 'numeric' | ||
| 95 | }); | ||
| 96 | |||
| 97 | const commentElement = document.createElement('li'); | ||
| 98 | commentElement.innerHTML = `<p><b>${comment.name}</b> - ${date}<p><p>${comment.comment}<p><hr>`; | ||
| 99 | commentsPlaceholder.appendChild(commentElement); | ||
| 100 | } | 89 | } |
| 101 | } | 90 | }; |
| 91 | |||
| 92 | blur.addEventListener('click', async (evt) => { | ||
| 93 | evt.target.classList.add('hidden'); | ||
| 94 | searchForm.classList.add('hidden'); | ||
| 95 | }); | ||
| 96 | |||
| 97 | document.querySelector('.search-form input').addEventListener('keyup', async (evt) => { | ||
| 98 | // Perform search. | ||
| 99 | const searchResults = window.index.search(evt.target.value); | ||
| 100 | |||
| 101 | // We need to clear the list before adding new results. | ||
| 102 | searchResultsList.innerHTML = ''; | ||
| 103 | |||
| 104 | // Loop through the results and add them to the list. | ||
| 105 | for (const result of searchResults.slice(0, 9)) { | ||
| 106 | const listItem = document.createElement('li'); | ||
| 107 | listItem.innerHTML = `<a href="${result.doc.url}">${result.doc.title}</a>`; | ||
| 108 | searchResultsList.appendChild(listItem); | ||
| 109 | } | ||
| 110 | }); | ||
| 102 | 111 | ||
| 103 | }); | 112 | }); |
diff --git a/template/style.css b/template/style.css index af0d7bc..ebb2b26 100755 --- a/template/style.css +++ b/template/style.css | |||
| @@ -29,7 +29,7 @@ body { | |||
| 29 | background: white; | 29 | background: white; |
| 30 | /*font-family: 'Times New Roman', Times, serif;*/ | 30 | /*font-family: 'Times New Roman', Times, serif;*/ |
| 31 | /*font-family: 'IBM Plex Sans', sans-serif;*/ | 31 | /*font-family: 'IBM Plex Sans', sans-serif;*/ |
| 32 | font-family: "SF Pro Text","SF Pro Icons","Helvetica Neue","Helvetica","Arial",sans-serif; | 32 | font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica", "Arial", sans-serif; |
| 33 | color: var(--base-color); | 33 | color: var(--base-color); |
| 34 | font-size: var(--base-font-size); | 34 | font-size: var(--base-font-size); |
| 35 | line-height: var(--base-line-heigh); | 35 | line-height: var(--base-line-heigh); |
| @@ -54,6 +54,10 @@ hr { | |||
| 54 | color: #000; | 54 | color: #000; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | .cursor { | ||
| 58 | cursor: pointer; | ||
| 59 | } | ||
| 60 | |||
| 57 | /* width of the page */ | 61 | /* width of the page */ |
| 58 | 62 | ||
| 59 | .wrapper { | 63 | .wrapper { |
| @@ -74,12 +78,35 @@ a:hover { | |||
| 74 | 78 | ||
| 75 | /* headings */ | 79 | /* headings */ |
| 76 | 80 | ||
| 77 | h1 { font-size: 220%; line-height: 1.2em; } | 81 | h1 { |
| 78 | h2 { font-size: 180%; line-height: 1.2em; } | 82 | font-size: 220%; |
| 79 | h3 { font-size: 160%; line-height: 1.2em; } | 83 | line-height: 1.2em; |
| 80 | h4 { font-size: 140%; line-height: 1.2em; } | 84 | } |
| 81 | h5 { font-size: 120%; line-height: 1.2em; } | 85 | |
| 82 | h6 { font-size: 100%; line-height: 1.2em; } | 86 | h2 { |
| 87 | font-size: 180%; | ||
| 88 | line-height: 1.2em; | ||
| 89 | } | ||
| 90 | |||
| 91 | h3 { | ||
| 92 | font-size: 160%; | ||
| 93 | line-height: 1.2em; | ||
| 94 | } | ||
| 95 | |||
| 96 | h4 { | ||
| 97 | font-size: 140%; | ||
| 98 | line-height: 1.2em; | ||
| 99 | } | ||
| 100 | |||
| 101 | h5 { | ||
| 102 | font-size: 120%; | ||
| 103 | line-height: 1.2em; | ||
| 104 | } | ||
| 105 | |||
| 106 | h6 { | ||
| 107 | font-size: 100%; | ||
| 108 | line-height: 1.2em; | ||
| 109 | } | ||
| 83 | 110 | ||
| 84 | h1[itemtype="headline"] { | 111 | h1[itemtype="headline"] { |
| 85 | padding-bottom: 0; | 112 | padding-bottom: 0; |
| @@ -95,12 +122,15 @@ table { | |||
| 95 | width: 100%; | 122 | width: 100%; |
| 96 | } | 123 | } |
| 97 | 124 | ||
| 98 | table, th, td { | 125 | table, |
| 126 | th, | ||
| 127 | td { | ||
| 99 | border: 1px solid black; | 128 | border: 1px solid black; |
| 100 | text-align: left; | 129 | text-align: left; |
| 101 | } | 130 | } |
| 102 | 131 | ||
| 103 | th, td { | 132 | th, |
| 133 | td { | ||
| 104 | padding: 5px 10px; | 134 | padding: 5px 10px; |
| 105 | } | 135 | } |
| 106 | 136 | ||
| @@ -268,7 +298,7 @@ code { | |||
| 268 | font-weight: 500; | 298 | font-weight: 500; |
| 269 | } | 299 | } |
| 270 | 300 | ||
| 271 | pre > code { | 301 | pre>code { |
| 272 | background: unset; | 302 | background: unset; |
| 273 | padding: unset; | 303 | padding: unset; |
| 274 | 304 | ||
| @@ -285,7 +315,8 @@ pre { | |||
| 285 | margin-block-end: 40px; | 315 | margin-block-end: 40px; |
| 286 | } | 316 | } |
| 287 | 317 | ||
| 288 | img, video { | 318 | img, |
| 319 | video { | ||
| 289 | max-width: 100%; | 320 | max-width: 100%; |
| 290 | margin: 30px auto; | 321 | margin: 30px auto; |
| 291 | display: block; | 322 | display: block; |
| @@ -357,14 +388,14 @@ audio { | |||
| 357 | 388 | ||
| 358 | /* comments */ | 389 | /* comments */ |
| 359 | 390 | ||
| 360 | .comments input{ | 391 | .comments input { |
| 361 | width: 100%; | 392 | width: 100%; |
| 362 | font: var(--comment-form-font); | 393 | font: var(--comment-form-font); |
| 363 | border: 1px solid #bbb; | 394 | border: 1px solid #bbb; |
| 364 | padding: 5px; | 395 | padding: 5px; |
| 365 | } | 396 | } |
| 366 | 397 | ||
| 367 | .comments textarea{ | 398 | .comments textarea { |
| 368 | width: 100%; | 399 | width: 100%; |
| 369 | height: 100px; | 400 | height: 100px; |
| 370 | resize: vertical; | 401 | resize: vertical; |
| @@ -384,13 +415,69 @@ audio { | |||
| 384 | border-top: initial !important; | 415 | border-top: initial !important; |
| 385 | } | 416 | } |
| 386 | 417 | ||
| 418 | /* search form */ | ||
| 419 | |||
| 420 | .search-form { | ||
| 421 | position: fixed; | ||
| 422 | top: 120px; | ||
| 423 | left: 50%; | ||
| 424 | margin-left: -250px; | ||
| 425 | width: 500px; | ||
| 426 | padding: 30px; | ||
| 427 | background: #eee; | ||
| 428 | border-radius: 5px; | ||
| 429 | } | ||
| 430 | |||
| 431 | .blur { | ||
| 432 | position: fixed; | ||
| 433 | top: 0; | ||
| 434 | left: 0; | ||
| 435 | right: 0; | ||
| 436 | bottom: 0; | ||
| 437 | backdrop-filter: blur(15px); | ||
| 438 | } | ||
| 439 | |||
| 440 | .hidden { | ||
| 441 | display: none; | ||
| 442 | } | ||
| 443 | |||
| 444 | .search-form input { | ||
| 445 | width: 100%; | ||
| 446 | margin-bottom: 20px; | ||
| 447 | border: 1px solid #ffffff; | ||
| 448 | padding: 5px 10px; | ||
| 449 | border-radius: 3px; | ||
| 450 | outline: none; | ||
| 451 | } | ||
| 452 | |||
| 453 | .search-form ul { | ||
| 454 | list-style-type: none; | ||
| 455 | padding: 0; | ||
| 456 | margin: 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | .search-form ul li { | ||
| 460 | margin-bottom: 5px; | ||
| 461 | } | ||
| 462 | |||
| 387 | /* responsive */ | 463 | /* responsive */ |
| 388 | 464 | ||
| 389 | @media only screen and (max-width: 960px) { | 465 | @media only screen and (max-width: 960px) { |
| 390 | main { padding: 0 20px; } | 466 | main { |
| 391 | footer { padding: 0 20px; } | 467 | padding: 0 20px; |
| 392 | h1[itemtype="headline"] { font-size: 220%; } | 468 | } |
| 393 | .navigation header { padding: 0 20px; } | 469 | |
| 470 | footer { | ||
| 471 | padding: 0 20px; | ||
| 472 | } | ||
| 473 | |||
| 474 | h1[itemtype="headline"] { | ||
| 475 | font-size: 220%; | ||
| 476 | } | ||
| 477 | |||
| 478 | .navigation header { | ||
| 479 | padding: 0 20px; | ||
| 480 | } | ||
| 394 | 481 | ||
| 395 | article img { | 482 | article img { |
| 396 | max-width: 100%; | 483 | max-width: 100%; |
| @@ -400,10 +487,26 @@ audio { | |||
| 400 | } | 487 | } |
| 401 | 488 | ||
| 402 | @media only screen and (max-width: 600px) { | 489 | @media only screen and (max-width: 600px) { |
| 403 | .navigation header { display: block; } | 490 | .navigation header { |
| 404 | .navigation header h3 { text-align: center; margin-bottom: 10px; } | 491 | display: block; |
| 405 | .navigation header nav { text-align: center; } | 492 | } |
| 406 | .post-list li a h2 { font-weight: 500; } | 493 | |
| 494 | .navigation header h3 { | ||
| 495 | text-align: center; | ||
| 496 | margin-bottom: 10px; | ||
| 497 | } | ||
| 498 | |||
| 499 | .navigation header nav { | ||
| 500 | text-align: center; | ||
| 501 | } | ||
| 502 | |||
| 503 | .post-list li a h2 { | ||
| 504 | font-weight: 500; | ||
| 505 | } | ||
| 506 | |||
| 507 | .search-trigger { | ||
| 508 | display: none; | ||
| 509 | } | ||
| 407 | } | 510 | } |
| 408 | 511 | ||
| 409 | /* light/dark mode */ | 512 | /* light/dark mode */ |
