@burger-editor/frozen-patty 0.10.0 → 4.0.0-alpha.1

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 (53) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +26 -27
  3. package/dist/field-name-parser.d.ts +8 -0
  4. package/dist/field-name-parser.js +18 -0
  5. package/{lib → dist}/frozen-patty.d.ts +4 -18
  6. package/dist/frozen-patty.js +43 -0
  7. package/dist/get-value.d.ts +10 -0
  8. package/dist/get-value.js +15 -0
  9. package/dist/get-values.d.ts +9 -0
  10. package/dist/get-values.js +158 -0
  11. package/dist/get.d.ts +9 -0
  12. package/dist/get.js +19 -0
  13. package/dist/index.d.ts +13 -0
  14. package/dist/index.js +14 -0
  15. package/dist/set-value.d.ts +21 -0
  16. package/{lib/setValue.js → dist/set-value.js} +249 -221
  17. package/dist/set.d.ts +9 -0
  18. package/dist/set.js +60 -0
  19. package/dist/types.d.ts +6 -0
  20. package/dist/types.js +1 -0
  21. package/dist/utils.d.ts +18 -0
  22. package/dist/utils.js +37 -0
  23. package/package.json +35 -39
  24. package/lib/frozen-patty.d.ts.map +0 -1
  25. package/lib/frozen-patty.js +0 -47
  26. package/lib/frozen-patty.js.map +0 -1
  27. package/lib/get.d.ts +0 -4
  28. package/lib/get.d.ts.map +0 -1
  29. package/lib/get.js +0 -20
  30. package/lib/get.js.map +0 -1
  31. package/lib/getValue.d.ts +0 -10
  32. package/lib/getValue.d.ts.map +0 -1
  33. package/lib/getValue.js +0 -142
  34. package/lib/getValue.js.map +0 -1
  35. package/lib/index.d.ts +0 -35
  36. package/lib/index.d.ts.map +0 -1
  37. package/lib/index.js +0 -55
  38. package/lib/index.js.map +0 -1
  39. package/lib/polyfill.d.ts +0 -1
  40. package/lib/polyfill.d.ts.map +0 -1
  41. package/lib/polyfill.js +0 -20
  42. package/lib/polyfill.js.map +0 -1
  43. package/lib/set.d.ts +0 -4
  44. package/lib/set.d.ts.map +0 -1
  45. package/lib/set.js +0 -56
  46. package/lib/set.js.map +0 -1
  47. package/lib/setValue.d.ts +0 -15
  48. package/lib/setValue.d.ts.map +0 -1
  49. package/lib/setValue.js.map +0 -1
  50. package/lib/util.d.ts +0 -8
  51. package/lib/util.d.ts.map +0 -1
  52. package/lib/util.js +0 -30
  53. package/lib/util.js.map +0 -1
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017 Yusuke Hirao
3
+ Copyright (c) 2017-2024 D-ZERO Co., Ltd.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen-patty
2
2
 
