@burger-editor/frozen-patty 4.0.0-alpha.75 → 4.0.0-alpha.77

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/README.md CHANGED
@@ -132,13 +132,15 @@ frozenPatty(html)
132
132
 
133
133
  適用時の自動変換ルール:
134
134
 
135
- | 配列インデックス | 生成要素 | DOM 位置 | 属性変換 |
136
- | ---------------- | -------- | ------------------------------ | ---------------------------------------- |
137
- | `0` | `img` | DOM 末尾 | `srcset` → `src`、`sizes` 削除 |
138
- | `1..n` | `source` | DOM 先頭側(配列の逆順で挿入) | `src` → `srcset`、`alt` / `loading` 削除 |
135
+ | 配列インデックス | 生成要素 | DOM 位置 | 属性変換 |
136
+ | ---------------- | -------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
137
+ | `0` | `img` | DOM 末尾 | `srcset` → `src`、`sizes` のバインド削除、静的な `media` / `type` 削除 |
138
+ | `1..n` | `source` | DOM 先頭側(配列の逆順で挿入) | `src` → `srcset`、`alt` / `loading` のバインド削除、静的な `img` 専用属性(`alt` / `src` / `loading` / `decoding` 等)削除 |
139
139
 
140
140
  `data-field` 構文も生成要素に合わせて再設定される(`img`: `path:src, …` / `source`: `path:srcset, …`)。配列要素に該当属性が存在しないスロット(例: `img` の `media`)は `null` で埋める。
141
141
 
142
+ 雛形にバインドされていない静的属性は、生成要素にそのまま引き継がれる。ただし生成要素で HTML 仕様上無効になる属性は落とす(雛形 `img` の静的な `alt` が `source` に付く、など)。既に無効な属性を持つ保存済み HTML も、再度 `merge` すれば取り除かれる。
143
+
142
144
  適用時の雛形(複製元の要素)は、DOM 末尾の要素(=配列 index 0、この場合 `img`)から取る。`source` を雛形にすると `alt` / `loading` のバインドを持たない状態で `img` に変換されてしまい、一度保存された HTML を再度テンプレートとして `merge` した際(`Item.import` の2回目以降の呼び出し等)に `img` から `alt` / `loading` が失われる。抽出時の「DOM 末尾 = 配列 index 0」という読み取り規則と対称にすることで、この劣化を防いでいる。
143
145
 
144
146
  ## Options
@@ -2,6 +2,54 @@ import { kebabCase } from '@burger-editor/utils';
2
2
  import { setValue } from './set-value.js';
3
3
  import { stringifyFields } from './stringify-fields.js';
4
4
  import { definedFields, flattenData, getFields, hasField, isReverseListElement, maxLengthOf, removeProp, replaceNode, replaceProp, } from './utils.js';
5
+ /**
6
+ * `picture` 内の `source` で無効な、`img` 専用の属性。
7
+ * `source` で有効な属性の allowlist にしないのは、グローバル属性・`data-*`・
8
+ * `aria-*` を列挙しきれず、取りこぼすと正しい属性まで落としてしまうため
9
+ */
10
+ const PICTURE_SOURCE_INVALID_ATTRS = [
11
+ 'alt',
12
+ 'src',
13
+ 'loading',
14
+ 'decoding',
15
+ 'fetchpriority',
16
+ 'crossorigin',
17
+ 'referrerpolicy',
18
+ 'usemap',
19
+ 'ismap',
20
+ 'elementtiming',
21
+ 'attributionsrc',
22
+ // Obsolete img attributes
23
+ 'align',
24
+ 'border',
25
+ 'hspace',
26
+ 'vspace',
27
+ 'longdesc',
28
+ 'name',
29
+ 'lowsrc',
30
+ ];
31
+ /**
32
+ * `picture` 内の `img` で無効な、`source` 専用の属性
33
+ */
34
+ const PICTURE_IMG_INVALID_ATTRS = ['media', 'type'];
35
+ /**
36
+ * 要素から指定した属性を取り除く
37
+ *
38
+ * replaceNode は未バインドの静的属性を要素の種類に関係なく引き継ぎ、
39
+ * 変換元と変換先の要素が同じ場合は何もしない。そのため、雛形 img の静的な
40
+ * alt が source に付いたり、過去の出力で img に付いた media が残ったりする。
41
+ * 変換の有無にかかわらず、ここで必ず落とす。
42
+ * バインドされたフィールドは落とさない。要素のプロパティに無い属性は
43
+ * setValue が書き込まないため(propInElement)、データの index 対応を
44
+ * 崩してまで data-* 宣言から外す必要がない
45
+ * @param el
46
+ * @param names
47
+ */
48
+ function removeAttrs(el, names) {
49
+ for (const name of names) {
50
+ el.removeAttribute(name);
51
+ }
52
+ }
5
53
  /**
6
54
  *
7
55
  * @param el
@@ -68,6 +116,7 @@ export function setComponent(el, data, attr, filter, xssSanitize = true) {
68
116
  if (i === 0) {
69
117
  // Convert first item to img element
70
118
  item = replaceNode(item, 'img', attr, xssSanitize);
119
+ removeAttrs(item, PICTURE_IMG_INVALID_ATTRS);
71
120
  fields = replaceProp(fields, 'srcset', 'src');
72
121
  fields = removeProp(fields, 'sizes');
73
122
  const fieldQuery = stringifyFields(fields);
@@ -76,6 +125,7 @@ export function setComponent(el, data, attr, filter, xssSanitize = true) {
76
125
  else {
77
126
  // Convert subsequent items to source elements
78
127
  item = replaceNode(item, 'source', attr, xssSanitize);
128
+ removeAttrs(item, PICTURE_SOURCE_INVALID_ATTRS);
79
129
  fields = replaceProp(fields, 'src', 'srcset');
80
130
  fields = removeProp(fields, 'alt');
81
131
  fields = removeProp(fields, 'loading');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burger-editor/frozen-patty",
3
- "version": "4.0.0-alpha.75",
3
+ "version": "4.0.0-alpha.77",
4
4
  "description": "Pure HTML to JSON converter that does not use a template engine.",
5
5
  "author": "D-ZERO",
6
6
  "license": "(MIT OR Apache-2.0)",
@@ -47,7 +47,7 @@
47
47
  "clean": "tsc --build --clean"
48
48
  },
49
49
  "dependencies": {
50
- "@burger-editor/utils": "4.0.0-alpha.75"
50
+ "@burger-editor/utils": "4.0.0-alpha.77"
51
51
  },
52
- "gitHead": "dcbf606dcf50d0d4e43b1b04aec3ee140f6d887a"
52
+ "gitHead": "196ad02ea9b1a05e9658a8cf42b564033a0fe3ec"
53
53
  }