Skip to content

Instantly share code, notes, and snippets.

@soundyogi
Last active December 24, 2023 22:09
Show Gist options
  • Save soundyogi/03df95505604c8351212 to your computer and use it in GitHub Desktop.
Save soundyogi/03df95505604c8351212 to your computer and use it in GitHub Desktop.
A snippet to export and import your chrome snippets
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");
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")
@soundyogi
Copy link
Author

Open Inspector (ctrl+shift+I)
Undock Inspector in Seperate Window
Inspect Inspector (ctrl+shift+i)
Paste Script Into Console:

impoexpo

@arangates
Copy link

Great work 👍

@ptim
Copy link

ptim commented Aug 8, 2017

👍

@soundyogi
Copy link
Author

soundyogi commented Aug 14, 2017

thanks, now I hopefully have the motivation to finish it and make it a "full" snippets manager.
Id love to store them somewhere online instead of .json, I still keep losing scripts.
And more than 50+ Scripts are very unmanagable still right now.

@alexnoz
Copy link

alexnoz commented Mar 5, 2018

This is awesome, thank you 👏

@soundyogi
Copy link
Author

the new version is still in progress, please use the 2016 one until it is finished.

@Enissay
Copy link

Enissay commented Dec 27, 2018

2016 is no more working :'(

@soundyogi
Copy link
Author

Really? Oh no :O !!!
Let me get back to you soon...

@mthompson
Copy link

@Enissay

Using version 2016, try changing function create_window to the following:

function create_window(options, title){
  var id = (new Date()).getTime();
  const w = window.open('' , id, options);
  w.document.title = title
  return w
}

I hope this helps.

@soundyogi
Copy link
Author

soundyogi commented Mar 2, 2019

2016 is no more working :'(

Did you inpect the inpector window?

You have to open inspector: ctrl+shift+i
Then undock it in a single window

Then again: ctrl+shift+i

Now paste the manager, does it work?

I will try to finish the new one soon

@Niscolinx
Copy link

Thanks a lot, great work

@ask1234560
Copy link

Great work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment