next-blurhash-previews 0.0.3-beta79 → 0.0.4-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ImageWithPreview.tsx +33 -5
 - package/components/NextWrapper.js +29 -0
 - package/imagePreviewBootstrap.js +1 -1
 - package/index.js +2 -1
 - package/package.json +4 -2
 - package/vite.nextwrapper.config.ts +18 -0
 - package/components/NextWrapper.tsx +0 -27
 
| 
         @@ -1,7 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import { decode } from "blurhash/dist/esm";
         
     | 
| 
       1 
2 
     | 
    
         
             
            type blurhash = { w: number; h: number; blurhash: string };
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
      
 4 
     | 
    
         
            +
            declare global {
         
     | 
| 
      
 5 
     | 
    
         
            +
              interface HTMLCanvasElement {
         
     | 
| 
      
 6 
     | 
    
         
            +
                transferControlToOffscreen(): this & Transferable;
         
     | 
| 
      
 7 
     | 
    
         
            +
              }
         
     | 
| 
       5 
8 
     | 
    
         
             
            }
         
     | 
| 
       6 
9 
     | 
    
         | 
| 
       7 
10 
     | 
    
         
             
            class ImageWithPreview extends HTMLElement {
         
     | 
| 
         @@ -29,6 +32,11 @@ class ImageWithPreview extends HTMLElement { 
     | 
|
| 
       29 
32 
     | 
    
         
             
                if (this.#imgEl && this.#canvasEl) {
         
     | 
| 
       30 
33 
     | 
    
         
             
                  this.mo?.disconnect();
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
                  console.log("checkready", this.#imgEl.complete);
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  setInterval(() => {
         
     | 
| 
      
 38 
     | 
    
         
            +
                    console.log("checkready interval", this.#imgEl.complete);
         
     | 
| 
      
 39 
     | 
    
         
            +
                  }, 100);
         
     | 
| 
       32 
40 
     | 
    
         
             
                  if (this.#imgEl.complete) {
         
     | 
| 
       33 
41 
     | 
    
         
             
                    this.#imgLoad();
         
     | 
| 
       34 
42 
     | 
    
         
             
                  } else {
         
     | 
| 
         @@ -53,6 +61,7 @@ class ImageWithPreview extends HTMLElement { 
     | 
|
| 
       53 
61 
     | 
    
         
             
              }
         
     | 
| 
       54 
62 
     | 
    
         | 
| 
       55 
63 
     | 
    
         
             
              #imgLoad = () => {
         
     | 
| 
      
 64 
     | 
    
         
            +
                console.log("imgLoad - should work", this.#imgEl.complete);
         
     | 
| 
       56 
65 
     | 
    
         
             
                this.sd.innerHTML = `<slot name="image"></slot>`;
         
     | 
| 
       57 
66 
     | 
    
         
             
              };
         
     | 
| 
       58 
67 
     | 
    
         | 
| 
         @@ -68,7 +77,11 @@ class ImageWithPreview extends HTMLElement { 
     | 
|
| 
       68 
77 
     | 
    
         
             
                }
         
     | 
| 
       69 
78 
     | 
    
         | 
| 
       70 
79 
     | 
    
         
             
                const previewObj = JSON.parse(this.getAttribute("preview")!);
         
     | 
| 
       71 
     | 
    
         
            -
                updateBlurHashPreview( 
     | 
| 
      
 80 
     | 
    
         
            +
                updateBlurHashPreview(
         
     | 
| 
      
 81 
     | 
    
         
            +
                  this.hasAttribute("sync"),
         
     | 
| 
      
 82 
     | 
    
         
            +
                  this.#canvasEl,
         
     | 
| 
      
 83 
     | 
    
         
            +
                  previewObj
         
     | 
| 
      
 84 
     | 
    
         
            +
                );
         
     | 
| 
       72 
85 
     | 
    
         
             
              }
         
     | 
| 
       73 
86 
     | 
    
         
             
            }
         
     | 
| 
       74 
87 
     | 
    
         | 
| 
         @@ -82,12 +95,27 @@ const workerBlob = new Blob( 
     | 
|
| 
       82 
95 
     | 
    
         
             
            );
         
     | 
| 
       83 
96 
     | 
    
         
             
            const worker = new Worker(window.URL.createObjectURL(workerBlob));
         
     | 
| 
       84 
97 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
            function updateBlurHashPreview( 
     | 
| 
      
 98 
     | 
    
         
            +
            function updateBlurHashPreview(
         
     | 
| 
      
 99 
     | 
    
         
            +
              sync: boolean,
         
     | 
| 
      
 100 
     | 
    
         
            +
              canvasEl: HTMLCanvasElement,
         
     | 
| 
      
 101 
     | 
    
         
            +
              preview: blurhash
         
     | 
| 
      
 102 
     | 
    
         
            +
            ) {
         
     | 
| 
       86 
103 
     | 
    
         
             
              const { w: width, h: height, blurhash } = preview;
         
     | 
| 
       87 
104 
     | 
    
         
             
              canvasEl.width = width;
         
     | 
| 
       88 
105 
     | 
    
         
             
              canvasEl.height = height;
         
     | 
| 
       89 
106 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
              if ( 
     | 
| 
      
 107 
     | 
    
         
            +
              if (sync) {
         
     | 
| 
      
 108 
     | 
    
         
            +
                const start = +new Date();
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                const pixels = decode(blurhash, width, height);
         
     | 
| 
      
 111 
     | 
    
         
            +
                const ctx = canvasEl.getContext("2d")!;
         
     | 
| 
      
 112 
     | 
    
         
            +
                const imageData = ctx.createImageData(width, height);
         
     | 
| 
      
 113 
     | 
    
         
            +
                imageData.data.set(pixels);
         
     | 
| 
      
 114 
     | 
    
         
            +
                ctx.putImageData(imageData, 0, 0);
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                const end = +new Date();
         
     | 
| 
      
 117 
     | 
    
         
            +
                console.log("Done Encoding Sync", blurhash, end - start);
         
     | 
| 
      
 118 
     | 
    
         
            +
              } else if (canvasEl.transferControlToOffscreen) {
         
     | 
| 
       91 
119 
     | 
    
         
             
                const offscreen = canvasEl.transferControlToOffscreen();
         
     | 
| 
       92 
120 
     | 
    
         
             
                worker.postMessage({ canvas: offscreen, width, height, blurhash }, [
         
     | 
| 
       93 
121 
     | 
    
         
             
                  offscreen,
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import React, {
         
     | 
| 
      
 2 
     | 
    
         
            +
              useEffect,
         
     | 
| 
      
 3 
     | 
    
         
            +
              useRef,
         
     | 
| 
      
 4 
     | 
    
         
            +
              createElement,
         
     | 
| 
      
 5 
     | 
    
         
            +
              cloneElement,
         
     | 
| 
      
 6 
     | 
    
         
            +
              Children,
         
     | 
| 
      
 7 
     | 
    
         
            +
            } from "react";
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            export const NextWrapper = props => {
         
     | 
| 
      
 10 
     | 
    
         
            +
              const wcRef = useRef(null);
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              const { blurhash, width, height } = props;
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              const json = JSON.stringify({ w: width, h: height, blurhash });
         
     | 
| 
      
 15 
     | 
    
         
            +
              const wcProps = { preview: json };
         
     | 
| 
      
 16 
     | 
    
         
            +
              if (props.sync) {
         
     | 
| 
      
 17 
     | 
    
         
            +
                wcProps.sync = true;
         
     | 
| 
      
 18 
     | 
    
         
            +
              }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              return createElement(
         
     | 
| 
      
 21 
     | 
    
         
            +
                "blurhash-image",
         
     | 
| 
      
 22 
     | 
    
         
            +
                {
         
     | 
| 
      
 23 
     | 
    
         
            +
                  ref: wcRef,
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ...wcProps,
         
     | 
| 
      
 25 
     | 
    
         
            +
                },
         
     | 
| 
      
 26 
     | 
    
         
            +
                cloneElement(Children.only(props.children), { slot: "image" }),
         
     | 
| 
      
 27 
     | 
    
         
            +
                createElement("canvas", { width, height, slot: "preview" })
         
     | 
| 
      
 28 
     | 
    
         
            +
              );
         
     | 
| 
      
 29 
     | 
    
         
            +
            };
         
     | 
    
        package/imagePreviewBootstrap.js
    CHANGED
    
    | 
         @@ -9,6 +9,6 @@ export const imagePreviewBootstrap = createElement( 
     | 
|
| 
       9 
9 
     | 
    
         
             
                dangerouslySetInnerHTML: { __html: `(() => { "use strict";const I=["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","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],u=t=>{let n=0;for(let o=0;o<t.length;o++){const e=t[o],c=I.indexOf(e);n=n*83+c}return n},D=t=>{let n=t/255;return n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)},b=t=>{let n=Math.max(0,Math.min(1,t));return n<=.0031308?Math.round(n*12.92*255+.5):Math.round((1.055*Math.pow(n,.4166666666666667)-.055)*255+.5)},P=t=>t<0?-1:1,p=(t,n)=>P(t)*Math.pow(Math.abs(t),n);class q extends Error{constructor(n){super(n),this.name="ValidationError",this.message=n}}const v=t=>{if(!t||t.length<6)throw new q("The blurhash string must be at least 6 characters");const n=u(t[0]),o=Math.floor(n/9)+1,e=n%9+1;if(t.length!==4+2*e*o)throw new q(\`blurhash length mismatch: length is \${t.length} but it should be \${4+2*e*o}\`)},A=t=>{const n=t>>16,o=t>>8&255,e=t&255;return[D(n),D(o),D(e)]},T=(t,n)=>{const o=Math.floor(t/361),e=Math.floor(t/19)%19,c=t%19;return[p((o-9)/9,2)*n,p((e-9)/9,2)*n,p((c-9)/9,2)*n]},V=(t,n,o,e)=>{v(t),e=e|1;const c=u(t[0]),i=Math.floor(c/9)+1,l=c%9+1,h=(u(t[1])+1)/166,r=new Array(l*i);for(let s=0;s<r.length;s++)if(s===0){const a=u(t.substring(2,6));r[s]=A(a)}else{const a=u(t.substring(4+s*2,6+s*2));r[s]=T(a,h*e)}const d=n*4,g=new Uint8ClampedArray(d*o);for(let s=0;s<o;s++)for(let a=0;a<n;a++){let B=0,E=0,R=0;for(let M=0;M<i;M++)for(let f=0;f<l;f++){const w=Math.cos(Math.PI*a*f/n)*Math.cos(Math.PI*s*M/o);let x=r[f+M*l];B+=x[0]*w,E+=x[1]*w,R+=x[2]*w}let C=b(B),G=b(E),y=b(R);g[4*a+0+s*d]=C,g[4*a+1+s*d]=G,g[4*a+2+s*d]=y,g[4*a+3+s*d]=255}return g};var $=V;addEventListener("message",t=>{console.log(t);const{canvas:n,width:o,height:e,blurhash:c}=t.data;console.log("Encoding",c);const i=+new Date,l=$(c,o,e),m=n.getContext("2d"),h=m.createImageData(o,e);h.data.set(l),m.putImageData(h,0,0);const r=+new Date;console.log("Done Encoding",c,r-i)}); })();` },
         
     | 
| 
       10 
10 
     | 
    
         
             
              }),
         
     | 
| 
       11 
11 
     | 
    
         
             
              createElement("script", {
         
     | 
| 
       12 
     | 
    
         
            -
                dangerouslySetInnerHTML: { __html: `(() => { "use strict";class n extends HTMLElement{sd;mo;static observedAttributes=["preview"];#s=!1;get# 
     | 
| 
      
 12 
     | 
    
         
            +
                dangerouslySetInnerHTML: { __html: `(() => { "use strict";const T=["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","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],u=e=>{let t=0;for(let o=0;o<e.length;o++){const s=e[o],r=T.indexOf(s);t=t*83+r}return t},p=e=>{let t=e/255;return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)},M=e=>{let t=Math.max(0,Math.min(1,e));return t<=.0031308?Math.round(t*12.92*255+.5):Math.round((1.055*Math.pow(t,.4166666666666667)-.055)*255+.5)},A=e=>e<0?-1:1,v=(e,t)=>A(e)*Math.pow(Math.abs(e),t);class L extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t}}const D=e=>{if(!e||e.length<6)throw new L("The blurhash string must be at least 6 characters");const t=u(e[0]),o=Math.floor(t/9)+1,s=t%9+1;if(e.length!==4+2*s*o)throw new L(\`blurhash length mismatch: length is \${e.length} but it should be \${4+2*s*o}\`)},O=e=>{const t=e>>16,o=e>>8&255,s=e&255;return[p(t),p(o),p(s)]},P=(e,t)=>{const o=Math.floor(e/361),s=Math.floor(e/19)%19,r=e%19;return[v((o-9)/9,2)*t,v((s-9)/9,2)*t,v((r-9)/9,2)*t]},E=(e,t,o,s)=>{D(e),s=s|1;const r=u(e[0]),a=Math.floor(r/9)+1,c=r%9+1,g=(u(e[1])+1)/166,l=new Array(c*a);for(let n=0;n<l.length;n++)if(n===0){const i=u(e.substring(2,6));l[n]=O(i)}else{const i=u(e.substring(4+n*2,6+n*2));l[n]=P(i,g*s)}const h=t*4,d=new Uint8ClampedArray(h*o);for(let n=0;n<o;n++)for(let i=0;i<t;i++){let y=0,C=0,k=0;for(let m=0;m<a;m++)for(let f=0;f<c;f++){const w=Math.cos(Math.PI*i*f/t)*Math.cos(Math.PI*n*m/o);let b=l[f+m*c];y+=b[0]*w,C+=b[1]*w,k+=b[2]*w}let B=M(y),R=M(C),q=M(k);d[4*i+0+n*h]=B,d[4*i+1+n*h]=R,d[4*i+2+n*h]=q,d[4*i+3+n*h]=255}return d};var I=E;class S extends HTMLElement{sd;mo;static observedAttributes=["preview"];#s=!1;get#t(){return this.querySelector("img")}get#e(){return this.querySelector("canvas")}constructor(){super(),this.sd=this.attachShadow({mode:"open"}),this.sd.innerHTML='<slot name="preview"></slot>'}#o=()=>{if(this.#t&&this.#e)return this.mo?.disconnect(),console.log("checkready",this.#t.complete),setInterval(()=>{console.log("checkready interval",this.#t.complete)},100),this.#t.complete?this.#n():(this.#r(),this.#t.addEventListener("load",this.#n)),1};connectedCallback(){this.#s=!0,this.#o()||(this.mo=new MutationObserver(this.#o),this.mo.observe(this,{subtree:!0,childList:!0,attributes:!1}))}#n=()=>{console.log("imgLoad - should work",this.#t.complete),this.sd.innerHTML='<slot name="image"></slot>'};attributeChangedCallback(t){this.#e&&t==="preview"&&this.#r()}#r(){if(!this.#s||!this.getAttribute("preview"))return;const t=JSON.parse(this.getAttribute("preview"));H(this.hasAttribute("sync"),this.#e,t)}}customElements.get("blurhash-image")||customElements.define("blurhash-image",S);const G=new Blob([document.querySelector("#next-blurhash-worker-script").textContent],{type:"text/javascript"}),j=new Worker(window.URL.createObjectURL(G));function H(e,t,o){const{w:s,h:r,blurhash:a}=o;if(t.width=s,t.height=r,e){const c=+new Date,x=I(a,s,r),g=t.getContext("2d"),l=g.createImageData(s,r);l.data.set(x),g.putImageData(l,0,0);const h=+new Date;console.log("Done Encoding Sync",a,h-c)}else if(t.transferControlToOffscreen){const c=t.transferControlToOffscreen();j.postMessage({canvas:c,width:s,height:r,blurhash:a},[c])}} })();` },
         
     | 
| 
       13 
13 
     | 
    
         
             
              })
         
     | 
| 
       14 
14 
     | 
    
         
             
            );
         
     | 
    
        package/index.js
    CHANGED
    
    
    
        package/package.json
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            {
         
     | 
| 
       2 
2 
     | 
    
         
             
              "name": "next-blurhash-previews",
         
     | 
| 
       3 
     | 
    
         
            -
              "version": "0.0. 
     | 
| 
      
 3 
     | 
    
         
            +
              "version": "0.0.4-beta1",
         
     | 
| 
       4 
4 
     | 
    
         
             
              "description": "",
         
     | 
| 
       5 
5 
     | 
    
         
             
              "main": "index.js",
         
     | 
| 
       6 
6 
     | 
    
         
             
              "module": "index.js",
         
     | 
| 
         @@ -24,7 +24,7 @@ 
     | 
|
| 
       24 
24 
     | 
    
         
             
                "url": "https://github.com/arackaf/next-static-image-previews/issues"
         
     | 
| 
       25 
25 
     | 
    
         
             
              },
         
     | 
| 
       26 
26 
     | 
    
         
             
              "homepage": "https://github.com/arackaf/next-static-image-previews#readme",
         
     | 
| 
       27 
     | 
    
         
            -
              " 
     | 
| 
      
 27 
     | 
    
         
            +
              "devDependencies": {
         
     | 
| 
       28 
28 
     | 
    
         
             
                "@types/react": "^18.0.15",
         
     | 
| 
       29 
29 
     | 
    
         
             
                "@types/react-dom": "^18.0.6",
         
     | 
| 
       30 
30 
     | 
    
         
             
                "@vitejs/plugin-react": "^1.3.2",
         
     | 
| 
         @@ -34,6 +34,8 @@ 
     | 
|
| 
       34 
34 
     | 
    
         
             
                "install": "^0.13.0",
         
     | 
| 
       35 
35 
     | 
    
         
             
                "node-fetch": "^3.2.6",
         
     | 
| 
       36 
36 
     | 
    
         
             
                "npm": "^8.15.1",
         
     | 
| 
      
 37 
     | 
    
         
            +
                "react": "^18.2.0",
         
     | 
| 
      
 38 
     | 
    
         
            +
                "react-dom": "^18.2.0",
         
     | 
| 
       37 
39 
     | 
    
         
             
                "remark": "^14.0.2",
         
     | 
| 
       38 
40 
     | 
    
         
             
                "remark-frontmatter": "^4.0.1",
         
     | 
| 
       39 
41 
     | 
    
         
             
                "retext": "^8.1.0",
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import { defineConfig } from "vite";
         
     | 
| 
      
 2 
     | 
    
         
            +
            import react from "@vitejs/plugin-react";
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            export default defineConfig({
         
     | 
| 
      
 5 
     | 
    
         
            +
              build: {
         
     | 
| 
      
 6 
     | 
    
         
            +
                target: "es2022",
         
     | 
| 
      
 7 
     | 
    
         
            +
                outDir: "./build",
         
     | 
| 
      
 8 
     | 
    
         
            +
                emptyOutDir: false,
         
     | 
| 
      
 9 
     | 
    
         
            +
                lib: {
         
     | 
| 
      
 10 
     | 
    
         
            +
                  entry: "components/NextWrapper.tsx",
         
     | 
| 
      
 11 
     | 
    
         
            +
                  formats: ["es"],
         
     | 
| 
      
 12 
     | 
    
         
            +
                  fileName: () => "NextWrapper.js",
         
     | 
| 
      
 13 
     | 
    
         
            +
                  name: "NextWrapper",
         
     | 
| 
      
 14 
     | 
    
         
            +
                },
         
     | 
| 
      
 15 
     | 
    
         
            +
                //minify: false,
         
     | 
| 
      
 16 
     | 
    
         
            +
              },
         
     | 
| 
      
 17 
     | 
    
         
            +
              plugins: [react()],
         
     | 
| 
      
 18 
     | 
    
         
            +
            });
         
     | 
| 
         @@ -1,27 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import React, { useEffect, useRef } from "react";
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            declare global {
         
     | 
| 
       4 
     | 
    
         
            -
              namespace JSX {
         
     | 
| 
       5 
     | 
    
         
            -
                interface IntrinsicElements {
         
     | 
| 
       6 
     | 
    
         
            -
                  ["blurhash-image"]: any;
         
     | 
| 
       7 
     | 
    
         
            -
                }
         
     | 
| 
       8 
     | 
    
         
            -
              }
         
     | 
| 
       9 
     | 
    
         
            -
            }
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            export const ImageWithPreview = (props: any) => {
         
     | 
| 
       12 
     | 
    
         
            -
              const wcRef = useRef<any>(null);
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
              const { preview } = props;
         
     | 
| 
       15 
     | 
    
         
            -
              const { w, h } = JSON.parse(preview);
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
              useEffect(() => {
         
     | 
| 
       18 
     | 
    
         
            -
                wcRef.current.activate();
         
     | 
| 
       19 
     | 
    
         
            -
              }, []);
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
              return (
         
     | 
| 
       22 
     | 
    
         
            -
                <blurhash-image ref={wcRef} {...props}>
         
     | 
| 
       23 
     | 
    
         
            -
                  <img style={{ display: "none" }} />
         
     | 
| 
       24 
     | 
    
         
            -
                  <canvas width={w} height={h}></canvas>
         
     | 
| 
       25 
     | 
    
         
            -
                </blurhash-image>
         
     | 
| 
       26 
     | 
    
         
            -
              );
         
     | 
| 
       27 
     | 
    
         
            -
            };
         
     |