@ascii-web/client 0.9.0 → 0.9.2

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.
Files changed (2) hide show
  1. package/dist/ascii-img.js +23 -14
  2. package/package.json +2 -2
package/dist/ascii-img.js CHANGED
@@ -11,27 +11,33 @@ const STYLES = `
11
11
  :host {
12
12
  display: block;
13
13
  width: 100%;
14
- overflow: hidden;
15
14
  contain: inline-size;
16
15
  }
17
- pre {
16
+ pre, .measure {
18
17
  margin: 0;
19
18
  padding: 0;
20
- overflow: hidden;
21
19
  white-space: pre;
22
- max-width: 100%;
23
20
  font-family: var(--ascii-font-family, monospace);
24
21
  font-size: var(--ascii-font-size, 8px);
25
22
  line-height: var(--ascii-line-height, 1);
23
+ }
24
+ pre {
26
25
  color: var(--ascii-color, white);
27
26
  background-color: var(--ascii-bg, black);
28
27
  }
28
+ .measure {
29
+ position: absolute;
30
+ visibility: hidden;
31
+ pointer-events: none;
32
+ }
29
33
  `;
30
34
  export class AsciiImg extends HTMLElement {
31
35
  static observedAttributes = ['src', 'alt', 'min-cols', 'max-cols'];
32
36
  #shadow;
33
37
  #pre;
38
+ #measure;
34
39
  #resizeObserver;
40
+ #resizeFrame = 0;
35
41
  #imageData = null;
36
42
  #imageNaturalWidth = 0;
37
43
  #imageNaturalHeight = 0;
@@ -47,8 +53,18 @@ export class AsciiImg extends HTMLElement {
47
53
  this.#pre = document.createElement('pre');
48
54
  this.#pre.setAttribute('aria-hidden', 'true');
49
55
  this.#shadow.appendChild(this.#pre);
56
+ this.#measure = document.createElement('span');
57
+ this.#measure.className = 'measure';
58
+ this.#measure.textContent = 'M'.repeat(100);
59
+ this.#shadow.appendChild(this.#measure);
50
60
  this.setAttribute('role', 'img');
51
- this.#resizeObserver = new ResizeObserver(() => this.renderAscii());
61
+ // render on the next frame rather than inside the callback: rendering
62
+ // changes the host's height, which would resize the observed element
63
+ // mid-callback and trigger a ResizeObserver loop error
64
+ this.#resizeObserver = new ResizeObserver(() => {
65
+ cancelAnimationFrame(this.#resizeFrame);
66
+ this.#resizeFrame = requestAnimationFrame(() => this.renderAscii());
67
+ });
52
68
  }
53
69
  connectedCallback() {
54
70
  this.#resizeObserver.observe(this);
@@ -56,6 +72,7 @@ export class AsciiImg extends HTMLElement {
56
72
  }
57
73
  disconnectedCallback() {
58
74
  this.#resizeObserver.disconnect();
75
+ cancelAnimationFrame(this.#resizeFrame);
59
76
  }
60
77
  attributeChangedCallback(name, oldValue, newValue) {
61
78
  if (oldValue === newValue)
@@ -109,15 +126,7 @@ export class AsciiImg extends HTMLElement {
109
126
  };
110
127
  }
111
128
  measureCharWidth() {
112
- const span = document.createElement('span');
113
- span.style.font = getComputedStyle(this.#pre).font;
114
- span.style.visibility = 'hidden';
115
- span.style.position = 'absolute';
116
- span.textContent = 'M';
117
- document.body.appendChild(span);
118
- const width = span.getBoundingClientRect().width;
119
- document.body.removeChild(span);
120
- return width;
129
+ return this.#measure.getBoundingClientRect().width / 100;
121
130
  }
122
131
  async renderAscii() {
123
132
  if (!this.#imageData || !this.#imageNaturalHeight || !this.#imageNaturalWidth)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ascii-web/client",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "A web component that renders images as ASCII art using WASM",
5
5
  "author": "Raffaele Cataldo",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  "dist/"
17
17
  ],
18
18
  "dependencies": {
19
- "@ascii-web/wasm": "0.9.0"
19
+ "@ascii-web/wasm": "0.9.2"
20
20
  },
21
21
  "devDependencies": {
22
22
  "typescript": "^5.6.0"