#+tags[]: vite, javascript
I found this cool little project called notepadtab.com that lets you enter text into a box, and it will encode it in the url, which you can then bookmark, or share around, or whatever. Put it through a url shortener or what have you and the next is available to see anywhere.
I wanted to see how it worked by implementing it myself. This code is much smaller than what is at revolter/notepadtab.com, and once I figured out how to add pako compression, I figured why not also add a QR code?
// main.js
import '@unocss/reset/tailwind.css';
import './main.css';
import '@shoelace-style/shoelace/dist/themes/light.css';
import '@shoelace-style/shoelace/dist/components/copy-button/copy-button.js';
import '@shoelace-style/shoelace/dist/components/textarea/textarea.js';
import '@shoelace-style/shoelace/dist/components/qr-code/qr-code.js';
import pako from 'pako';
function deflateToBase64( inputData ) {
const compressed = pako.deflate( inputData );
const base64 = window.btoa( String.fromCharCode.apply(null, compressed ));
return base64;
}
function inflateFromBase64( base64 ) {
const reverseBase64 = atob(base64);
const reverseBase64Array = new Uint8Array(reverseBase64.split("").map(function(c) {
return c.charCodeAt(0); }));
const inflatedRaw = pako.inflate( reverseBase64Array );
const decompressed = String.fromCharCode.apply( null, inflatedRaw );
return decompressed;
}
window.addEventListener("load", (event) => {
const box = document.getElementById( "note-area" )
const copy = document.getElementById( "copy" );
copy.value = window.location;
const hash = window.location.hash
if( hash != '' ) {
// Restore the value
const smaller = inflateFromBase64( hash.substring( 1 ) )
box.value = smaller;
}
qrcode.value = window.location.href
qrcode.size = 256;
box.addEventListener( "sl-input", (event) => {
// Update the url on change
const hash = deflateToBase64( box.value )
window.location.hash = '#' + hash
copy.value = window.location
qrcode.value = window.location.href
});
});
index.html
:
<html>
<head>
<title>Notepad</title>
<script src="main.js" type="module"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body px-2>
<div max-w-prose mx-auto prose>
<h1 font-header text-2xl font-bold>All your note data in the url</h1>
<sl-copy-button float-right id="copy"></sl-copy-button>
<sl-textarea
id="note-area"
label="Secret note"
resize="auto"
help-text="Nothing stored on the server, just a big url">
</sl-textarea>
<sl-qr-code
id="qrcode"
>
</sl-qr-code>
<p>
Reimplementing <a href="https://notepadtab.com/">notepadtab</a> for fun. This code is at
<a href="https://github.com/wschenk/nodepadjs/">https://github.com/wschenk/nodepadjs/</a>.
</p>
</div>
</body>
</html>
package.json
:
{
"type": "module",
"scripts": {
"dev": "unocss \"**/*.html\" -o main.css --watch & vite",
"build": "unocss \"**/*.html\" -o main.css && vite build"
},
"dependencies": {
"@shoelace-style/shoelace": "^2.15.1",
"pako": "^2.1.0",
"unocss": "^0.60.4",
"vite": "^5.2.12",
"vite-plugin-static-copy": "^1.0.5"
}
}
// uno.config.ts
import {
defineConfig,
presetAttributify,
presetTypography,
presetUno
} from 'unocss'
export default defineConfig({
presets: [
presetAttributify(), // required when using attributify mode
presetUno(), // required
presetTypography(),
],
})
Update the base
if you are deploying it somewhere else, I’m using
github pages without a domain so it’s in a subdirectory.
// vite.config.js
import { defineConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
const iconsPath = 'node_modules/@shoelace-style/shoelace/dist/assets/icons';
// https://vitejs.dev/config/
export default defineConfig({
base: '/nodepadjs/', // Or / if you arent using github pages
resolve: {
alias: [
{
find: /\/assets\/icons\/(.+)/,
replacement: `${iconsPath}/$1`,
},
],
},
build: {
rollupOptions: {
// external: /^lit/,
plugins: [],
},
},
plugins: [
viteStaticCopy({
targets: [
{
src: iconsPath,
dest: 'assets',
},
],
}),
],
});
mkdir -p .github/workflows
name: Deploy
on:
push:
branches:
- main
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Build project
run: npm run build
- name: Upload production-ready build files
uses: actions/upload-artifact@v3
with:
name: production-files
path: ./dist
deploy:
name: Deploy
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: production-files
path: ./dist
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
Deployed here. It takes forever because the vite build includes all of the icons for shoelace…