From 281966d39a8f328f85ed37c7a7b6ccab3d34d2cf Mon Sep 17 00:00:00 2001 From: elpatron Date: Sun, 22 Jun 2025 17:06:06 +0200 Subject: [PATCH] Initial commit: QR Code Generator with Docker support --- Caddyfile | 14 + Dockerfile | 15 + README.md | 60 ++++ assets/qrious.min.js.Download | 6 + docker-compose.yml | 9 + index.html | 587 ++++++++++++++++++++++++++++++++++ 6 files changed, 691 insertions(+) create mode 100644 Caddyfile create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 assets/qrious.min.js.Download create mode 100644 docker-compose.yml create mode 100644 index.html diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..e8b1e39 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,14 @@ +:80 { + root * /usr/share/caddy + file_server + + # Behandle die HTML-Datei als Index + try_files {path} /Just%20a%20QR%20Code.html + + # CORS-Header für Cross-Origin-Requests + header { + Access-Control-Allow-Origin * + Access-Control-Allow-Methods "GET, POST, OPTIONS" + Access-Control-Allow-Headers "Content-Type" + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f5ae042 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM caddy:2-alpine + +# Kopiere die HTML-Datei +COPY index.html /usr/share/caddy/ + +# Kopiere den Ordner mit den JavaScript-Dateien +COPY assets /usr/share/caddy/assets/ + +# Kopiere die Caddy-Konfiguration +COPY Caddyfile /etc/caddy/Caddyfile + +# Exponiere Port 80 +EXPOSE 80 + +# Caddy startet automatisch mit der Caddyfile-Konfiguration \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5882a4b --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# QR Code Generator + +Ein einfacher QR-Code-Generator, der vollständig im Browser läuft. Keine Daten werden an externe Server gesendet. + +## Docker Setup + +### Mit Docker Compose (empfohlen) + +```bash +# Container bauen und starten +docker-compose up -d + +# Container stoppen +docker-compose down +``` + +### Mit Docker direkt + +```bash +# Image bauen +docker build -t qr-generator . + +# Container starten +docker run -d -p 8080:80 --name qr-generator qr-generator + +# Container stoppen +docker stop qr-generator +docker rm qr-generator +``` + +## Verwendung + +Nach dem Start ist die Anwendung unter `http://localhost:8080` erreichbar. + +### URL-Parameter + +Die Anwendung unterstützt folgende URL-Parameter: + +- `text` - Text oder URL für den QR-Code +- `size` - Größe (128, 256, 512, 1024) +- `errorCorrection` - Fehlerkorrektur (L, M, Q, H) +- `foreground` - Vordergrundfarbe (Hex-Code) +- `background` - Hintergrundfarbe (Hex-Code) + +### Beispiele + +``` +http://localhost:8080/?text=Hello%20World +http://localhost:8080/?text=Test&size=512&errorCorrection=H +http://localhost:8080/?text=Colored&foreground=%23ff0000&background=%23ffff00 +``` + +## Features + +- ✅ Vollständig clientseitig (keine Server-Kommunikation) +- ✅ URL-Parameter für alle Einstellungen +- ✅ Anpassbare Größen und Farben +- ✅ Verschiedene Fehlerkorrektur-Level +- ✅ Download-Funktion +- ✅ Responsive Design \ No newline at end of file diff --git a/assets/qrious.min.js.Download b/assets/qrious.min.js.Download new file mode 100644 index 0000000..5735ea6 --- /dev/null +++ b/assets/qrious.min.js.Download @@ -0,0 +1,6 @@ +/*! QRious v4.0.2 | (C) 2017 Alasdair Mercer | GPL v3 License +Based on jsqrencode | (C) 2010 tz@execpc.com | GPL v3 License +*/ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.QRious=e()}(this,function(){"use strict";function t(t,e){var n;return"function"==typeof Object.create?n=Object.create(t):(s.prototype=t,n=new s,s.prototype=null),e&&i(!0,n,e),n}function e(e,n,s,r){var o=this;return"string"!=typeof e&&(r=s,s=n,n=e,e=null),"function"!=typeof n&&(r=s,s=n,n=function(){return o.apply(this,arguments)}),i(!1,n,o,r),n.prototype=t(o.prototype,s),n.prototype.constructor=n,n.class_=e||o.class_,n.super_=o,n}function i(t,e,i){for(var n,s,a=0,h=(i=o.call(arguments,2)).length;a>1&1,n=0;n0;e--)n[e]=n[e]?n[e-1]^_.EXPONENT[v._modN(_.LOG[n[e]]+t)]:n[e-1];n[0]=_.EXPONENT[v._modN(_.LOG[n[0]]+t)]}for(t=0;t<=i;t++)n[t]=_.LOG[n[t]]},_checkBadness:function(){var t,e,i,n,s,r=0,o=this._badness,a=this.buffer,h=this.width;for(s=0;sh*h;)u-=h*h,c++;for(r+=c*v.N4,n=0;n=o-2&&(t=o-2,s>9&&t--);var a=t;if(s>9){for(r[a+2]=0,r[a+3]=0;a--;)e=r[a],r[a+3]|=255&e<<4,r[a+2]=e>>4;r[2]|=255&t<<4,r[1]=t>>4,r[0]=64|t>>12}else{for(r[a+1]=0,r[a+2]=0;a--;)e=r[a],r[a+2]|=255&e<<4,r[a+1]=e>>4;r[1]|=255&t<<4,r[0]=64|t>>4}for(a=t+3-(s<10);a=5&&(i+=v.N1+n[e]-5);for(e=3;et||3*n[e-3]>=4*n[e]||3*n[e+3]>=4*n[e])&&(i+=v.N3);return i},_finish:function(){this._stringBuffer=this.buffer.slice();var t,e,i=0,n=3e4;for(e=0;e<8&&(this._applyMask(e),(t=this._checkBadness())>=1)1&n&&(s[r-1-e+8*r]=1,e<6?s[8+r*e]=1:s[8+r*(e+1)]=1);for(e=0;e<7;e++,n>>=1)1&n&&(s[8+r*(r-7+e)]=1,e?s[6-e+8*r]=1:s[7+8*r]=1)},_interleaveBlocks:function(){var t,e,i=this._dataBlock,n=this._ecc,s=this._eccBlock,r=0,o=this._calculateMaxLength(),a=this._neccBlock1,h=this._neccBlock2,f=this._stringBuffer;for(t=0;t1)for(t=u.BLOCK[n],i=s-7;;){for(e=s-7;e>t-3&&(this._addAlignment(e,i),!(e6)for(t=d.BLOCK[r-7],e=17,i=0;i<6;i++)for(n=0;n<3;n++,e--)1&(e>11?r>>e-12:t>>e)?(s[5-i+o*(2-n+o-11)]=1,s[2-n+o-11+o*(5-i)]=1):(this._setMask(5-i,2-n+o-11),this._setMask(2-n+o-11,5-i))},_isMasked:function(t,e){var i=v._getMaskBit(t,e);return 1===this._mask[i]},_pack:function(){var t,e,i,n=1,s=1,r=this.width,o=r-1,a=r-1,h=(this._dataBlock+this._eccBlock)*(this._neccBlock1+this._neccBlock2)+this._neccBlock2;for(e=0;ee&&(i=t,t=e,e=i),i=e,i+=e*e,i>>=1,i+=t},_modN:function(t){for(;t>=255;)t=((t-=255)>>8)+(255&t);return t},N1:3,N2:3,N3:40,N4:10}),p=v,m=f.extend({draw:function(){this.element.src=this.qrious.toDataURL()},reset:function(){this.element.src=""},resize:function(){var t=this.element;t.width=t.height=this.qrious.size}}),g=h.extend(function(t,e,i,n){this.name=t,this.modifiable=Boolean(e),this.defaultValue=i,this._valueTransformer=n},{transform:function(t){var e=this._valueTransformer;return"function"==typeof e?e(t,this):t}}),k=h.extend(null,{abs:function(t){return null!=t?Math.abs(t):null},hasOwn:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},noop:function(){},toUpperCase:function(t){return null!=t?t.toUpperCase():null}}),w=h.extend(function(t){this.options={},t.forEach(function(t){this.options[t.name]=t},this)},{exists:function(t){return null!=this.options[t]},get:function(t,e){return w._get(this.options[t],e)},getAll:function(t){var e,i=this.options,n={};for(e in i)k.hasOwn(i,e)&&(n[e]=w._get(i[e],t));return n},init:function(t,e,i){"function"!=typeof i&&(i=k.noop);var n,s;for(n in this.options)k.hasOwn(this.options,n)&&(s=this.options[n],w._set(s,s.defaultValue,e),w._createAccessor(s,e,i));this._setAll(t,e,!0)},set:function(t,e,i){return this._set(t,e,i)},setAll:function(t,e){return this._setAll(t,e)},_set:function(t,e,i,n){var s=this.options[t];if(!s)throw new Error("Invalid option: "+t);if(!s.modifiable&&!n)throw new Error("Option cannot be modified: "+t);return w._set(s,e,i)},_setAll:function(t,e,i){if(!t)return!1;var n,s=!1;for(n in t)k.hasOwn(t,n)&&this._set(n,t[n],e,i)&&(s=!0);return s}},{_createAccessor:function(t,e,i){var n={get:function(){return w._get(t,e)}};t.modifiable&&(n.set=function(n){w._set(t,n,e)&&i(n,t)}),Object.defineProperty(e,t.name,n)},_get:function(t,e){return e["_"+t.name]},_set:function(t,e,i){var n="_"+t.name,s=i[n],r=t.transform(null!=e?e:t.defaultValue);return i[n]=r,r!==s}}),M=w,b=h.extend(function(){this._services={}},{getService:function(t){var e=this._services[t];if(!e)throw new Error("Service is not being managed with name: "+t);return e},setService:function(t,e){if(this._services[t])throw new Error("Service is already managed with name: "+t);e&&(this._services[t]=e)}}),B=new M([new g("background",!0,"white"),new g("backgroundAlpha",!0,1,k.abs),new g("element"),new g("foreground",!0,"black"),new g("foregroundAlpha",!0,1,k.abs),new g("level",!0,"L",k.toUpperCase),new g("mime",!0,"image/png"),new g("padding",!0,null,k.abs),new g("size",!0,100,k.abs),new g("value",!0,"")]),y=new b,O=h.extend(function(t){B.init(t,this,this.update.bind(this));var e=B.get("element",this),i=y.getService("element"),n=e&&i.isCanvas(e)?e:i.createCanvas(),s=e&&i.isImage(e)?e:i.createImage();this._canvasRenderer=new c(this,n,!0),this._imageRenderer=new m(this,s,s===e),this.update()},{get:function(){return B.getAll(this)},set:function(t){B.setAll(t,this)&&this.update()},toDataURL:function(t){return this.canvas.toDataURL(t||this.mime)},update:function(){var t=new p({level:this.level,value:this.value});this._canvasRenderer.render(t),this._imageRenderer.render(t)}},{use:function(t){y.setService(t.getName(),t)}});Object.defineProperties(O.prototype,{canvas:{get:function(){return this._canvasRenderer.getElement()}},image:{get:function(){return this._imageRenderer.getElement()}}});var A=O,L=h.extend({getName:function(){}}).extend({createCanvas:function(){},createImage:function(){},getName:function(){return"element"},isCanvas:function(t){},isImage:function(t){}}).extend({createCanvas:function(){return document.createElement("canvas")},createImage:function(){return document.createElement("img")},isCanvas:function(t){return t instanceof HTMLCanvasElement},isImage:function(t){return t instanceof HTMLImageElement}});return A.use(new L),A}); + +//# sourceMappingURL=qrious.min.js.map \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a84e8ec --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3.8' + +services: + qr-generator: + build: . + ports: + - "8080:80" + container_name: qr-generator + restart: unless-stopped \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..7db2e5c --- /dev/null +++ b/index.html @@ -0,0 +1,587 @@ + + + + + + Just a QR Code + + + + + + +
+

Just a QR Code

+ + +
+ +
+ + +
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+
+ +
+
+ + Generated QR Code +
+
+ +
+
+ +
+
+

About

+ +
+
+

I needed to make a QR code again. It's one of those tasks that's useful enough to pop up regularly, but not frequently enough for you to have a go-to solution. When the need arises, you end up googling "QR code generator" and picking the least sketchy-looking option from the results. A couple ads and some invisible trackers are just the price you pay, right?

+ +

Not today.

+ +

Rather than bemoan the fact that there's no easy way to get just a QR code without the low-key parasitic monetization, I found a library (qrious) and put together just enough Javascript code to generate QR codes in the browser. No ads, no trackers, no sending your data to someone else's server for who-knows-what-reason.

+ +

Go ahead and inspect the page source. Save it to your computer, copy it, remix it, whatever you want.

+ +

This is my act of resistance: I'll pay for the domain name and hosting just so you and I don't ever have to give one more click or tracker data-point to some questionable "free" site again. If you find this useful, you can pay it back by making or doing something of your own and giving it away freely.

+ +

This is the web we were trying to build.

+ +

Be excellent to each other.

+
+
+ + + + + + + \ No newline at end of file