Stylash- A live CSS editor bookmarklet



Features:

  • Autosave
  • Beautify
  • Save to file
  • Live preview (+toggle on an off)

image
image

Installation:

Select all of this and put it into a bookmark (you’re a developer, you should know this)

javascript:(() => {let height="100px",font="Montserrat",html=`\n<title>Style editor</title>\n<script src="https://cdn.jsdelivr.net/npm/[email protected]"><\/script>\n<script src=https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/ace.js><\/script>\n<script>window.define = ace.define;<\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/keybinding-vscode.min.js"><\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/mode-less.min.js"><\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.14/ext-language_tools.min.js"><\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ext-beautify.js"><\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify.min.js"><\/script>\n<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.0/beautify-css.min.js"><\/script>\n<div id="top">\n    <h1>Style editor</h1>\n    <label><input type="checkbox" id="live" name="live" checked> Enable live update</label>\n    <div id="buttons">\n        <button id="beautify" onclick="beautify()">Beautify</button>\n        <button id="save" onclick="save()">Save to file</button>\n        <button id="copy" onclick="copy()">Copy</button>\n        <button id="compile" onclick="compile()">Compile to CSS</button>\n    </div>\n</div>\n<div id=editor></div>\n<style>\[email protected] url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,[email protected],200;0,300;0,400;0,500;1,200;1,300;1,400&family=Work+Sans:[email protected]&display=swap');\[email protected] url('https://fonts.googleapis.com/css2?family=${font.replace(/ /g,"+")}');\n\n* {\n    margin: 0;\n    padding: 0;\n}\n#editor, #editor *, .ace_tooltip {\n    font-family: "Source Code Pro", monospace;\n}\n\n#buttons button {\n    padding: 5px 10px;\n    border: 1px solid #45f4;\n    background: #45f1;\n    color: white;\n    border-radius: 3px;\n    cursor: pointer;\n    transition: all .2s ease;\n}\n#buttons button:hover {\n    background: #45f3;\n}\n#buttons button:active {\n    transform: scale(.9);\n}\n#top {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    color: #eee;\n    background: #333;\n    height: ${height};\n    flex-direction: column;\n    font-family: '${font}', sans-serif;\n}\n  #editor {position: absolute; top: ${height}; bottom: 0; left: 0; right: 0}\n</style>\n<script>\nconst $ = (a) => document.querySelector(a);\nlet placeholder = "Write CSS here! Any edits will update the main page in real time. They are also saved in localStorage";\nvar langTools = ace.require("ace/ext/language_tools");\nvar editor = ace.edit("editor");\neditor.setTheme("ace/theme/monokai");\neditor.session.setMode("ace/mode/less");\neditor.setShowPrintMargin(false);\neditor.setOptions({\n    enableBasicAutocompletion: true,\n    enableSnippets: true,\n    enableLiveAutocompletion: true,\n    placeholder,\n});\n\neditor.setValue(localStorage.style_bookmarklet_style || ${JSON.stringify(localStorage.style_bookmarklet_style||"")})\n\nfunction update() {\n    setStyle(editor.session.getValue())\n    var shouldShow = !editor.session.getValue().length;\n    var node = editor.renderer.emptyMessageNode;\n    if (!shouldShow && node) {\n        editor.renderer.scroller.removeChild(editor.renderer.emptyMessageNode);\n        editor.renderer.emptyMessageNode = null;\n    } else if (shouldShow && !node) {\n        node = editor.renderer.emptyMessageNode = document.createElement("div");\n        node.textContent = placeholder;\n        node.className = "ace_emptyMessage"\n        node.style.padding = "0 9px"\n        node.style.position = "absolute"\n        node.style.zIndex = 9\n        node.style.opacity = 0.5\n        editor.renderer.scroller.appendChild(node);\n    }\n}\neditor.on("input", update);\nsetTimeout(update, 100);\n\nasync function setStyle(code){\n    if (!$("#live").checked){return}\n    localStorage.setItem("style_bookmarklet_style", code);\n    let w = window.opener;\n    w.postMessage({type: "setStorage", code})\n    let doc = w.document;\n    code = (await less.render(code)).css;\n    if (doc.querySelector("#style_bookmarklet_style")){\n        doc.querySelector("#style_bookmarklet_style").innerHTML = code;\n    } else {\n        let style = doc.createElement("style");\n        style.id = "style_bookmarklet_style";\n        doc.body.insertAdjacentElement("afterend", style);\n    }\n}\nfunction beautify(){\n    setValue(css_beautify(editor.session.getValue()))\n}\nfunction save(){\n    download(editor.session.getValue(), window.opener.location.hostname.replace(/\\./g, "-") + " style.css", "text/css")\n}\nasync function copy(){\n    try {\n        await navigator.clipboard.writeText(editor.session.getValue())\n    } catch(_){\n        prompt("Couldn't copy, copy from here instead: ", editor.session.getValue());\n    }\n}\nasync function compile() {\n    let {css} = await less.render(editor.session.getValue());\n    setValue(css_beautify(css));\n}\nfunction setValue(val){\n    let o = editor.selection.toJSON();\n    editor.session.setValue(val);\n    editor.selection.fromJSON(o);\n}\nfunction download(data, filename, type) {\n    var file = new Blob([data], {type: type});\n    if (window.navigator.msSaveOrOpenBlob) // IE10+\n        window.navigator.msSaveOrOpenBlob(file, filename);\n    else { // Others\n        var a = document.createElement("a"),\n                url = URL.createObjectURL(file);\n        a.href = url;\n        a.download = filename;\n        document.body.appendChild(a);\n        a.click();\n        setTimeout(function() {\n            document.body.removeChild(a);\n            window.URL.revokeObjectURL(url);  \n        }, 0); \n    }\n}\n$("#live").onchange = () => {\n    setStyle(editor.session.getValue())\n}\n<\/script>\n`,url=URL.createObjectURL(new Blob([html],{type:"text/html"})),width=window.outerWidth/3,w=window.open(url,"Style editor",`height=${window.outerHeight},width=${width},left=${window.outerWidth-width},titlebar=no,location=no,menubar=no,toolbar=no`);window.addEventListener("message",({data:e})=>{"setStorage"===e.type&&localStorage.setItem("style_bookmarklet_style",e.code),console.log(e)});})();

GitHub

View Github