3
- [![npm version](https://badge.fury.io/js/%burger-editor%2Ffrozen-patty.svg)](https://badge.fury.io/js/%burger-editor%2Ffrozen-patty) [![Build Status](https://travis-ci.org/YusukeHirao/frozen-patty.svg?branch=master)](https://travis-ci.org/YusukeHirao/frozen-patty) [![Coverage Status](https://coveralls.io/repos/github/YusukeHirao/frozen-patty/badge.svg?branch=master)](https://coveralls.io/github/YusukeHirao/frozen-patty?branch=master)
3
+ [![npm version](https://badge.fury.io/js/@burger-editor%2Ffrozen-patty.svg)](https://badge.fury.io/js/@burger-editor%2Ffrozen-patty)
4
4
 
5
5
  Pure HTML to JSON converter that not use template engine.
6
6
 
@@ -15,53 +15,52 @@ $ npm install -D @burger-editor/frozen-patty
15
15
  ### Extraction
16
16
 
17
17
  ```js
18
- import FrozenPatty from 'frozen-patty';
18
+ import frozenPatty from '@burger-editor/frozen-patty';
19
19
 
20
- FrozenPatty('<div data-field="text">value</div>').toJSON(); // => { text: 'value' }
21
- FrozenPatty('<div data-field="field-name">value</div>').toJSON(); // => { 'field-name': 'value' }
22
- FrozenPatty('<a href="http://localhost" data-field="href:href">link</a>').toJSON(); // => { 'href': 'http://localhost' }
20
+ frozenPatty('<div data-field="text">value</div>').toJSON(); // => { text: 'value' }
21
+ frozenPatty('<div data-field="field-name">value</div>').toJSON(); // => { 'field-name': 'value' }
22
+ frozenPatty('<a href="http://localhost" data-field="href:href">link</a>').toJSON(); // => { 'href': 'http://localhost' }
23
23
 
24
- FrozenPatty('<div data-bge="text">value</div>', { attr: 'bge' }).toJSON(); // => { text: 'value' }
24
+ frozenPatty('<div data-bge="text">value</div>', { attr: 'bge' }).toJSON(); // => { text: 'value' }
25
25
  ```
26
26
 
27
27
  ### Data merge
28
28
 
29
29
  ```js
30
- FrozenPatty('<div data-field="text">value</div>').merge({ text: 'merged' }).toHTML() // => "<div data-field="text">merged</div>";
30
+ frozenPatty('<div data-field="text">value</div>').merge({ text: 'merged' }).toHTML(); // => "<div data-field="text">merged</div>";
31
31
  ```
32
32
 
33
-
34
33
  ## API
35
34
 
36
- ### FrozenPatty (html[, options])
35
+ ### `frozenPatty(html[, options])`
37
36
 
38
37
  Extraction data from HTML.
39
38
 
40
- #### arguments
39
+ #### Parameters
41
40
 
42
- args|type|required|descriptions
43
- ---|---|---|---
44
- html|`string`|required|Original HTML
45
- options|`Object`|optional|†
41
+ | parameter | type | required | descriptions |
42
+ | --------- | -------- | -------- | ------------- |
43
+ | html | `string` | required | Original HTML |
44
+ | options | `Object` | optional | † |
46
45
 
47
- #### options†
46
+ #### Options†
48
47
 
49
- options|type|default|descriptions
50
- ---|---|---|---
51
- attr|string|`"field"`|**Data attribute** name for specifying the node that FrozenPatty treats as a _field_
48
+ | options | type | default | descriptions |
49
+ | ------- | ------ | --------- | ------------------------------------------------------------------------------------ |
50
+ | attr | string | `"field"` | **Data attribute** name for specifying the node that FrozenPatty treats as a _field_ |
52
51
 
53
- ### merge (data)
52
+ ### `merge(data)`
54
53
 
55
- Data merge
54
+ Merge data.
56
55
 
57
- args|type|required|descriptions
58
- ---|---|---|---
59
- data|`Object`|required|New data
56
+ | args | type | required | descriptions |
57
+ | ---- | -------- | -------- | ------------ |
58
+ | data | `Object` | required | New data |
60
59
 
61
- ### toJSON
60
+ ### `toJSON`
62
61
 
63
- Data to plain Object.
62
+ Convert to JSON.
64
63
 
65
- ### toHTML
64
+ ### `toHTML`
66
65
 
67
- Render to HTML as string.
66
+ Convert to HTML string.
@@ -0,0 +1,8 @@
1
+ /**
2
+ *
3
+ * @param field
4
+ */
5
+ export declare function fieldNameParser(field: string): {
6
+ fieldName: string;
7
+ propName: string;
8
+ };
@@ -0,0 +1,18 @@
1
+ import { camelCase } from './utils.js';
2
+ /**
3
+ *
4
+ * @param field
5
+ */
6
+ export function fieldNameParser(field) {
7
+ field = field.trim().toLowerCase();
8
+ if (!field) {
9
+ throw new Error('Field name is empty.');
10
+ }
11
+ let [fieldName, propName] = field.split(':');
12
+ propName = propName?.trim() || '';
13
+ fieldName = fieldName?.trim() || propName || field;
14
+ return {
15
+ fieldName: camelCase(fieldName),
16
+ propName,
17
+ };
18
+ }
@@ -1,11 +1,6 @@
1
+ import type { Filter, FrozenPattyData } from './types.js';
1
2
  export default class FrozenPatty {
2
- private _dom;
3
- private _attr;
4
- private _typeConvert;
5
- /**
6
- * Value filter
7
- */
8
- private _filter?;
3
+ #private;
9
4
  /**
10
5
  *
11
6
  * @param html Original HTML
@@ -13,14 +8,13 @@ export default class FrozenPatty {
13
8
  */
14
9
  constructor(html: string, options?: FrozenPattyOptions);
15
10
  merge(data: FrozenPattyData): this;
16
- toJSON(filtering?: boolean): FrozenPattyData;
17
- toHTML(): string;
18
11
  toDOM(): Element;
12
+ toHTML(): string;
13
+ toJSON(filtering?: boolean): FrozenPattyData;
19
14
  }
20
15
  export interface FrozenPattyOptions {
21
16
  /**
22
17
  * **Data attribute** name for specifying the node that FrozenPatty treats as a _field_
23
- *
24
18
  * @default `"field"`
25
19
  */
26
20
  attr?: string;
@@ -33,7 +27,6 @@ export interface FrozenPattyOptions {
33
27
  * - `"1"` => `1`
34
28
  * - `"1.0"` => `1`
35
29
  * - `"0.1"` => `0.1`
36
- *
37
30
  * @default `false`
38
31
  */
39
32
  typeConvert?: boolean;
@@ -42,10 +35,3 @@ export interface FrozenPattyOptions {
42
35
  */
43
36
  valueFilter?: Filter;
44
37
  }
45
- export interface FrozenPattyData {
46
- [filed: string]: PrimitiveData;
47
- }
48
- export declare type PrimitiveDatum = string | number | boolean | null | undefined;
49
- export declare type PrimitiveData = PrimitiveDatum | PrimitiveDatum[];
50
- export declare type Filter = <T>(value: T) => T;
51
- //# sourceMappingURL=frozen-patty.d.ts.map
@@ -0,0 +1,43 @@
1
+ import get from './get.js';
2
+ import set from './set.js';
3
+ export default class FrozenPatty {
4
+ #attr = 'field';
5
+ #dom;
6
+ /**
7
+ * Value filter
8
+ */
9
+ #filter;
10
+ #typeConvert = false;
11
+ /**
12
+ *
13
+ * @param html Original HTML
14
+ * @param options Options
15
+ */
16
+ constructor(html, options) {
17
+ this.#dom = document.createElement('fp-placeholer');
18
+ this.#dom.innerHTML = html;
19
+ if (options) {
20
+ if (options.attr) {
21
+ this.#attr = options.attr;
22
+ }
23
+ this.#typeConvert = !!options.typeConvert;
24
+ this.#filter = options.valueFilter;
25
+ }
26
+ }
27
+ merge(data) {
28
+ const currentData = this.toJSON(false);
29
+ const newData = Object.assign(currentData, data);
30
+ this.#dom = set(this.#dom, newData, this.#attr, this.#filter);
31
+ return this;
32
+ }
33
+ toDOM() {
34
+ return this.#dom;
35
+ }
36
+ toHTML() {
37
+ return this.#dom.innerHTML;
38
+ }
39
+ toJSON(filtering = true) {
40
+ const filter = filtering ? this.#filter : undefined;
41
+ return get(this.#dom, this.#attr, this.#typeConvert, filter);
42
+ }
43
+ }
@@ -0,0 +1,10 @@
1
+ import type { Filter, PrimitiveDatum } from './types.js';
2
+ /**
3
+ * Get value from an element
4
+ * @param el A target element
5
+ * @param name A label name
6
+ * @param typeConvert Auto covert type of value
7
+ * @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
8
+ * @param filter
9
+ */
10
+ export declare function getValue(el: Element, name: string, typeConvert?: boolean, attr?: string, filter?: Filter): PrimitiveDatum | PrimitiveDatum[];
@@ -0,0 +1,15 @@
1
+ import { getValues } from './get-values.js';
2
+ import { arrayToHash } from './utils.js';
3
+ /**
4
+ * Get value from an element
5
+ * @param el A target element
6
+ * @param name A label name
7
+ * @param typeConvert Auto covert type of value
8
+ * @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
9
+ * @param filter
10
+ */
11
+ export function getValue(el, name, typeConvert = false, attr = 'field', filter) {
12
+ const value = getValues(el, typeConvert, attr, filter);
13
+ const data = arrayToHash(value);
14
+ return data[name];
15
+ }
@@ -0,0 +1,9 @@
1
+ import type { Filter, PrimitiveDatum } from './types.js';
2
+ /**
3
+ * Get value from an element
4
+ * @param el A target element
5
+ * @param convertType Auto covert type of value
6
+ * @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
7
+ * @param filter
8
+ */
9
+ export declare function getValues(el: Element, convertType?: boolean, attr?: string, filter?: Filter): [key: string | number, value: PrimitiveDatum, forceArray: boolean][];
@@ -0,0 +1,158 @@
1
+ import { fieldNameParser } from './field-name-parser.js';
2
+ import { kebabCase } from './utils.js';
3
+ /**
4
+ * Get value from an element
5
+ * @param el A target element
6
+ * @param convertType Auto covert type of value
7
+ * @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
8
+ * @param filter
9
+ */
10
+ export function getValues(el, convertType = false, attr = 'field', filter) {
11
+ const result = [];
12
+ const rawValue = el.getAttribute(`data-${attr}`);
13
+ const listRoot = el.closest(`[data-${attr}-list]`);
14
+ const forceArray = !!listRoot;
15
+ if (rawValue == null) {
16
+ throw new Error(`data-${attr} attriblute is empty.`);
17
+ }
18
+ const fieldList = rawValue.split(/\s*,\s*/);
19
+ for (const field of fieldList) {
20
+ let value;
21
+ const { fieldName, propName } = fieldNameParser(field);
22
+ if (propName) {
23
+ switch (propName) {
24
+ case 'node': {
25
+ value = el.localName ?? el.nodeName.toLowerCase();
26
+ break;
27
+ }
28
+ case 'text': {
29
+ value = el.textContent?.trim() ?? '';
30
+ break;
31
+ }
32
+ case 'html': {
33
+ value = el.innerHTML.trim();
34
+ break;
35
+ }
36
+ default: {
37
+ if (/^style\([a-z-]+\)$/i.test(propName)) {
38
+ const css = propName.replace(/^style\(([a-z-]+)\)$/i, '$1');
39
+ let style;
40
+ if (el instanceof HTMLElement) {
41
+ style = el.style;
42
+ }
43
+ else {
44
+ style = window.getComputedStyle(el);
45
+ }
46
+ value = style.getPropertyValue(css);
47
+ if (css === 'background-image') {
48
+ value = getBackgroundImagePath(value);
49
+ }
50
+ break;
51
+ }
52
+ value = getAttribute(el, attr, propName, convertType);
53
+ }
54
+ }
55
+ }
56
+ else {
57
+ if (el instanceof HTMLInputElement ||
58
+ el instanceof HTMLSelectElement ||
59
+ el instanceof HTMLTextAreaElement) {
60
+ const val = el.value;
61
+ value = convertType ? convert(val) : val;
62
+ }
63
+ else {
64
+ value = el.innerHTML.trim();
65
+ }
66
+ }
67
+ if (filter) {
68
+ value = filter(value);
69
+ }
70
+ if (value === undefined) {
71
+ continue;
72
+ }
73
+ result.push([fieldName, value, forceArray]);
74
+ }
75
+ return result;
76
+ }
77
+ /**
78
+ *
79
+ * @param el
80
+ * @param attr
81
+ * @param keyAttr
82
+ * @param typeConvert
83
+ */
84
+ function getAttribute(el, attr, keyAttr, typeConvert) {
85
+ switch (keyAttr) {
86
+ case 'contenteditable': {
87
+ if (el instanceof HTMLElement) {
88
+ return el.contentEditable === '' || el.contentEditable === 'true';
89
+ }
90
+ else {
91
+ return el.getAttribute(keyAttr) === '' || el.getAttribute(keyAttr) === 'true';
92
+ }
93
+ }
94
+ case 'checked': {
95
+ return el.checked;
96
+ }
97
+ case 'disabled': {
98
+ return el.disabled;
99
+ }
100
+ case 'download': {
101
+ // An inactive download attribute always returns an empty string.
102
+ // So to get inactive it is necessary to use the "hasAttribute" method.
103
+ return el.hasAttribute('download') ? el.getAttribute('download') : null;
104
+ }
105
+ case 'href': {
106
+ // return (el as HTMLAnchorElement).href;
107
+ return el.getAttribute(keyAttr) ?? ''; // return plain string
108
+ }
109
+ default: {
110
+ let value;
111
+ const dataAttr = ['data', attr, kebabCase(keyAttr)].join('-');
112
+ if (el.hasAttribute(dataAttr)) {
113
+ value = el.getAttribute(dataAttr) || '';
114
+ }
115
+ else {
116
+ value = el.getAttribute(keyAttr) || '';
117
+ }
118
+ if (typeConvert) {
119
+ value = convert(value);
120
+ }
121
+ return value;
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ *
127
+ * @param value
128
+ */
129
+ function convert(value) {
130
+ value = parse(value);
131
+ if (URL.canParse(value)) {
132
+ const url = new URL(value, location.href);
133
+ if (url.origin === location.origin) {
134
+ return url.pathname;
135
+ }
136
+ }
137
+ return value;
138
+ }
139
+ /**
140
+ *
141
+ * @param value
142
+ */
143
+ function parse(value) {
144
+ try {
145
+ return JSON.parse(value);
146
+ }
147
+ catch {
148
+ return value;
149
+ }
150
+ }
151
+ /**
152
+ * Get path from value of "background-image"
153
+ * @param value
154
+ */
155
+ function getBackgroundImagePath(value) {
156
+ const origin = `${location.protocol}//${location.hostname}${location.port ? `:${location.port}` : ''}`;
157
+ return decodeURI(value.replace(/^url\(["']?([^"']+)["']?\)$/i, '$1').replace(origin, ''));
158
+ }
package/dist/get.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Filter, FrozenPattyData } from './types.js';
2
+ /**
3
+ *
4
+ * @param el
5
+ * @param attr
6
+ * @param typeConvert
7
+ * @param filter
8
+ */
9
+ export default function (el: Element, attr: string, typeConvert: boolean, filter?: Filter): FrozenPattyData;
package/dist/get.js ADDED
@@ -0,0 +1,19 @@
1
+ import { getValues } from './get-values.js';
2
+ import { arrayToHash } from './utils.js';
3
+ /**
4
+ *
5
+ * @param el
6
+ * @param attr
7
+ * @param typeConvert
8
+ * @param filter
9
+ */
10
+ export default function (el, attr, typeConvert, filter) {
11
+ // eslint-disable-next-line unicorn/prefer-spread
12
+ const filedElements = Array.from(el.querySelectorAll(`[data-${attr}]`));
13
+ let values = [];
14
+ for (const _el of filedElements) {
15
+ values = [...values, ...getValues(_el, typeConvert, attr, filter)];
16
+ }
17
+ const result = arrayToHash(values);
18
+ return result;
19
+ }
@@ -0,0 +1,13 @@
1
+ import type { FrozenPattyOptions } from './frozen-patty.js';
2
+ import FrozenPatty from './frozen-patty.js';
3
+ /**
4
+ * Pure HTML to JSON converter that not use template engine.
5
+ * @param html Original HTML
6
+ * @param options Options
7
+ */
8
+ /**
9
+ *
10
+ * @param html
11
+ * @param options
12
+ */
13
+ export default function frozenPatty(html: string, options?: FrozenPattyOptions): FrozenPatty;
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ import FrozenPatty from './frozen-patty.js';
2
+ /**
3
+ * Pure HTML to JSON converter that not use template engine.
4
+ * @param html Original HTML
5
+ * @param options Options
6
+ */
7
+ /**
8
+ *
9
+ * @param html
10
+ * @param options
11
+ */
12
+ export default function frozenPatty(html, options) {
13
+ return new FrozenPatty(html, options);
14
+ }
@@ -0,0 +1,21 @@
1
+ import type { Filter, PrimitiveDatum } from './types.js';
2
+ /**
3
+ * Set value to an element
4
+ *
5
+ * ```html
6
+ * <div [target-attribute] data-[attr]="[name]:[target-attribute]"></div>
7
+ * ```
8
+ * @param el A target element
9
+ * @param name A label name
10
+ * @param datum A datum of value
11
+ * @param attr Data attribute name for specifying the node that FrozenPatty treats as a field
12
+ * @param filter
13
+ */
14
+ export declare function setValue(el: Element, name: string, datum: PrimitiveDatum, attr?: string, filter?: Filter): void;
15
+ /**
16
+ *
17
+ * @param el
18
+ * @param datum
19
+ * @param asHtml
20
+ */
21
+ export declare function setContent(el: Element, datum: PrimitiveDatum, asHtml?: boolean): void;