next-blurhash-previews 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/bin/markdown-sync.js +25 -0
- package/components/ImageWithPreview.tsx +99 -0
- package/components/NextWrapper.tsx +19 -0
- package/components/imagePreviewBootstrap.tsx +7 -0
- package/example.md +9 -0
- package/img1.png +0 -0
- package/img5.png +0 -0
- package/index.js +5 -0
- package/junk.js +1 -0
- package/next-runner/.eslintrc.json +3 -0
- package/next-runner/README.md +34 -0
- package/next-runner/next.config.js +6 -0
- package/next-runner/package-lock.json +5064 -0
- package/next-runner/package.json +23 -0
- package/next-runner/pages/_app.js +11 -0
- package/next-runner/pages/_document.js +19 -0
- package/next-runner/pages/index.js +26 -0
- package/next-runner/public/dynamo-introduction/img1.png +0 -0
- package/next-runner/public/dynamo-introduction/img10.png +0 -0
- package/next-runner/public/dynamo-introduction/img11.png +0 -0
- package/next-runner/public/dynamo-introduction/img12.png +0 -0
- package/next-runner/public/dynamo-introduction/img13.png +0 -0
- package/next-runner/public/dynamo-introduction/img14.png +0 -0
- package/next-runner/public/dynamo-introduction/img15.png +0 -0
- package/next-runner/public/dynamo-introduction/img2.png +0 -0
- package/next-runner/public/dynamo-introduction/img3.png +0 -0
- package/next-runner/public/dynamo-introduction/img4.png +0 -0
- package/next-runner/public/dynamo-introduction/img5.png +0 -0
- package/next-runner/public/dynamo-introduction/img5a.png +0 -0
- package/next-runner/public/dynamo-introduction/img6.png +0 -0
- package/next-runner/public/dynamo-introduction/img7.png +0 -0
- package/next-runner/public/dynamo-introduction/img8.png +0 -0
- package/next-runner/public/dynamo-introduction/img9.png +0 -0
- package/next-runner/public/favicon.ico +0 -0
- package/next-runner/public/vercel.svg +4 -0
- package/next-runner/styles/Home.module.css +0 -0
- package/next-runner/styles/globals.css +22 -0
- package/next-runner/yalc.lock +9 -0
- package/next-runner/yarn.lock +1645 -0
- package/output.md +15 -0
- package/package.json +42 -0
- package/plugin.js +78 -0
- package/tsconfig.json +21 -0
- package/tsconfig.node.json +8 -0
- package/util/setBootstrap.js +13 -0
- package/vite.config.ts +21 -0
- package/yalc.lock +9 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import fs from "fs";
|
4
|
+
import path, { dirname } from "path";
|
5
|
+
import { reporter } from "vfile-reporter";
|
6
|
+
import { remark } from "remark";
|
7
|
+
|
8
|
+
import retextSentenceSpacing from "../plugin.js";
|
9
|
+
|
10
|
+
import { fileURLToPath } from "url";
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
12
|
+
|
13
|
+
const __dirname = dirname(__filename);
|
14
|
+
const buffer = fs.readFileSync(path.join(__dirname, "example.md"));
|
15
|
+
|
16
|
+
async function run() {
|
17
|
+
remark()
|
18
|
+
.use(retextSentenceSpacing)
|
19
|
+
.process(buffer)
|
20
|
+
.then((file) => {
|
21
|
+
fs.writeFileSync("output.md", file.toString());
|
22
|
+
});
|
23
|
+
}
|
24
|
+
|
25
|
+
run();
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import { decode } from "../node_modules/blurhash/dist/esm/index";
|
2
|
+
|
3
|
+
type blurhash = { w: number; h: number; blurhash: string };
|
4
|
+
|
5
|
+
class ImageWithPreview extends HTMLElement {
|
6
|
+
isReady: boolean = false;
|
7
|
+
loaded: boolean = false;
|
8
|
+
sd: ShadowRoot;
|
9
|
+
mo?: MutationObserver;
|
10
|
+
|
11
|
+
static observedAttributes = ["preview", "url"];
|
12
|
+
|
13
|
+
get imgEl(): any {
|
14
|
+
return this.querySelector("img");
|
15
|
+
}
|
16
|
+
get canvasEl(): any {
|
17
|
+
return this.querySelector("canvas");
|
18
|
+
}
|
19
|
+
|
20
|
+
constructor() {
|
21
|
+
super();
|
22
|
+
|
23
|
+
this.sd = this.attachShadow({ mode: "open" });
|
24
|
+
this.sd.innerHTML = `<slot name="preview"></slot>`;
|
25
|
+
}
|
26
|
+
|
27
|
+
checkReady = () => {
|
28
|
+
if (this.imgEl && this.canvasEl) {
|
29
|
+
this.ready();
|
30
|
+
this.mo?.disconnect();
|
31
|
+
}
|
32
|
+
return this.isReady;
|
33
|
+
};
|
34
|
+
|
35
|
+
connectedCallback() {
|
36
|
+
if (!this.checkReady()) {
|
37
|
+
this.mo = new MutationObserver(this.checkReady);
|
38
|
+
this.mo.observe(this, { subtree: true, childList: true, attributes: false });
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
ready() {
|
43
|
+
this.isReady = true;
|
44
|
+
this.updatePreview();
|
45
|
+
if (this.imgEl.complete) {
|
46
|
+
this.onImageLoad();
|
47
|
+
}
|
48
|
+
this.imgEl.addEventListener("load", this.onImageLoad);
|
49
|
+
}
|
50
|
+
|
51
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
52
|
+
if (!this.isReady) {
|
53
|
+
return;
|
54
|
+
}
|
55
|
+
|
56
|
+
if (name === "preview") {
|
57
|
+
this.updatePreview();
|
58
|
+
} else if (name === "url") {
|
59
|
+
this.loaded = false;
|
60
|
+
}
|
61
|
+
|
62
|
+
this.render();
|
63
|
+
}
|
64
|
+
|
65
|
+
updatePreview() {
|
66
|
+
const previewObj = JSON.parse(this.getAttribute("preview")!);
|
67
|
+
updateBlurHashPreview(this.canvasEl, previewObj);
|
68
|
+
}
|
69
|
+
|
70
|
+
onImageLoad = () => {
|
71
|
+
if (this.getAttribute("url") !== this.imgEl.src) {
|
72
|
+
setTimeout(() => {
|
73
|
+
this.loaded = true;
|
74
|
+
this.render();
|
75
|
+
}, 1500);
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
render() {
|
80
|
+
this.sd.innerHTML = `<slot name="${this.loaded ? "image" : "preview"}"></slot>`;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
if (!customElements.get("uikit-image")) {
|
85
|
+
customElements.define("uikit-image", ImageWithPreview);
|
86
|
+
}
|
87
|
+
|
88
|
+
function updateBlurHashPreview(canvasEl: HTMLCanvasElement, preview: blurhash) {
|
89
|
+
const { w: width, h: height } = preview;
|
90
|
+
|
91
|
+
canvasEl.width = width;
|
92
|
+
canvasEl.height = height;
|
93
|
+
|
94
|
+
const pixels = decode(preview.blurhash, width, height);
|
95
|
+
const ctx = canvasEl.getContext("2d")!;
|
96
|
+
const imageData = ctx.createImageData(width, height);
|
97
|
+
imageData.data.set(pixels);
|
98
|
+
ctx.putImageData(imageData, 0, 0);
|
99
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { useEffect, useRef } from "react";
|
2
|
+
|
3
|
+
export const ImageWithPreview = (props: any) => {
|
4
|
+
const wcRef = useRef(null);
|
5
|
+
|
6
|
+
const { preview } = props;
|
7
|
+
const { w, h } = JSON.parse(preview);
|
8
|
+
|
9
|
+
useEffect(() => {
|
10
|
+
wcRef.current.activate();
|
11
|
+
}, []);
|
12
|
+
|
13
|
+
return (
|
14
|
+
<uikit-image ref={wcRef} {...props}>
|
15
|
+
<img style={{ display: "none" }} />
|
16
|
+
<canvas width={w} height={h}></canvas>
|
17
|
+
</uikit-image>
|
18
|
+
);
|
19
|
+
};
|
package/example.md
ADDED
package/img1.png
ADDED
Binary file
|
package/img5.png
ADDED
Binary file
|
package/index.js
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
import { imagePreviewBootstrap } from "./imagePreviewBootstrap";
|
2
|
+
|
3
|
+
export { imagePreviewBootstrap };
|
4
|
+
|
5
|
+
export const src = `(() => { "use strict";var A=Object.defineProperty;var R=(t,e,s)=>e in t?A(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var u=(t,e,s)=>(R(t,typeof e!="symbol"?e+"":e,s),s);const G=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],h=t=>{let e=0;for(let s=0;s<t.length;s++){const n=t[s],o=G.indexOf(n);e=e*83+o}return e},p=t=>{let e=t/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)},b=t=>{let e=Math.max(0,Math.min(1,t));return e<=.0031308?Math.round(e*12.92*255+.5):Math.round((1.055*Math.pow(e,.4166666666666667)-.055)*255+.5)},P=t=>t<0?-1:1,E=(t,e)=>P(t)*Math.pow(Math.abs(t),e);class v extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e}}const k=t=>{if(!t||t.length<6)throw new v("The blurhash string must be at least 6 characters");const e=h(t[0]),s=Math.floor(e/9)+1,n=e%9+1;if(t.length!==4+2*n*s)throw new v(\`blurhash length mismatch: length is \${t.length} but it should be \${4+2*n*s}\`)},D=t=>{const e=t>>16,s=t>>8&255,n=t&255;return[p(e),p(s),p(n)]},H=(t,e)=>{const s=Math.floor(t/361),n=Math.floor(t/19)%19,o=t%19;return[E((s-9)/9,2)*e,E((n-9)/9,2)*e,E((o-9)/9,2)*e]},S=(t,e,s,n)=>{k(t),n=n|1;const o=h(t[0]),a=Math.floor(o/9)+1,c=o%9+1,q=(h(t[1])+1)/166,g=new Array(c*a);for(let r=0;r<g.length;r++)if(r===0){const i=h(t.substring(2,6));g[r]=D(i)}else{const i=h(t.substring(4+r*2,6+r*2));g[r]=H(i,q*n)}const l=e*4,d=new Uint8ClampedArray(l*s);for(let r=0;r<s;r++)for(let i=0;i<e;i++){let I=0,x=0,C=0;for(let m=0;m<a;m++)for(let f=0;f<c;f++){const M=Math.cos(Math.PI*i*f/e)*Math.cos(Math.PI*r*m/s);let w=g[f+m*c];I+=w[0]*M,x+=w[1]*M,C+=w[2]*M}let B=b(I),T=b(x),y=b(C);d[4*i+0+r*l]=B,d[4*i+1+r*l]=T,d[4*i+2+r*l]=y,d[4*i+3+r*l]=255}return d};class L extends HTMLElement{constructor(){super();u(this,"loaded",!1);u(this,"sd");u(this,"onImageLoad",()=>{this.getAttribute("url")!==this.currentImageEl.src&&setTimeout(()=>{this.loaded=!0,this.render()},1500)});this.sd=this.attachShadow({mode:"open"}),this.sd.innerHTML='<slot name="preview"></slot>'}get currentImageEl(){return this.querySelector("img")}get currentCanvasEl(){return this.querySelector("canvas")}connectedCallback(){this.currentImageEl.complete&&this.onImageLoad(),this.currentImageEl.addEventListener("load",this.onImageLoad)}attributeChangedCallback(s,n,o){if(s==="preview"){const a=JSON.parse(o);O(this.currentCanvasEl,a)}else s==="url"&&o!==this.currentImageEl.getAttribute("src")&&(this.loaded=!1,this.currentImageEl.src=o||"");this.render()}render(){this.sd.innerHTML=\`<slot name="\${this.loaded?"image":"preview"}"></slot>\`}}u(L,"observedAttributes",["preview","url"]);customElements.get("uikit-image")||customElements.define("uikit-image",L);function O(t,e){const{w:s,h:n}=e;t.width=s,t.height=n;const o=S(e.blurhash,s,n),a=t.getContext("2d"),c=a.createImageData(s,n);c.data.set(o),a.putImageData(c,0,0)} })();`;
|
package/junk.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";var B=Object.defineProperty;var T=(t,e,s)=>e in t?B(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var a=(t,e,s)=>(T(t,typeof e!="symbol"?e+"":e,s),s);const k=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],h=t=>{let e=0;for(let s=0;s<t.length;s++){const n=t[s],o=k.indexOf(n);e=e*83+o}return e},p=t=>{let e=t/255;return e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)},b=t=>{let e=Math.max(0,Math.min(1,t));return e<=.0031308?Math.round(e*12.92*255+.5):Math.round((1.055*Math.pow(e,.4166666666666667)-.055)*255+.5)},A=t=>t<0?-1:1,v=(t,e)=>A(t)*Math.pow(Math.abs(t),e);class C extends Error{constructor(e){super(e),this.name="ValidationError",this.message=e}}const G=t=>{if(!t||t.length<6)throw new C("The blurhash string must be at least 6 characters");const e=h(t[0]),s=Math.floor(e/9)+1,n=e%9+1;if(t.length!==4+2*n*s)throw new C(\`blurhash length mismatch: length is \${t.length} but it should be \${4+2*n*s}\`)},V=t=>{const e=t>>16,s=t>>8&255,n=t&255;return[p(e),p(s),p(n)]},D=(t,e)=>{const s=Math.floor(t/361),n=Math.floor(t/19)%19,o=t%19;return[v((s-9)/9,2)*e,v((n-9)/9,2)*e,v((o-9)/9,2)*e]},H=(t,e,s,n)=>{G(t),n=n|1;const o=h(t[0]),c=Math.floor(o/9)+1,l=o%9+1,x=(h(t[1])+1)/166,g=new Array(l*c);for(let r=0;r<g.length;r++)if(r===0){const i=h(t.substring(2,6));g[r]=V(i)}else{const i=h(t.substring(4+r*2,6+r*2));g[r]=D(i,x*n)}const d=e*4,u=new Uint8ClampedArray(d*s);for(let r=0;r<s;r++)for(let i=0;i<e;i++){let y=0,E=0,I=0;for(let m=0;m<c;m++)for(let f=0;f<l;f++){const w=Math.cos(Math.PI*i*f/e)*Math.cos(Math.PI*r*m/s);let M=g[f+m*l];y+=M[0]*w,E+=M[1]*w,I+=M[2]*w}let L=b(y),P=b(E),q=b(I);u[4*i+0+r*d]=L,u[4*i+1+r*d]=P,u[4*i+2+r*d]=q,u[4*i+3+r*d]=255}return u};class R extends HTMLElement{constructor(){super();a(this,"isReady",!1);a(this,"loaded",!1);a(this,"sd");a(this,"mo");a(this,"checkReady",()=>{this.currentImageEl&&this.currentCanvasEl&&(this.ready(),this.mo.disconnect())});a(this,"onImageLoad",()=>{this.getAttribute("url")!==this.currentImageEl.src&&setTimeout(()=>{this.loaded=!0,this.render()},1500)});this.sd=this.attachShadow({mode:"open"}),this.sd.innerHTML='<slot name="preview"></slot>'}get currentImageEl(){return this.querySelector("img")}get currentCanvasEl(){return this.querySelector("canvas")}connectedCallback(){this.mo=new MutationObserver(this.checkReady),this.mo.observe(this,{subtree:!0,childList:!0,attributes:!1})}ready(){this.isReady=!0,this.currentImageEl.complete&&this.onImageLoad(),this.currentImageEl.addEventListener("load",this.onImageLoad),this.loaded||this.updatePreview()}attributeChangedCallback(s,n,o){!this.isReady||(s==="preview"?this.updatePreview():s==="url"&&(this.loaded=!1),this.render())}updatePreview(){const s=JSON.parse(this.getAttribute("preview"));O(this.currentCanvasEl,s)}render(){this.sd.innerHTML=\`<slot name="\${this.loaded?"image":"preview"}"></slot>\`}}a(R,"observedAttributes",["preview","url"]);customElements.get("uikit-image")||customElements.define("uikit-image",R);function O(t,e){const{w:s,h:n}=e;t.width=s,t.height=n;const o=H(e.blurhash,s,n),c=t.getContext("2d"),l=c.createImageData(s,n);l.data.set(o),c.putImageData(l,0,0)}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
First, run the development server:
|
6
|
+
|
7
|
+
```bash
|
8
|
+
npm run dev
|
9
|
+
# or
|
10
|
+
yarn dev
|
11
|
+
```
|
12
|
+
|
13
|
+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
14
|
+
|
15
|
+
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
16
|
+
|
17
|
+
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
18
|
+
|
19
|
+
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
20
|
+
|
21
|
+
## Learn More
|
22
|
+
|
23
|
+
To learn more about Next.js, take a look at the following resources:
|
24
|
+
|
25
|
+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
26
|
+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
27
|
+
|
28
|
+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
29
|
+
|
30
|
+
## Deploy on Vercel
|
31
|
+
|
32
|
+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
33
|
+
|
34
|
+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|