Last active
December 21, 2024 20:04
-
-
Save soundyogi/03df95505604c8351212 to your computer and use it in GitHub Desktop.
A snippet to export and import your chrome snippets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void function() { "use strict" | |
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WIP DO NOT USE WIP !!!!!!!!!!!!!!!!!!!!! | |
DO NOT USE THIS YET. | |
USE THE 2016 VERSION BELOW PLEASE. | |
WWWWWWWW WWWWWWWWIIIIIIIIIIPPPPPPPPPPPPPPPPP | |
W::::::W W::::::WI::::::::IP::::::::::::::::P | |
W::::::W W::::::WI::::::::IP::::::PPPPPP:::::P | |
W::::::W W::::::WII::::::IIPP:::::P P:::::P | |
W:::::W WWWWW W:::::W I::::I P::::P P:::::P | |
W:::::W W:::::W W:::::W I::::I P::::P P:::::P | |
W:::::W W:::::::W W:::::W I::::I P::::PPPPPP:::::P | |
W:::::W W:::::::::W W:::::W I::::I P:::::::::::::PP | |
W:::::W W:::::W:::::W W:::::W I::::I P::::PPPPPPPPP | |
W:::::W W:::::W W:::::W W:::::W I::::I P::::P | |
W:::::W:::::W W:::::W:::::W I::::I P::::P | |
W:::::::::W W:::::::::W I::::I P::::P | |
W:::::::W W:::::::W II::::::IIPP::::::PP | |
W:::::W W:::::W I::::::::IP::::::::P | |
W:::W W:::W I::::::::IP::::::::P | |
WWW WWW IIIIIIIIIIPPPPPPPPPP | |
* Manage and Import/Export Chrome Snippets (2018) | |
* by: http://github.com/soundyogi | |
* inspired by: https://github.com/bgrins/devtools-snippets/blob/master/import-export/chrome/devtools_import_export.js | |
*/ | |
// - Templates | |
// - Test Harness | |
// - Diy Redux | |
// - Main | |
// - Util | |
// - CSS | |
// Templates | |
// | |
function Layout({getState}){ return ` | |
<article> | |
<header><h1>Chrome Export</h1></header> | |
${sideMenu({getState})} | |
<main> | |
<h2>Current snippets buffer / state / preview: </h2> | |
${getState().scriptSnippets.forEach((snippet) => { | |
return ` | |
<li>${snippet}</li> | |
`})} | |
</main> | |
${outMenu({getState})} | |
<footer></footer> | |
</article> | |
`} | |
function sideMenu({getState}) { return ` | |
<aside> | |
<nav> | |
<h3>--> Input</h3> | |
<ul> | |
<li> | |
<label> load chrome snippets: </label> | |
<button id=${uuidv4()} onclick='dispatch(events.snippetsFetchRequested())'> (re)init </button> | |
</li> | |
<li> | |
<label> on name conflicts: </label> | |
<select onchange='( x => {console.log(x,event); dispatch(events.snippetsFetchRequested(event))} )()' id='rename'> | |
<option value='true'>Rename Import Files</option> | |
<option value="false">Overwrite Snippets</option> | |
</select> | |
</li> | |
<li> | |
<dropzone> | |
<div>Click/Drop .js or .json</div> | |
<input id="drop_files" type='file' multiple='true'/> | |
</dropzone> | |
<label>append files or replace everything? | |
<select id='append'> | |
<option value='true'>Append</option> | |
<option value="false">Replace</option> | |
</select> | |
</label> | |
</li> | |
<li> | |
import files from external sources: | |
<button id="external_bgrins">load some scripts from bgrins/devtools-snippets repo</button> | |
<button id="external_bahmutov">load some scripts from bahmutov/code-snippets repo</button> | |
</li> | |
</ul> | |
</nav> | |
</aside> | |
`}; | |
function outMenu({getState}){ return ` | |
<out> | |
<nav> | |
<h3>Output --></h3> | |
<ul> | |
<li> | |
<button id="export_snippets">export</button> | |
<select id='format'> | |
<option value="json">Single .json</option> | |
<option value="js">Multiple .js</option> | |
</select> | |
</li> | |
<li> | |
<button id="save_snippets">Save to Chrome</button> | |
</li> | |
<li> | |
<button id="reset_snippets">DELETE all on Chrome</button> | |
</li> | |
</ul> | |
</nav> | |
</out> | |
`} | |
// Test Harness | |
// | |
function log(...x) { | |
return console.log(...x) | |
} | |
function test(suiteName, f) { | |
log(`Test: ${suiteName}`) | |
f({ok}) | |
} | |
function ok(expr, msg) { | |
expr ? log(' %c!pass:' + msg, 'color:green') : log(' %c?fail:' + msg, 'color:red') | |
} | |
// INIT TEST | |
test('selftest', function(t) { | |
t.ok(true, ' I pass') | |
t.ok(false, 'I fail') | |
}) | |
test("are we inspecting devtools?", ()=>{ | |
if (location.origin !== "chrome-devtools://devtools") | |
console.log("not in devtools of devtools / please inspect devtools again with: (ctrl+shift+i)") | |
ok(location.origin === "chrome-devtools://devtools", 'we are in devtools of devtools, good to go') | |
}) | |
// Naive Redux | |
// | |
function createStore(rootReducer, initialState, storeEnhancer) { | |
const createStore = storeEnhancer | |
? storeEnhancer(_createStore) | |
: _createStore | |
; | |
return createStore(); | |
function _createStore() { | |
if (!rootReducer) throw Error('rootReducer is missing') | |
const _mapSubscribers = {} | |
const _rootReducer = rootReducer | |
const _store = { | |
dispatch: baseDispatch, | |
getState, | |
subscribe | |
} | |
let _state = initialState | |
return _store; | |
function getState() { | |
return _state | |
} | |
function subscribe(f) { | |
_mapSubscribers[uuidv4()] = f | |
} | |
function baseDispatch(action) { | |
if (!action || !action.type) throw Error("cant call dispatch without action. stupid."); | |
_state = _rootReducer(_state, action) | |
for (var subscriberKey in _mapSubscribers) | |
_mapSubscribers[subscriberKey] ? _mapSubscribers[subscriberKey]() : null; | |
return true; | |
} | |
} | |
} | |
function applyMiddleware(...middlewares) { | |
return createStore => (...args) => { | |
const store = createStore(...args) | |
let chain = [] | |
let dispatch | |
const middlewareAPI = { | |
getState: store.getState, | |
dispatch: (...args) => dispatch(...args) | |
} | |
chain = middlewares.map(middleware => middleware(middlewareAPI)) | |
dispatch = compose(...chain)(store.dispatch) | |
return { | |
...store, | |
dispatch | |
} | |
} | |
} | |
// Middleware | |
// | |
const logger = store => next => action => { | |
if(!action.type && action instanceof Function) console.log('thunk: '+action.name) | |
else { console.info('event: ', action) } | |
let result = next(action) | |
return result | |
} | |
const crashReporter = store => next => action => { | |
try { | |
return next(action) | |
} catch (err) { | |
console.error('Caught an exception!', err) | |
throw err | |
} | |
} | |
const vanillaPromise = store => next => action => { | |
if (typeof action.then !== 'function') { | |
return next(action) | |
} | |
return Promise.resolve(action).then(store.dispatch) | |
} | |
const thunk = store => next => action => | |
typeof action === 'function' | |
? action(store.dispatch, store.getState) | |
: next(action) | |
/* | |
function combineReducers(reducerObject:Object):function{} | |
Combines Reducers by returning a Reducer Reducing Reducers | |
*/ | |
function combineReducers(reducerObject){ | |
function rootReducer(state, action){ | |
const newState = {} | |
Object.keys(reducerObject).reduce( (newState, currentKey) => { | |
if(!state) state = {} | |
// if(!state[currentKey]) state[currentKey] = undefined; | |
newState[currentKey] = reducerObject[currentKey](state[currentKey], action) | |
return newState | |
}, newState) | |
return newState | |
} | |
return rootReducer | |
} | |
// Snippets 'Duck' | |
// | |
// Actions | |
// | |
const SNIPPETS_FETCH_REQUESTED = 'SNIPPETS_FETCH_REQUESTED' | |
const SNIPPETS_FETCHED = 'SNIPPETS_FETCHED' | |
const SNIPPET_ADDED = 'SNIPPET_ADDED' | |
const SNIPPET_REMOVED = 'SNIPPET_REMOVED' | |
// Action Creators / Thunk Creators | |
// | |
function snippetsFetchRequested(){ | |
return function snippetsFetchRequestedThunk(dispatch, getState){ | |
dispatch({type: SNIPPETS_FETCH_REQUESTED}) | |
InspectorFrontendHost.getPreferences(prefs=>{ | |
const lastScriptSnippets = prefs.scriptSnippets | |
const snippets = deserialize(lastScriptSnippets) | |
const lastIdentifier = prefs.scriptSnippets_lastIdentifier | |
dispatch(snippetsFetched({snippets, lastIdentifier})) | |
}) | |
} | |
} | |
function snippetsFetched(payload){ | |
return {type: SNIPPETS_FETCHED, payload} | |
} | |
function snippetAdded(){} | |
function snippetRemoved(){} | |
const actionCreators = { | |
snippetsFetchRequested, | |
snippetsFetched, | |
} | |
function import_files(event){ | |
if(!state.gui_switches.append) state.scriptSnippets = [] | |
const files = event.target.files | |
const stack = Object.keys(files) | |
.forEach((key)=>{ | |
const file = files[key] | |
const reader = new FileReader() | |
reader.fileName = file.name | |
reader.onerror = (()=> {throw Error}) | |
reader.onabort = (()=> {throw Error}) | |
reader.onload = file_loaded | |
reader.readAsText(file) | |
}) | |
function file_loaded(event){ | |
const content_string = event.target.result | |
const fileName = event.target.fileName | |
const fileNameNoExt = /(.+?)(\.[^.]*$|$)/.exec(fileName)[1] | |
const ext = /\.[0-9a-z]+$/.exec(fileName)[0] | |
if(ext === ".json") return import_json(content_string) | |
return add_snippet(fileNameNoExt, content_string) | |
} | |
} | |
function import_json(content_string){ | |
var json_data = deserialize(content_string) | |
json_data.snippets.forEach(snippet => { | |
add_snippet(snippet.name, snippet.content) | |
}) | |
} | |
function set_pref(name, data_string){ | |
InspectorFrontendHost.setPreference(name, data_string) | |
} | |
function save_snippets(){ | |
set_pref( "scriptSnippets", serialize(state.scriptSnippets) ) | |
set_pref( "scriptSnippets_lastIdentifier", state.lastIdentifier) | |
prompt('restart chrome now!') | |
} | |
function reset_snippets(){ | |
var choice = window.confirm("DELETE ALL SNIPPETS IN DEVTOOLS?") | |
if(choice) clear_chrome_snippets() | |
init() | |
} | |
function clear_chrome_snippets(){ | |
set_pref("scriptSnippets", "[]") | |
set_pref("scriptSnippets_lastIdentifier", "0") | |
} | |
function add_snippet(name, snippet_content_string){ | |
if(is_duplicate(name, state.scriptSnippets)) { | |
if(!state.gui_switches.rename) return state.scriptSnippets[name] = snippet_content_string | |
return add_snippet(name+"copy", snippet_content_string) | |
} | |
const currentIdentifier = serialize(parseInt(state.lastIdentifier)+1) | |
const new_snip = { | |
content: snippet_content_string, | |
id: currentIdentifier, | |
name: name | |
} | |
state.scriptSnippets.push( new_snip ) | |
state.lastIdentifier = currentIdentifier | |
update() | |
} | |
function external_bgrins(){ | |
const brings_snippets = [ | |
'allcolors', | |
'cachebuster', | |
'cssreload', | |
'cssprettifier', | |
'hashlink' | |
] | |
brings_snippets.forEach((snippet)=>{ | |
request('https://raw.githubusercontent.com/bgrins/devtools-snippets/master/snippets/'+snippet+'/'+snippet+'.js', function(request){ | |
const snippet_content_string = request.target.response | |
add_snippet(snippet, snippet_content_string) | |
}) | |
}) | |
} | |
function external_bahmutov(){ | |
const bahmutov_snippets = [ | |
'timing', | |
'profile-method-call', | |
'time-method-call' | |
] | |
bahmutov_snippets.forEach((snippet)=>{ | |
request('https://raw.githubusercontent.com/bahmutov/code-snippets/master/'+snippet+'.js', function(request){ | |
const snippet_content_string = request.target.response | |
add_snippet(snippet, snippet_content_string) | |
}) | |
}) | |
} | |
function export_snippets(){ | |
if(state.gui_switches.format === "json") return download_json() | |
return download_js() | |
} | |
function download_js(){ | |
state.scriptSnippets.forEach((snippet)=>{ | |
download(snippet.name+'.js', snippet.content) | |
}) | |
} | |
function download_json(){ | |
console.log("json") | |
const fileName = serialize(Date()) | |
const json_data = serialize({'snippets': state.scriptSnippets}, ['snippets', 'name', 'content'], 2) | |
download(fileName+".json", json_data) | |
} | |
// Reducer | |
// | |
const snippetsShape = { | |
scriptSnippets: [], | |
lastIdentifier: 0, | |
//ui | |
rename: true, | |
format: 'json', | |
review: false, | |
append: true | |
} | |
function snippetsReducer(state = snippetsShape, {TYPE, PL}) { | |
if(TYPE === SNIPPETS_FETCHED) return {...state, scriptSnippets: PL.snippets} | |
return state | |
} | |
// Main logic | |
// | |
const app_window = createWindow("menubar=false, width=1024, height=768", "Chrome Snippets Import/Export/Manager") | |
const store = createStore(snippetsReducer, undefined, applyMiddleware(logger,thunk,vanillaPromise,crashReporter)) | |
app_window.dispatch = store.dispatch | |
app_window.getState = store.getState | |
app_window.events = actionCreators | |
app_window.document.head.innerHTML = style(); | |
store.subscribe(function(){ | |
// console.log(JSON.stringify(store.getState())) | |
render(app_window.document.body, Layout) | |
}) | |
store.dispatch({type: 'first', payload: Date.now()}) | |
// UTIL | |
// | |
function render(mountNode, template){ | |
mountNode.innerHTML = template({getState: store.getState}); | |
} | |
function compose(...funcs) { | |
if (funcs.length === 0) { | |
return arg => arg | |
} | |
if (funcs.length === 1) { | |
return funcs[0] | |
} | |
return funcs.reduce((a, b) => (...args) => a(b(...args))) | |
} | |
function uuidv4() { | |
// RFC4122 version 4 compliant | |
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | |
var r = Math.random() * 16 | 0 | |
, v = c == 'x' ? r : (r & 0x3 | 0x8); | |
return v.toString(16); | |
}); | |
} | |
function request(url, success) { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', url); | |
xhr.onload = success; | |
xhr.send(); | |
return xhr; | |
} | |
function serialize(object, ...rest) { | |
if (!object) throw Error("serialize needs input") | |
return JSON.stringify(object, ...rest) | |
} | |
function deserialize(string) { | |
if (typeof string !== "string") throw Error("deserialize needs a string") | |
if (string === "") throw Error("no snippets present") | |
return JSON.parse(string) | |
} | |
function download(name, data) { | |
const Blob = new window.Blob([data],{ 'type': 'text/utf-8' }) | |
const a = app_window.document.createElement('a') | |
a.href = URL.createObjectURL(Blob) | |
a.download = name | |
a.click() | |
} | |
function is_duplicate(name, snippets_arr) { | |
const result = snippets_arr.filter(function(snippet) { | |
return snippet.name === name | |
}) | |
if (result.length === 0) return false | |
return true | |
} | |
function createWindow(options, title) { | |
const w = window.open("", "", options) | |
w.document.title = title | |
return w | |
} | |
// CSS | |
// | |
function style() { return ` | |
<style> | |
body { | |
font-family: 'Open Sans', sans-serif; | |
} | |
article { | |
display: grid; | |
grid-template-columns: auto minmax(min-content, 1fr); | |
grid-template-rows: auto minmax(min-content, 1fr) auto; | |
max-width: 800px; | |
margin: 0 auto; | |
} | |
header { | |
grid-column: 1 / span 3; | |
grid-row: 1; | |
} | |
aside { | |
grid-column: 1; | |
grid-row: 2; | |
background-color: #F0F0F2; | |
padding: 5px 10px; | |
} | |
out { | |
grid-column: 3; | |
grid-row: 2; | |
background-color: #F0F0F2; | |
padding: 5px 10px; | |
} | |
main { | |
grid-column: 2; | |
grid-row: 2; | |
align-self: start; | |
margin-left: 18px; | |
} | |
footer { | |
grid-column: 1 / span 2; | |
grid-row: 3; | |
background-color: #474F59; | |
margin-top: 20px; | |
padding: 5px 10px; | |
color: white; | |
margin-bottom: 20px; | |
} | |
#drop_files { | |
opacity: 0; | |
width: 100%; | |
height: 20vh; | |
} | |
dropzone { | |
cursor: pointer; | |
border: 1px black dotted; | |
font-weight: bold; | |
font-size: 1em; | |
text-align: center; | |
} | |
</style> | |
` | |
} | |
}("live long and prosper"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void function(){ | |
"use strict" | |
/* | |
222222222222222 000000000 1111111 66666666 | |
2:::::::::::::::22 00:::::::::00 1::::::1 6::::::6 | |
2::::::222222:::::2 00:::::::::::::00 1:::::::1 6::::::6 | |
2222222 2:::::2 0:::::::000:::::::0111:::::1 6::::::6 | |
2:::::2 0::::::0 0::::::0 1::::1 6::::::6 | |
2:::::2 0:::::0 0:::::0 1::::1 6::::::6 | |
2222::::2 0:::::0 0:::::0 1::::1 6::::::6 | |
22222::::::22 0:::::0 000 0:::::0 1::::l 6::::::::66666 | |
22::::::::222 0:::::0 000 0:::::0 1::::l 6::::::::::::::66 | |
2:::::22222 0:::::0 0:::::0 1::::l 6::::::66666:::::6 | |
2:::::2 0:::::0 0:::::0 1::::l 6:::::6 6:::::6 | |
2:::::2 0::::::0 0::::::0 1::::l 6:::::6 6:::::6 | |
2:::::2 2222220:::::::000:::::::0111::::::1116::::::66666::::::6 | |
2::::::2222222:::::2 00:::::::::::::00 1::::::::::1 66:::::::::::::66 | |
2::::::::::::::::::2 00:::::::::00 1::::::::::1 66:::::::::66 | |
22222222222222222222 000000000 111111111111 666666666 | |
* Manage and Import / Export snippets from chrome (2016) | |
* hacked together by: http://github.com/soundyogi | |
* inspired by: https://github.com/bgrins/devtools-snippets/blob/master/import-export/chrome/devtools_import_export.js | |
* ALPHA / SILLY SIDE PROJECT | |
*/ | |
let_us("execute some init tests", () => { | |
if(location.origin !== "chrome-devtools://devtools") throw Error("not in devtools of devtools / please inspect devtools again (ctrl+shift+i)") | |
ok(location.origin === "chrome-devtools://devtools", 'we are in devtools of devtools, good to go') | |
}) | |
const state = { | |
scriptSnippets: [], | |
} | |
window.state = state | |
const style = ` | |
<style> | |
body{ | |
margin: 0; | |
padding: 0; | |
} | |
grid { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
-webkit-flex-flow: column; | |
} | |
column { | |
display: flex; | |
-webkit-flex-flow: column; | |
width: 30vw; | |
} | |
row { | |
display: flex; | |
-webkit-flex-flow: row; | |
width: 90vw; | |
margin-bottom: 2vh; | |
} | |
item { | |
background: tomato; | |
min-height: 13vh; | |
color: white; | |
font-weight: bold; | |
font-size: 1.5em; | |
text-align: center; | |
padding: 20px; | |
} | |
#drop_files { | |
opacity: 0; | |
width: 100%; | |
height: 20vh; | |
} | |
dropzone { | |
cursor: pointer; | |
border: 1px black dotted; | |
font-weight: bold; | |
font-size: 1em; | |
text-align: center; | |
} | |
</style> | |
` | |
const markup = ` | |
<grid> | |
<row> | |
<column> | |
<item> load chrome snippets: | |
<button id="init">(re)init</button> | |
</item> | |
</column> | |
<column> | |
<item> | |
<label>on name conflicts: | |
<select id='rename'> | |
<option value='true'>Rename Import Files</option> | |
<option value="false">Overwrite Snippets</option> | |
</select> | |
</label> | |
</item> | |
</column> | |
<column> | |
<item> | |
<button id="export_snippets">export</button> | |
<select id='format'> | |
<option value="json">Single .json</option> | |
<option value="js">Multiple .js</option> | |
</select> | |
</item> | |
</column> | |
<column> | |
<item> | |
<button id="save_snippets">Save to Chrome</button> | |
</item> | |
</column> | |
<column> | |
<item> | |
<button id="reset_snippets">DELETE all on Chrome</button> | |
</item> | |
</column> | |
</row> | |
<row> | |
<column> | |
<dropzone> | |
<div>Click/Drop .js or .json</div> | |
<input id="drop_files" type='file' multiple='true'/> | |
</dropzone> | |
<label>append files or replace everything? | |
<select id='append'> | |
<option value='true'>Append</option> | |
<option value="false">Replace</option> | |
</select> | |
</label> | |
</column> | |
<column>===== snippets preview =====<ul id="state.scriptSnippets"></ul></column> | |
<column>import files from external sources: | |
<button id="external_bgrins">load some scripts from bgrins/devtools-snippets repo</button> | |
<button id="external_bahmutov">load some scripts from bahmutov/code-snippets repo</button> | |
</column> | |
</row> | |
</grid> | |
` | |
/* Main logic | |
*/ | |
const app_window = create_window("menubar=false, height=700, width=1000", "chrome snippets import/export - ALPHA USE AT OWN RISK") | |
const document = app_window.document | |
let_us("bootstrap the whole thing", () => { | |
init() | |
}) | |
function init(){ | |
setupGUI() | |
state.scriptSnippets = [] | |
state.lastIdentifier = 0 | |
state.gui_switches = { | |
rename: true, | |
format: "json", | |
review: false, | |
append: true | |
} | |
InspectorFrontendHost.getPreferences( prefs => { | |
const lastScriptSnippets = prefs.scriptSnippets | |
state.scriptSnippets = deserialize(lastScriptSnippets) | |
state.lastIdentifier = prefs.scriptSnippets_lastIdentifier | |
update() | |
}) | |
} | |
function setupGUI(){ | |
app_window.document.body.innerHTML = style+markup | |
getID("format").on("change", handle_gui_switches) | |
getID("rename").on("change", handle_gui_switches) | |
getID("append").on("change", handle_gui_switches) | |
getID("drop_files").on("change", import_files) | |
getID("export_snippets").on("click", export_snippets) | |
getID("init").on("click", init) | |
getID("save_snippets").on("click", save_snippets) | |
getID("reset_snippets").on("click", reset_snippets) | |
getID("external_bgrins").on("click", external_bgrins) | |
getID("external_bahmutov").on("click", external_bahmutov) | |
} | |
function handle_gui_switches(ev){ | |
const target = ev.target | |
const opt = state.gui_switches | |
if(target.id === 'format') { | |
opt.format = target.value | |
return update() | |
} | |
if(target.id === 'rename') { | |
opt.rename = !target.value | |
return update() | |
} | |
if(target.id === 'review') { | |
opt.review = !opt.review | |
return update() | |
} | |
if(target.id === 'append') { | |
opt.append = !target.value | |
return update() | |
} | |
} | |
function update(){ | |
render_list() | |
console.log(state.gui_switches) | |
} | |
function render_list(){ | |
const ul = app_window.document.getElementById("state.scriptSnippets") | |
ul.innerHTML = '' | |
state.scriptSnippets.forEach((snippet)=>{ | |
const li = document.createElement('li') | |
//const a = document.createElement('a') | |
//a.href = snippet.name | |
li.innerHTML = snippet.name | |
//li.appendChild(a) | |
ul.appendChild(li) | |
}) | |
} | |
/* Helpers | |
*/ | |
function import_files(event){ | |
if(!state.gui_switches.append) state.scriptSnippets = [] | |
const files = event.target.files | |
const stack = Object.keys(files) | |
.forEach((key)=>{ | |
const file = files[key] | |
const reader = new FileReader() | |
reader.fileName = file.name | |
reader.onerror = (()=> {throw Error}) | |
reader.onabort = (()=> {throw Error}) | |
reader.onload = file_loaded | |
reader.readAsText(file) | |
}) | |
} | |
function file_loaded(event){ | |
const content_string = event.target.result | |
const fileName = event.target.fileName | |
const fileNameNoExt = /(.+?)(\.[^.]*$|$)/.exec(fileName)[1] | |
const ext = /\.[0-9a-z]+$/.exec(fileName)[0] | |
if(ext === ".json") return import_json(content_string) | |
return add_snippet(fileNameNoExt, content_string) | |
} | |
function import_json(content_string){ | |
var json_data = deserialize(content_string) | |
json_data.snippets.forEach(snippet => { | |
add_snippet(snippet.name, snippet.content) | |
}) | |
} | |
function set_pref(name, data_string){ | |
InspectorFrontendHost.setPreference(name, data_string) | |
} | |
function save_snippets(){ | |
set_pref( "scriptSnippets", serialize(state.scriptSnippets) ) | |
set_pref( "scriptSnippets_lastIdentifier", state.lastIdentifier) | |
prompt('restart chrome now!') | |
} | |
function reset_snippets(){ | |
var choice = window.confirm("DELETE ALL SNIPPETS IN DEVTOOLS?") | |
if(choice) clear_chrome_snippets() | |
init() | |
} | |
function clear_chrome_snippets(){ | |
set_pref("scriptSnippets", "[]") | |
set_pref("scriptSnippets_lastIdentifier", "0") | |
} | |
function add_snippet(name, snippet_content_string){ | |
if(is_duplicate(name, state.scriptSnippets)) { | |
if(!state.gui_switches.rename) return state.scriptSnippets[name] = snippet_content_string | |
return add_snippet(name+"copy", snippet_content_string) | |
} | |
const currentIdentifier = serialize(parseInt(state.lastIdentifier)+1) | |
const new_snip = { | |
content: snippet_content_string, | |
id: currentIdentifier, | |
name: name | |
} | |
state.scriptSnippets.push( new_snip ) | |
state.lastIdentifier = currentIdentifier | |
update() | |
} | |
function external_bgrins(){ | |
const brings_snippets = [ | |
'allcolors', | |
'cachebuster', | |
'cssreload', | |
'cssprettifier', | |
'hashlink' | |
] | |
brings_snippets.forEach((snippet)=>{ | |
request('https://raw.githubusercontent.com/bgrins/devtools-snippets/master/snippets/'+snippet+'/'+snippet+'.js', function(request){ | |
const snippet_content_string = request.target.response | |
add_snippet(snippet, snippet_content_string) | |
}) | |
}) | |
} | |
function external_bahmutov(){ | |
const bahmutov_snippets = [ | |
'timing', | |
'profile-method-call', | |
'time-method-call' | |
] | |
bahmutov_snippets.forEach((snippet)=>{ | |
request('https://raw.githubusercontent.com/bahmutov/code-snippets/master/'+snippet+'.js', function(request){ | |
const snippet_content_string = request.target.response | |
add_snippet(snippet, snippet_content_string) | |
}) | |
}) | |
} | |
function export_snippets(){ | |
if(state.gui_switches.format === "json") return download_json() | |
return download_js() | |
} | |
function download_js(){ | |
state.scriptSnippets.forEach((snippet)=>{ | |
download(snippet.name+'.js', snippet.content) | |
}) | |
} | |
function download_json(){ | |
console.log("json") | |
const fileName = serialize(Date()) | |
const json_data = serialize({'snippets': state.scriptSnippets}, ['snippets', 'name', 'content'], 2) | |
download(fileName+".json", json_data) | |
} | |
/* util & shorthand | |
*/ | |
function request(url, success) { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', url); | |
xhr.onload = success; | |
xhr.send(); | |
return xhr; | |
} | |
function getID(id){ | |
const element = app_window.document.getElementById(id) | |
element.on = function on(event_name, fn){ | |
this.addEventListener(event_name, fn) | |
return this | |
} | |
return element | |
} | |
function serialize(object, ...rest){ | |
if(!object) throw Error("serialize needs an object") | |
return JSON.stringify(object, ...rest) | |
} | |
function deserialize(string){ | |
if(typeof string !== "string") throw Error("deserialize needs a string") | |
if(string === "") throw Error("no snippets present") | |
return JSON.parse(string) | |
} | |
function download(name, data){ | |
const Blob = new window.Blob([data],{ | |
'type': 'text/utf-8' | |
}) | |
const a = document.createElement('a') | |
a.href = URL.createObjectURL(Blob) | |
a.download = name | |
a.click() | |
} | |
function is_duplicate(name, snippets_arr){ | |
const result = snippets_arr.filter(function(snippet){ | |
return snippet.name === name | |
}) | |
if(result.length === 0) return false | |
return true | |
} | |
function create_window(options, title){ | |
const w = window.open("", "", options) | |
w.document.title = title | |
return w | |
} | |
/* | |
* UNIT TESTS | |
*/ | |
let_us("write some tests", ()=>{ | |
// TODO | |
// TDD tests are deleted now / remove harness | |
}) | |
/* Nanoharness | |
*/ | |
function let_us(msg,f){ | |
console.log("we_will: "+msg) | |
try { f() } | |
catch (exception) { | |
console.warn(exception.stack.replace(/:(\d+):(\d+)/g, "$& (Line $1, Column $2)")) | |
} | |
} | |
function ok(expr, msg){ | |
log(expr, msg) | |
} | |
function log(expr, msg){ | |
expr ? console.log("!pass "+msg) : console.log("?fail "+msg) | |
} | |
function html_log(){ | |
const queue = [] | |
return function log(expr, msg) { | |
queue.push( expr ? `!pass ${msg}` : `?fail ${msg}` ) | |
} | |
} | |
}("goodbye and thanks for all the fish") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great work