2022-02-15 23:28:50 +00:00
import * as bitty from './bitty.js' ;
2022-01-29 19:40:35 +00:00
2022-06-09 05:53:37 +00:00
window . bitty = bitty ;
2022-05-17 15:38:05 +00:00
// if ('serviceWorker' in navigator) {
// navigator.serviceWorker
// .register('/worker.js')
// .then(function() { console.debug("Service Worker Registered"); });
// }
2022-01-29 19:40:35 +00:00
2022-06-30 14:25:05 +00:00
const isFramed = window . self !== window . top ;
2022-06-29 15:34:17 +00:00
2022-05-20 15:37:00 +00:00
function addToast ( ) {
// `<div id="toast">
// itty.bitty is experimental technology that renders linked content from outside sources.
// <a href="http://toast.bitty.site" target="_blank">Learn more</a>.
// <br><br>This content is only as trustworthy as its source, and it should be treated with the caution you would show any insecure web page.
// <br><br><button onclick="dismiss()">I understand</button> <input id="never" type="checkbox"><label for="never">Never show this</label>
// </div>`
}
2022-06-30 14:25:05 +00:00
// function dismiss() {
// if (document.getElementById("never").checked) window.localStorage.setItem('toasted', true);
// document.body.classList.remove("toasting")
// }
2022-06-11 15:48:32 +00:00
2022-06-29 15:34:17 +00:00
function showLoader ( state ) {
let loader = document . getElementById ( "loader" ) ;
if ( state ) {
if ( ! loader ) {
loader = document . createElement ( "div" ) ;
loader . id = "loader" ;
document . body . appendChild ( loader ) ;
2022-06-30 14:25:05 +00:00
}
} else if ( loader ) {
setTimeout ( ( ) => loader ? . parentElement ? . removeChild ( loader ) , 500 )
2022-06-29 15:34:17 +00:00
}
2022-06-30 14:25:05 +00:00
setTimeout ( ( ) => document . body . classList . toggle ( "loading" , state ) , 1 )
2022-06-11 15:48:32 +00:00
}
2022-06-29 15:34:17 +00:00
window . showLoader = showLoader ;
2022-01-12 14:49:23 +00:00
2022-06-30 15:50:57 +00:00
// Document Attribute Setters
2022-06-11 05:29:43 +00:00
function setThemeColor ( color ) {
2022-06-15 14:52:10 +00:00
let el = document . getElementById ( "themeColor" ) ;
if ( ! el ) {
el = document . createElement ( "meta" ) ;
el . name = "theme-color" ;
el . id = "themeColor" ;
document . head . appendChild ( el ) ;
}
el . content = color ;
2022-06-11 05:29:43 +00:00
}
2022-01-29 19:40:35 +00:00
function setFavicon ( favicon ) {
document . getElementById ( "favicon" ) . href = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em"><text y=".9em">' + favicon + '</text></svg>'
2022-01-19 07:57:49 +00:00
}
2022-02-15 23:28:50 +00:00
window . el = function ( tagName , attrs , ... children ) {
let l = document . createElement ( tagName ) ;
Object . entries ( attrs ) . forEach ( ( [ k , v ] ) => l [ k ] = v ) ;
children . forEach ( ( c ) => l . appendChild ( c ) ) ;
return l ;
}
const renderers = {
2022-02-17 17:54:22 +00:00
"application/ld+json" : { script : "recipe" } ,
2022-07-02 21:28:23 +00:00
"text/canvas+javascript" : { script : "canvas" } ,
"text/javascript" : { script : "script" } ,
2022-07-09 15:33:14 +00:00
"application/bitsy" : { script : "/render/bitsy.html" , sandbox : "bitsy" } ,
2022-07-02 21:28:23 +00:00
"c" : { script : "color" } ,
2022-05-12 05:35:27 +00:00
"text/rawhtml" : { script : "parse" } ,
2022-02-17 17:54:22 +00:00
"javascript" : { script : "bookmarklet" } ,
2022-06-15 14:52:10 +00:00
"ipfs" : { script : "ipfs" , sandbox : "ipfs" } ,
"web3" : { script : "web3" } ,
2022-06-11 03:48:44 +00:00
"text/directory" : { script : "download" , args : { extension : "vcf" , filename : "contact" } }
2022-06-09 05:53:37 +00:00
}
2022-01-29 19:40:35 +00:00
2022-06-15 14:52:10 +00:00
function share ( info ) { // {title, text, url}
if ( ! info . url ) info = { title : document . title , text : document . title , url : location . href } ;
console . log ( "Share" , info ) ;
if ( navigator . share ) {
navigator . share ( info )
. then ( ( ) => { console . log ( 'Thanks for sharing!' ) ; } )
. catch ( console . error ) ;
} else {
copyLink ( info )
}
}
function copyLink ( info ) {
var text = info . url ;
var dummy = document . createElement ( "input" ) ;
document . body . appendChild ( dummy ) ;
dummy . value = text ;
dummy . select ( ) ;
document . execCommand ( "copy" ) ;
document . body . removeChild ( dummy ) ;
document . body . classList . add ( "copied" ) ;
setTimeout ( function ( ) {
document . body . classList . remove ( "copied" ) ;
} , 2000 ) ;
}
2022-06-20 13:58:13 +00:00
let wakeLock ;
const getWakeLock = async ( ) => {
try {
wakeLock = await navigator . wakeLock . request ( ) ;
wakeLock . addEventListener ( 'release' , ( ) => { } ) ;
console . log ( 'Keeping Screen Awake:' , ! wakeLock . released ) ;
} catch ( err ) {
console . error ( ` ${ err . name } , ${ err . message } ` ) ;
}
} ;
const handleVisibilityChange = async ( ) => {
if ( wakeLock !== null && document . visibilityState === 'visible' ) {
await getWakeLock ( ) ;
}
} ;
document . addEventListener ( 'visibilitychange' , handleVisibilityChange ) ;
2022-06-15 14:52:10 +00:00
2022-01-29 19:40:35 +00:00
window . addEventListener ( "message" , function ( e ) {
2022-04-28 03:01:03 +00:00
console . debug ( "Message:" , e . origin , e . data )
2022-01-29 19:40:35 +00:00
if ( e . data . title ) document . title = e . data . title ;
if ( e . data . favicon ) setFavicon ( e . data . favicon ) ;
2022-06-11 05:29:43 +00:00
if ( e . data . themeColor ) setThemeColor ( e . data . themeColor ) ;
2022-04-29 03:10:15 +00:00
if ( e . data . updateURL ) {
2022-06-28 15:43:25 +00:00
window . location . pathname = bitty . metadataToPath ( e . data ) ;
2022-05-17 15:38:05 +00:00
}
2022-06-09 05:53:37 +00:00
2022-06-15 14:52:10 +00:00
if ( e . data . share ) {
share ( e . data . share ) ;
}
2022-06-20 13:58:13 +00:00
if ( e . data . wakeLock ) {
getWakeLock ( ) ;
}
2022-07-02 21:44:18 +00:00
if ( e . data . updateHash ) {
window . history . replaceState ( null , null , e . data . updateHash ) ;
}
2022-05-17 15:38:05 +00:00
if ( e . data . replaceURL ) {
2022-06-09 05:53:37 +00:00
if ( e . data . compressURL ) {
let durl = new bitty . DataURL ( e . data . replaceURL ) ;
durl . compress ( ) . then ( arg => {
window . history . replaceState ( null , null , "/#/" + arg . href ) ;
renderContent ( ) ;
} )
} else {
window . history . replaceState ( null , null , e . data . replaceURL ) ;
renderContent ( ) ;
}
2022-04-29 03:10:15 +00:00
}
2022-06-09 05:53:37 +00:00
2022-01-29 19:40:35 +00:00
if ( e . data . setStorage ) document . localStorage . setItem ( contentHash , e . data . set ) ;
if ( e . data . getStorage ) document . getElementById ( "iframe" ) . postMessage ( document . localStorage . getItem ( contentHash ) , e . origin )
2022-05-17 15:38:05 +00:00
} , false ) ;
2022-06-29 15:34:17 +00:00
async function renderContent ( ) {
showLoader ( true )
2022-06-30 14:25:05 +00:00
2022-04-28 03:01:03 +00:00
var fragment = window . location . hash . substring ( 1 ) ;
2022-06-30 15:50:57 +00:00
if ( fragment . length < 3 && ! isFramed ) {
2022-06-30 14:25:05 +00:00
return location . href = "/edit" ;
}
2022-01-29 19:40:35 +00:00
if ( window . location . search ) { // Redirect search to path (coming out of server opengraph forwarding)
2022-04-28 03:01:03 +00:00
window . history . replaceState ( null , null , window . location . search . substring ( 1 ) + "#" + fragment ) ;
2022-01-29 19:40:35 +00:00
}
var isIE = navigator . userAgent . match ( /rv:11/ ) ;
var isEdge = navigator . userAgent . match ( /Edge\// ) ;
var isWatch = ( window . outerWidth < 200 ) ;
2022-06-30 14:25:05 +00:00
let bittyInfo = bitty . parseBittyURL ( location ) ;
let durl = new bitty . DataURL ( bittyInfo . hashData ) ;
if ( durl . params . compress ) {
console . log ( "Compressing URL" , durl ) ;
delete durl . params . compress ;
durl . compress ( bitty . GZIP _MARKER ) . then ( arg => {
window . history . replaceState ( null , null , "/#/" + arg . href ) ;
renderContent ( ) ;
} )
return ;
2022-01-29 19:40:35 +00:00
}
2019-06-24 20:10:27 +00:00
// if (!window.localStorage.getItem('toasted')) document.body.classList.add("toasting");
2018-07-11 05:38:55 +00:00
2018-07-08 16:18:51 +00:00
var iframe = document . getElementById ( "iframe" ) ;
2022-01-29 19:40:35 +00:00
var dataPrefix = undefined ;
2022-01-21 23:08:26 +00:00
var renderMode = "data" ;
2022-06-11 03:48:44 +00:00
var renderer ;
2018-07-08 15:17:48 +00:00
2022-05-18 05:36:38 +00:00
let components = window . location . pathname . substring ( 1 ) . split ( "/" ) ;
let info = { }
2022-05-20 15:37:00 +00:00
info . title = decodeURIComponent ( components . shift ( ) ) . replace ( /-/g , " " ) . replace ( /– /g , "-" ) ;
let i ;
for ( i = 0 ; i < components . length ; i += 2 ) {
let key = components [ i ] ;
let value = decodeURIComponent ( components [ i + 1 ] ) ;
2022-05-18 05:36:38 +00:00
if ( key . length && value . length ) info [ key ] = value ;
2022-05-20 15:37:00 +00:00
}
info . d = info . d ? . replace ( /-/g , " " ) . replace ( /– /g , "-" ) ;
2022-05-18 05:36:38 +00:00
2022-05-20 15:56:39 +00:00
if ( info . f ) setFavicon ( info . f ) ;
2022-05-18 05:36:38 +00:00
2022-01-29 19:40:35 +00:00
var slashIndex = fragment . indexOf ( "/" ) ;
2022-05-20 15:56:39 +00:00
var title = fragment . substring ( 0 , slashIndex ) || info . title ;
2022-05-17 15:38:05 +00:00
if ( title ) title = decodeURIComponent ( title . replace ( /_/g , " " ) )
var type = undefined ;
var description = undefined ;
document . title = title ? ? location . hostname ;
2018-07-08 15:17:48 +00:00
2022-01-29 19:40:35 +00:00
fragment = fragment . substring ( slashIndex + 1 ) ;
var editable = fragment . charAt ( 0 ) == "?" ;
2022-02-15 23:28:50 +00:00
var link = document . getElementById ( "edit" ) ;
2018-07-08 15:17:48 +00:00
if ( editable ) {
2022-01-29 19:40:35 +00:00
fragment = fragment . substring ( 1 ) ;
2022-02-15 23:28:50 +00:00
document . body . appendChild ( el ( "a" , { id : "edit" , onclick : function ( ) { location . href = "/edit" + location . hash } } ) )
// link.href = "/edit" + location.hash;
2018-07-08 16:18:51 +00:00
}
2022-02-15 23:28:50 +00:00
2022-01-29 19:40:35 +00:00
if ( fragment . startsWith ( "data:" ) ) {
2022-04-28 03:01:03 +00:00
2022-06-30 14:25:05 +00:00
renderer = durl . params ? . render ? { script : durl . params . render , sandbox : "hash" } : renderers [ durl . mediatype ] ;
2022-07-02 21:28:23 +00:00
2022-06-30 14:25:05 +00:00
type = "data:" + durl . mediaype ;
if ( durl . mediatype == "text/html" ) {
dataPrefix = bitty . HEAD _TAGS ( ) ;
} else if ( durl . mediatype == "text/plain" || durl . mediatype == undefined ) {
dataPrefix = bitty . HEAD _TAGS _EXTENDED ( ) ;
durl . mediatype = "text/html" ;
// fragment = fragment.replace("text/plain,", "text/html").replace(",", "text/html");
2022-02-15 23:28:50 +00:00
renderMode = "data" ;
2022-06-30 14:25:05 +00:00
} else if ( durl . type == "text" ) {
} else if ( durl . type == "image" ) {
} else if ( durl . type == undefined ) {
2022-04-28 03:01:03 +00:00
} else if ( ! renderer ) {
2022-02-15 23:28:50 +00:00
console . log ( "unknown type, rendering as download" )
renderMode = "download" ;
2022-01-29 19:40:35 +00:00
}
2022-02-15 23:28:50 +00:00
if ( renderer ) {
2022-06-11 03:48:44 +00:00
var script = renderer . script ;
2022-02-15 23:28:50 +00:00
if ( script . indexOf ( "/" ) == - 1 ) script = location . origin + '/render/' + script + '.js'
renderMode = "script" ;
}
2022-01-29 19:40:35 +00:00
} else {
var colon = fragment . indexOf ( ":" ) ;
2019-03-17 00:14:49 +00:00
if ( colon > 0 && colon < 15 ) {
document . body . classList . remove ( "toasting" ) ;
2022-02-15 23:28:50 +00:00
let scheme = fragment . substring ( 0 , colon ) ;
2022-05-17 15:38:05 +00:00
type = scheme ;
2022-02-15 23:28:50 +00:00
let renderer = renderers [ scheme ] ;
if ( renderer ) {
2022-06-15 14:52:10 +00:00
return renderContentWithScript ( { renderer , title , info , body : fragment , url : fragment } ) ;
2022-02-15 23:28:50 +00:00
}
2022-01-29 19:40:35 +00:00
return window . location . replace ( fragment ) ;
2019-03-17 00:14:49 +00:00
}
2022-02-15 23:28:50 +00:00
2018-07-08 15:17:48 +00:00
var compressed = true ;
2022-06-30 14:25:05 +00:00
dataPrefix = bitty . HEAD _TAGS _EXTENDED ( ) ;
2022-06-09 05:53:37 +00:00
let encoding = ! compressed ? "base64," : ( fragment . startsWith ( "XQA" ) ? bitty . LZMA _MARKER : bitty . GZIP _MARKER ) ;
2022-06-30 14:25:05 +00:00
durl = new bitty . DataURL ( ` data:text/html;charset=utf-8;format= ${ encoding } ;base64, ${ fragment } ` ) ;
2018-07-08 16:18:51 +00:00
}
2022-02-15 23:28:50 +00:00
2018-07-08 15:17:48 +00:00
if ( ( isEdge || isIE ) && location . href . length == 2083 ) {
2022-02-15 23:28:50 +00:00
let element = document . getElementById ( "warning" ) || document . body . appendChild ( el ( "div" , { id : "warning" } ) )
element . innerHTML =
2018-07-08 16:18:51 +00:00
'Edge only supports shorter URLs (maximum 2083 bytes).<br>Larger sites may require a different browser.<br><a href="http://reference.bitty.site">Learn more</a>' ;
}
2022-02-15 23:28:50 +00:00
2022-06-09 05:53:37 +00:00
await durl . decompress ( ) ;
durl . dataPrefix = dataPrefix ;
let dataURL = durl . href ;
let dataContent = durl . rawData ;
2022-06-15 14:52:10 +00:00
if ( ! dataURL ) return ;
iframe . sandbox = "allow-same-origin allow-downloads allow-scripts allow-forms allow-top-navigation allow-popups allow-modals allow-popups-to-escape-sandbox" ;
if ( isIE && renderMode == "data" ) renderMode = "frame" ;
let contentTarget // = iframe.contentWindow.document;
if ( isWatch ) {
console . log ( "Rendering for watch" )
contentTarget = document ;
}
2022-07-02 21:28:23 +00:00
console . log ( "🖋 Rendering mode: " + "\x1B[1m" + renderMode , { url : durl } )
2022-06-15 14:52:10 +00:00
// dataURL = dataURL.replace("application/ld+json", "text/plain");
if ( renderMode == "download" ) {
try {
//let dl = document.querySelector("#download");
let extension = title . split ( "." )
let dl = el ( "a" , { id : "download" , href : dataURL , download : title } ,
el ( "div" , { id : "dl-image" , innerText : extension . pop ( ) ? ? "" } ) ,
el ( "div" , { id : "dl-name" , innerText : "title" } ) ,
el ( "div" , { id : "dl-button" } ) ,
)
document . body . append ( dl )
document . body . classList . add ( "download" ) ;
dl . click ( ) ;
return ;
} catch ( e ) {
console . log ( "DL error" , e )
2022-01-12 14:49:23 +00:00
iframe . src = dataURL ;
2022-06-29 15:34:17 +00:00
showLoader ( false )
2018-07-08 15:17:48 +00:00
}
2022-06-15 14:52:10 +00:00
} else if ( renderMode == "data" ) {
iframe . src = dataURL ;
2022-06-29 15:34:17 +00:00
showLoader ( false )
2022-06-15 14:52:10 +00:00
} else {
bitty . dataToString ( dataURL , function ( content ) {
if ( renderMode == "frame" ) {
writeDocContent ( contentTarget , content )
} else if ( renderMode == "script" ) {
renderContentWithScript ( { renderer , title , info , body : content , url : dataURL , overwrite : contentTarget == document } ) ;
}
} ) ;
2022-06-09 05:53:37 +00:00
}
2022-05-17 15:38:05 +00:00
2022-06-28 15:43:25 +00:00
let recordHistory = true
2022-06-30 14:25:05 +00:00
if ( ! isFramed && recordHistory ) recordToHistory ( durl ) ;
2022-01-29 19:40:35 +00:00
} ;
2022-06-29 15:34:17 +00:00
window . addEventListener ( 'DOMContentLoaded' , renderContent ) ;
window . addEventListener ( 'hashchange' , renderContent ) ;
2022-05-17 15:38:05 +00:00
2022-06-09 05:53:37 +00:00
2022-02-17 17:54:22 +00:00
const SCRIPT _LOADER = ` <!doctype html><meta charset=utf-8><script src=" ${ location . origin } /render.js"></script> `
2022-06-15 14:52:10 +00:00
async function renderContentWithScript ( params ) {
params . script = params . renderer . script ;
params . originalURL = location . href ;
if ( params . script . indexOf ( "/" ) == - 1 ) params . script = location . origin + '/render/' + params . script + '.js'
2022-06-09 05:53:37 +00:00
2022-06-15 14:52:10 +00:00
if ( params . overwrite ) {
// Overwrite the current page with the script. Dangerous, but required for browsers on apple watch to scroll.
2022-06-09 05:53:37 +00:00
let scriptEl = document . createElement ( "script" )
scriptEl . src = "/render.js"
scriptEl . addEventListener ( 'load' , function ( e ) {
console . log ( "Loaded script" , scriptEl . src ) ;
2022-06-15 14:52:10 +00:00
renderScriptContent ( params , "*" ) ;
2022-06-09 05:53:37 +00:00
} ) ;
document . head . appendChild ( scriptEl ) ;
2022-06-15 14:52:10 +00:00
} else {
// Render in an iframe, either via sandboxed subdomain or a data url (disables storage APIs)
2022-06-09 05:53:37 +00:00
iframe . onload = ( ( ) => {
2022-06-15 14:52:10 +00:00
iframe . contentWindow . postMessage ( params , "*" ) ;
2022-06-09 05:53:37 +00:00
delete iframe . onload
2022-06-28 15:43:25 +00:00
iframe . contentWindow . focus ( ) ;
2022-06-29 15:34:17 +00:00
showLoader ( false )
2022-06-09 05:53:37 +00:00
} ) ;
// writeDocContent(iframe.contentWindow.document, SCRIPT_LOADER)
// iframe.srcdoc = SCRIPT_LOADER;
2022-02-15 23:28:50 +00:00
2022-06-17 01:48:41 +00:00
let src = window . scriptDomain ? ? location . origin ;
src += "/render" ;
2022-07-09 15:33:14 +00:00
if ( params . script . endsWith ( ".html" ) ) {
src = params . script ;
}
2022-06-15 14:52:10 +00:00
let sandbox = params . renderer ? . sandbox ;
if ( sandbox == "hash" ) { // Generate sandbox based off of body hash
let hash = await bitty . hashString ( params . body ) ;
src = src . replace ( "https://" , "https://script-" + hash + "." ) ;
} else if ( sandbox ) { // Use named sandbox
src = src . replace ( "https://" , "https://" + sandbox + "." ) ;
} else { // Render using data url (storage disabled)
src = "data:text/html," + SCRIPT _LOADER ;
}
2022-07-02 21:28:23 +00:00
console . log ( "📜 Loading script with source:" , src )
2022-06-15 14:52:10 +00:00
iframe . src = src ;
}
2018-07-08 15:17:48 +00:00
}
2022-05-17 15:38:05 +00:00
2022-06-15 14:52:10 +00:00
function writeDocContent ( doc , content ) {
doc . open ( ) ;
doc . write ( content ) ;
doc . close ( ) ;
}
2022-05-17 15:38:05 +00:00
2022-06-28 15:43:25 +00:00
function extractTerms ( ... args ) {
let wordSet = { }
args . forEach ( ( string ) => {
if ( string ) string . split ( /\s/ ) . forEach ( ( word ) => { if ( word . length > 2 ) wordSet [ word . toLowerCase ( ) ] = true } ) ;
} )
return Object . keys ( wordSet ) ;
}
async function recordToHistory ( ) {
let location = window . location ;
let fragment = location . hash ;
fragment = fragment . substring ( fragment . indexOf ( "/" ) + 1 ) ;
// var slashIndex = fragment.indexOf("/");
// var title = fragment.substring(0, slashIndex) || info.title;
let hash = await bitty . hashString ( fragment ) ;
let durl = new bitty . DataURL ( fragment )
let type = durl . mediatype ;
let metadata = bitty . pathToMetadata ( location . pathname ) ;
if ( ! metadata . title ) {
let dom = await ( await durl . decompress ( ) ) . parseDom ( ) ;
2022-06-30 14:25:05 +00:00
if ( dom ) {
for ( let el of dom . getElementsByTagName ( 'script' ) ) { el . parentNode . removeChild ( el ) }
metadata . title = dom . title ;
metadata . description = dom . body ? . innerText . trim ( ) ;
if ( ! metadata . title . length ) {
metadata . title = ( dom . body ? . children [ 0 ] ? . innerText . trim ( ) ) ? . split ( "\n" ) . pop ( ) ;
}
metadata . description = metadata . description ? . replace ( metadata . title , "" ) . trim ( ) ;
2022-06-29 15:34:17 +00:00
}
2022-06-28 15:43:25 +00:00
2022-07-02 21:28:23 +00:00
console . debug ( "Extracting metadata from content" , metadata ) ;
2022-06-28 15:43:25 +00:00
}
2022-05-17 15:38:05 +00:00
if ( navigator . storage && navigator . storage . persist )
navigator . storage . persist ( ) . then ( granted => {
if ( granted )
2022-06-29 15:34:17 +00:00
console . debug ( "Storage will not be cleared except by explicit user action" ) ;
2022-05-17 15:38:05 +00:00
else
2022-06-29 15:34:17 +00:00
console . debug ( "Storage may be cleared by the UA under storage pressure." ) ;
2022-05-17 15:38:05 +00:00
} ) ;
2022-06-28 15:43:25 +00:00
let openRequest = indexedDB . open ( "history" , 3 ) ;
2022-05-17 15:38:05 +00:00
openRequest . onupgradeneeded = function ( event ) {
2022-06-28 15:43:25 +00:00
console . log ( "Upgrading Database" , event )
2022-05-17 15:38:05 +00:00
const db = event . target . result ;
const transaction = event . target . transaction ;
let objectStore ;
2022-06-28 15:43:25 +00:00
if ( ! db . objectStoreNames . contains ( 'urls' ) ) {
objectStore = db . createObjectStore ( 'urls' , { keyPath : 'id' } ) ;
2022-05-17 15:38:05 +00:00
} else {
2022-06-28 15:43:25 +00:00
objectStore = transaction . objectStore ( 'urls' ) ;
2022-05-17 15:38:05 +00:00
}
objectStore . createIndex ( "created" , "created" ) ;
objectStore . createIndex ( "type" , "type" ) ;
2022-06-28 15:43:25 +00:00
objectStore . createIndex ( "terms" , "terms" , { multiEntry : true } ) ;
2022-05-17 15:38:05 +00:00
} ;
openRequest . onerror = function ( ) {
console . error ( "Error" , openRequest . error ) ;
} ;
openRequest . onsuccess = ( ) => {
let db = openRequest . result ;
2022-06-28 15:43:25 +00:00
let transaction = db . transaction ( "urls" , "readwrite" ) ; // (1)
2022-05-17 15:38:05 +00:00
2022-06-28 15:43:25 +00:00
let history = transaction . objectStore ( "urls" ) ; // (2)
2022-05-17 15:38:05 +00:00
let hashCode = s => s . split ( '' ) . reduce ( ( a , b ) => { a = ( ( a << 5 ) - a ) + b . charCodeAt ( 0 ) ; return a & a } , 0 )
2022-06-28 15:43:25 +00:00
let terms = extractTerms ( metadata . title , metadata . description ) ;
2022-05-17 15:38:05 +00:00
let entry = {
2022-06-28 15:43:25 +00:00
id : hash ,
2022-05-17 15:38:05 +00:00
url : location . href ,
2022-06-28 15:43:25 +00:00
title : metadata . title || '' ,
text : metadata . description ? . substring ( 0 , 256 ) ,
type : type ,
terms : terms ,
2022-05-17 15:38:05 +00:00
created : new Date ( )
} ;
2022-07-02 21:28:23 +00:00
console . log ( "🕙 Adding history" , { entry } )
2022-06-28 15:43:25 +00:00
let request = history . put ( entry ) ; // (3)
2022-05-17 15:38:05 +00:00
request . onsuccess = function ( ) { // (4)
2022-07-02 21:28:23 +00:00
console . debug ( "entry added to the history" , request . result ) ;
2022-05-17 15:38:05 +00:00
} ;
request . onerror = function ( ) {
console . log ( "Error" , request . error ) ;
} ;
// continue working with database using db object
} ;
}