waibu-mpa 1.0.0 → 1.0.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.
- package/README.md +13 -6
- package/bajo/.alias +1 -0
- package/bajo/config-dev.json +6 -0
- package/bajo/config-prod.json +14 -0
- package/bajo/config.json +62 -21
- package/bajo/hook/dobo.wmpa-session@before-sanitize-schema.js +10 -0
- package/bajo/hook/waibu-mpa.theme@after-inject-scripts.js +6 -0
- package/bajo/hook/waibu-mpa@pre-parsing.js +28 -5
- package/bajo/init.js +7 -0
- package/bajo/method/attr-to-array.js +4 -2
- package/bajo/method/attr-to-object.js +3 -1
- package/bajo/method/attribs/parse.js +28 -0
- package/bajo/method/attribs/stringify.js +27 -0
- package/bajo/method/base64-json-decode.js +5 -0
- package/bajo/method/base64-json-encode.js +5 -0
- package/bajo/method/build-url.js +27 -0
- package/bajo/method/get-app-title.js +9 -0
- package/bajo/method/get-resource.js +12 -0
- package/bajo/method/group-attrs.js +45 -0
- package/bajo/method/html-tags.js +6 -0
- package/bajo/method/iconset-mappings.js +350 -0
- package/bajo/method/json-stringify.js +86 -0
- package/bajo/method/minify.js +9 -0
- package/bajo/method/pagination-layout.js +7 -3
- package/bajo/method/render-string.js +4 -2
- package/bajo/method/render.js +19 -5
- package/bajo/method/resolve-layout.js +15 -0
- package/bajo/method/resolve-partial.js +7 -0
- package/bajo/method/resolve-template.js +7 -0
- package/bajo/method/url-to-breadcrumb.js +35 -0
- package/bajoI18N/resource/en-US.json +6 -0
- package/bajoI18N/resource/id.json +23 -2
- package/dobo/fixture/site-setting.json +5 -0
- package/dobo/schema/session.json +9 -0
- package/dobo/schema/site-setting.js +28 -0
- package/docs/component.md +232 -0
- package/docs/configuration.md +34 -0
- package/docs/hook.md +118 -0
- package/docs/instance.md +23 -0
- package/docs/page-building.md +79 -0
- package/lib/apply-format.js +6 -11
- package/lib/build-locals.js +29 -13
- package/lib/build-page/apply-include.js +21 -0
- package/lib/build-page/attrs-mutation.js +65 -0
- package/lib/build-page/concat-resources.js +69 -0
- package/lib/build-page/inject-elements/css.js +16 -0
- package/lib/build-page/inject-elements/meta.js +18 -0
- package/lib/build-page/inject-elements/script.js +61 -0
- package/lib/build-page/inject-elements.js +43 -0
- package/lib/build-page/manipulation.js +39 -0
- package/lib/build-page/replace-tag.js +48 -0
- package/lib/build-page.js +44 -0
- package/lib/build-routes.js +76 -28
- package/lib/class/component.js +178 -58
- package/lib/class/factory/any.js +12 -0
- package/lib/class/factory/datalist.js +12 -0
- package/lib/class/factory/icon.js +26 -0
- package/lib/class/factory/include.js +26 -0
- package/lib/class/factory/link.js +19 -0
- package/lib/class/factory/page-end.js +58 -0
- package/lib/class/factory/page-start.js +19 -0
- package/lib/class/factory/script.js +33 -0
- package/lib/class/factory/style.js +19 -0
- package/lib/class/factory/t.js +15 -0
- package/lib/class/factory/template.js +11 -0
- package/lib/class/factory/tree.js +36 -0
- package/lib/class/factory.js +79 -0
- package/lib/class/iconset.js +34 -0
- package/lib/class/theme.js +13 -1
- package/lib/class/view-engine.js +70 -19
- package/lib/collect-iconsets.js +42 -0
- package/lib/collect-themes.js +85 -38
- package/lib/collect-view-engines.js +12 -7
- package/lib/decorate.js +13 -8
- package/lib/error.js +16 -3
- package/lib/get-cached-result.js +31 -0
- package/lib/load-resource.js +27 -0
- package/lib/not-found.js +29 -1
- package/lib/resolve-resource.js +63 -0
- package/lib/session/setup.js +18 -0
- package/lib/session/store.js +61 -0
- package/lib/sub-app.js +6 -2
- package/package.json +4 -3
- package/waibu/boot.js +22 -26
- package/waibuDb/schema/session.json +3 -0
- package/waibuMpa/layout/default.html +5 -0
- package/waibuMpa/route/component/render.js +13 -0
- package/waibuMpa/route/logo/@id.js +21 -0
- package/waibuMpa/route/wmpa.js +30 -0
- package/waibuMpa/template/500.html +4 -0
- package/waibuMpa/template/_500.html +8 -0
- package/waibuMpa/template/wmpa.js +417 -0
- package/waibuMpa/view-engine.js +1 -1
- package/waibuStatic/virtual.json +2 -2
- package/bajo/hook/bajo-i18n@before-init.js +0 -6
- package/bajo/method/attrs-to-object.js +0 -14
- package/bajo/method/get-tpl-and-theme.js +0 -46
- package/bajo/method/object-to-attrs.js +0 -12
- package/lib/parse-components.js +0 -83
- package/waibuMpa/theme/component/self.js +0 -6
- package/waibuMpa/theme/component/tag-three.js +0 -6
- package/waibuMpa/theme.js +0 -35
- package/waibuMpa/view-engine/template/default/500.html +0 -1
- /package/waibuMpa/{view-engine/template/default → template}/404.html +0 -0
package/README.md
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# waibu-mpa
|
|
2
2
|
|
|
3
|
-
Plugin name: **
|
|
3
|
+
Plugin name: **waibuMpa**, alias: **wmpa**
|
|
4
4
|
|
|
5
|
-
 
|
|
6
6
|
|
|
7
7
|
> <br />**Attention**: I do NOT accept any pull request at the moment, thanks!<br /><br />
|
|
8
8
|
|
|
9
|
-
Multi Pages App (MPA) for [
|
|
9
|
+
Multi Pages App (MPA) for [Waibu Framework](https://github.com/ardhi/waibu)
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
Goto your ```<bajo-base-dir>``` and type:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
$ npm install
|
|
16
|
+
$ npm install waibu-mpa
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Now open your ```<bajo-data-dir>/config/.plugins``` and put ```
|
|
19
|
+
Now open your ```<bajo-data-dir>/config/.plugins``` and put ```waibu-mpa``` in it
|
|
20
|
+
|
|
21
|
+
## Documentation
|
|
22
|
+
|
|
23
|
+
- [Class Instance](docs/instance.md)
|
|
24
|
+
- [Configuration](docs/configuration.md)
|
|
25
|
+
- [App Hook](docs/hook.md)
|
|
26
|
+
- [Component](docs/component.md)
|
|
20
27
|
|
|
21
28
|
## License
|
|
22
29
|
|
package/bajo/.alias
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wmpa
|
package/bajo/config.json
CHANGED
|
@@ -1,35 +1,82 @@
|
|
|
1
1
|
{
|
|
2
|
-
"alias": "wbmpa",
|
|
3
2
|
"title": "Multi Page Webapp",
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
"waibu": {
|
|
4
|
+
"prefix": ""
|
|
5
|
+
},
|
|
6
|
+
"mountMainAsRoot": true,
|
|
7
|
+
"page": {
|
|
8
|
+
"charset": "utf-8",
|
|
9
|
+
"cacheMaxAge": 0,
|
|
10
|
+
"insertWarning": false
|
|
11
|
+
},
|
|
7
12
|
"darkMode": {
|
|
8
|
-
"
|
|
9
|
-
"qsKey": "dark"
|
|
13
|
+
"default": false,
|
|
14
|
+
"qsKey": "dark-mode"
|
|
10
15
|
},
|
|
11
16
|
"i18n": {
|
|
12
17
|
"detectors": ["qs"],
|
|
13
18
|
"defaultNs": ["dobo", "waibuMpa"]
|
|
14
19
|
},
|
|
20
|
+
"session": {
|
|
21
|
+
"secret": "f703a74b884b539e78c642a5369fe538",
|
|
22
|
+
"cookieName": "sid",
|
|
23
|
+
"cookie": {
|
|
24
|
+
"secure": "auto"
|
|
25
|
+
},
|
|
26
|
+
"saveUninitialized": false
|
|
27
|
+
},
|
|
15
28
|
"emoji": true,
|
|
16
29
|
"viewEngine": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
30
|
+
"cacheMaxAge": 0,
|
|
31
|
+
"layout": {
|
|
32
|
+
"default": "waibuMpa:/default.html",
|
|
33
|
+
"fallback": true
|
|
34
|
+
}
|
|
19
35
|
},
|
|
20
36
|
"theme": {
|
|
21
|
-
"
|
|
37
|
+
"default": null,
|
|
38
|
+
"autoInsert": {
|
|
39
|
+
"css": true,
|
|
40
|
+
"meta": true,
|
|
41
|
+
"scripts": true,
|
|
42
|
+
"inlineScript": true,
|
|
43
|
+
"inlineCss": true
|
|
44
|
+
},
|
|
22
45
|
"component": {
|
|
23
|
-
"
|
|
46
|
+
"unknownTag": "comment",
|
|
24
47
|
"defaultTag": "div",
|
|
25
|
-
"cacheMaxAge":
|
|
48
|
+
"cacheMaxAge": 0
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"iconset": {
|
|
52
|
+
"default": null,
|
|
53
|
+
"autoInsert": {
|
|
54
|
+
"css": true,
|
|
55
|
+
"scripts": true,
|
|
56
|
+
"inlineScript": true,
|
|
57
|
+
"inlineCss": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"concatResource": {
|
|
61
|
+
"cacheMaxAge": 0,
|
|
62
|
+
"excluded": [],
|
|
63
|
+
"css": false,
|
|
64
|
+
"scripts": false
|
|
65
|
+
},
|
|
66
|
+
"cheerio": {
|
|
67
|
+
"loadOptions": {
|
|
68
|
+
"xml": {
|
|
69
|
+
"xmlMode": false,
|
|
70
|
+
"decodeEntities": false,
|
|
71
|
+
"recognizeSelfClosing": true
|
|
72
|
+
}
|
|
26
73
|
}
|
|
27
74
|
},
|
|
28
75
|
"prettier": {
|
|
29
76
|
"parser": "html",
|
|
30
|
-
"printWidth":
|
|
77
|
+
"printWidth": 120
|
|
31
78
|
},
|
|
32
|
-
"
|
|
79
|
+
"minifier": {
|
|
33
80
|
"removeAttributeQuotes": true,
|
|
34
81
|
"removeComments": true,
|
|
35
82
|
"removeCommentsFromCDATA": true,
|
|
@@ -46,19 +93,13 @@
|
|
|
46
93
|
"tableHeadClass": "",
|
|
47
94
|
"tableBodyClass": "table-group-divider"
|
|
48
95
|
},
|
|
49
|
-
"
|
|
50
|
-
"action": "redirect",
|
|
51
|
-
"route": true
|
|
52
|
-
},
|
|
53
|
-
"multipart": {
|
|
54
|
-
},
|
|
96
|
+
"multipart": {},
|
|
55
97
|
"cors": {},
|
|
56
98
|
"helmet": {
|
|
57
99
|
"contentSecurityPolicy": false
|
|
58
100
|
},
|
|
59
101
|
"compress": false,
|
|
60
102
|
"rateLimit": false,
|
|
61
|
-
"traceNoTemplate": false,
|
|
62
103
|
"disabled": [],
|
|
63
|
-
"dependencies": ["waibu", "waibu-static"]
|
|
104
|
+
"dependencies": ["waibu", "waibu-static", "bajo-markdown"]
|
|
64
105
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
async function doboWmpaSessionBeforeSanitizeSession (schema) {
|
|
2
|
+
const { find } = this.app.bajo.lib._
|
|
3
|
+
|
|
4
|
+
const dobo = this.app.dobo
|
|
5
|
+
let conn = find(dobo.connections, { name: schema.connection })
|
|
6
|
+
if (!conn) conn = find(dobo.connections, { name: 'memory' })
|
|
7
|
+
if (conn) schema.connection = conn.name
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default doboWmpaSessionBeforeSanitizeSession
|
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
async function checkLang (req, reply) {
|
|
2
|
+
if (!req.session) return
|
|
3
|
+
if (req.langDetector) {
|
|
4
|
+
req.session.lang = req.lang
|
|
5
|
+
await req.i18n.changeLanguage(req.session.lang)
|
|
6
|
+
return
|
|
7
|
+
}
|
|
8
|
+
if (req.session.lang) req.lang = req.session.lang
|
|
9
|
+
await req.i18n.changeLanguage(req.lang)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function checkDark (req, reply) {
|
|
13
|
+
const { isSet } = this.app.bajo
|
|
14
|
+
const key = this.config.darkMode.qsKey
|
|
15
|
+
const value = req.query[key]
|
|
16
|
+
if (isSet(value)) {
|
|
17
|
+
req.darkMode = value
|
|
18
|
+
if (req.session) req.session.darkMode = req.darkMode
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
if (isSet(req.session.darkMode)) req.darkMode = req.session.darkMode
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const waibuMpaPreParsing = {
|
|
2
25
|
level: 9,
|
|
3
|
-
handler: async function (
|
|
26
|
+
handler: async function (req, reply) {
|
|
4
27
|
const { importModule } = this.app.bajo
|
|
5
28
|
const attachI18N = await importModule('waibu:/lib/webapp-scope/attach-i18n.js')
|
|
6
29
|
await attachI18N.call(this, this.config.i18n.detectors, req, reply)
|
|
7
|
-
|
|
8
|
-
|
|
30
|
+
await checkLang.call(this, req, reply)
|
|
31
|
+
await checkDark.call(this, req, reply)
|
|
9
32
|
}
|
|
10
33
|
}
|
|
11
34
|
|
|
12
|
-
export default
|
|
35
|
+
export default waibuMpaPreParsing
|
package/bajo/init.js
ADDED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
function attrToArray (text = '', delimiter = ' ') {
|
|
2
|
-
const { map, trim, without } = this.app.bajo.lib._
|
|
3
|
-
|
|
2
|
+
const { map, trim, without, isArray } = this.app.bajo.lib._
|
|
3
|
+
if (text === true) text = ''
|
|
4
|
+
if (isArray(text)) text = text.join(delimiter)
|
|
5
|
+
return without(map(text.split(delimiter), i => trim(i)), '', undefined, null)
|
|
4
6
|
}
|
|
5
7
|
|
|
6
8
|
export default attrToArray
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
function attrToObject (text = '', delimiter = ';', kvDelimiter = ':') {
|
|
2
|
-
const { camelCase } = this.app.bajo.lib._
|
|
2
|
+
const { camelCase, isPlainObject } = this.app.bajo.lib._
|
|
3
3
|
const result = {}
|
|
4
|
+
if (isPlainObject(text)) text = this.objectToAttr(text)
|
|
5
|
+
if (text.slice(1, 3) === '%=') return text
|
|
4
6
|
const array = this.attrToArray(text, delimiter)
|
|
5
7
|
array.forEach(item => {
|
|
6
8
|
const [key, val] = this.attrToArray(item, kvDelimiter)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function attribsParse (text = '', delimiter = ' ', kvDelimiter = '=', camelCasedKey = true) {
|
|
2
|
+
const { trim, camelCase, map, isPlainObject, forOwn } = this.app.bajo.lib._
|
|
3
|
+
let attrs = []
|
|
4
|
+
if (isPlainObject(text)) {
|
|
5
|
+
forOwn(text, (v, k) => {
|
|
6
|
+
attrs.push(`${k}${kvDelimiter}"${v}"`)
|
|
7
|
+
})
|
|
8
|
+
} else attrs = map(text.split(delimiter), t => trim(t))
|
|
9
|
+
const result = {}
|
|
10
|
+
for (const attr of attrs) {
|
|
11
|
+
let [k, ...v] = map(attr.split(kvDelimiter), a => trim(a))
|
|
12
|
+
v = v.join(kvDelimiter)
|
|
13
|
+
v = v.slice(1, v.length - 1)
|
|
14
|
+
if (v === 'undefined') continue
|
|
15
|
+
if (k !== 'content' && v === '') v = true
|
|
16
|
+
// check for retainAttrKey on ALL plugins
|
|
17
|
+
let retain = false
|
|
18
|
+
for (const name of this.app.bajo.pluginNames) {
|
|
19
|
+
const plugin = this.app[name]
|
|
20
|
+
if (plugin && plugin.retainAttrKey && plugin.retainAttrKey(k)) retain = true
|
|
21
|
+
}
|
|
22
|
+
if (!retain && camelCasedKey) k = camelCase(k)
|
|
23
|
+
result[k] = v
|
|
24
|
+
}
|
|
25
|
+
return result
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default attribsParse
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function attribsStringify (obj = {}, kebabCasedKey = true) {
|
|
2
|
+
const { isSet } = this.app.bajo
|
|
3
|
+
const { forOwn, kebabCase, isArray, isPlainObject, isEmpty } = this.app.bajo.lib._
|
|
4
|
+
const attrs = []
|
|
5
|
+
forOwn(obj, (v, k) => {
|
|
6
|
+
let retain = false
|
|
7
|
+
for (const name of this.app.bajo.pluginNames) {
|
|
8
|
+
const plugin = this.app[name]
|
|
9
|
+
if (plugin && plugin.retainAttrKey && plugin.retainAttrKey(k)) retain = true
|
|
10
|
+
}
|
|
11
|
+
if (retain) {
|
|
12
|
+
if (v === true) attrs.push(k)
|
|
13
|
+
else attrs.push(`${k}="${v}"`)
|
|
14
|
+
return undefined
|
|
15
|
+
}
|
|
16
|
+
if (kebabCasedKey) k = kebabCase(k)
|
|
17
|
+
if (!isSet(v)) return undefined
|
|
18
|
+
if (['class', 'style'].includes(k) && isEmpty(v)) return undefined
|
|
19
|
+
if (isArray(v)) v = this.arrayToAttr(v)
|
|
20
|
+
if (isPlainObject(v)) v = this.objectToAttr(v)
|
|
21
|
+
if (k !== 'content' && v === true) attrs.push(k)
|
|
22
|
+
else attrs.push(`${k}="${v}"`)
|
|
23
|
+
})
|
|
24
|
+
return attrs.join(' ')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default attribsStringify
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function buildUrl ({ exclude = [], prefix = '?', base, url = '', params = {} }) {
|
|
2
|
+
const { qs } = this.app.waibu
|
|
3
|
+
const { forOwn, omit, isEmpty } = this.app.bajo.lib._
|
|
4
|
+
const qsKey = this.app.waibu.config.qsKey
|
|
5
|
+
let path
|
|
6
|
+
let hash
|
|
7
|
+
let query
|
|
8
|
+
[path = '', hash = ''] = url.split('#')
|
|
9
|
+
if (hash.includes('?')) [hash, query] = hash.split('?')
|
|
10
|
+
else [path, query] = path.split('?')
|
|
11
|
+
query = qs.parse(query) ?? {}
|
|
12
|
+
forOwn(params, (v, k) => {
|
|
13
|
+
const key = qsKey[k] ?? k
|
|
14
|
+
query[key] = v
|
|
15
|
+
})
|
|
16
|
+
query = prefix + qs.stringify(omit(query, exclude))
|
|
17
|
+
if (!isEmpty(hash)) hash = '#' + hash
|
|
18
|
+
if (!base) return path + query + hash
|
|
19
|
+
const parts = path.split('/')
|
|
20
|
+
if (base) {
|
|
21
|
+
parts.pop()
|
|
22
|
+
parts.push(base)
|
|
23
|
+
}
|
|
24
|
+
return parts.join('/') + query + hash
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default buildUrl
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const subNses = ['layout', 'template', 'partial']
|
|
2
|
+
|
|
3
|
+
function getResource (name) {
|
|
4
|
+
const { ns, path, subNs, subSubNs, qs } = this.app.bajo.breakNsPath(name)
|
|
5
|
+
const plugin = this.app.bajo.getPlugin(ns)
|
|
6
|
+
const dir = `${plugin.dir.pkg}/waibuMpa`
|
|
7
|
+
if (!subNses.includes(subNs)) throw this.error('Unknown resource \'%s\'', name)
|
|
8
|
+
const fullPath = subSubNs ? `${dir}/${subSubNs}/${subNs}${path}` : `${dir}/${subNs}${path}`
|
|
9
|
+
return { ns, subNs, subSubNs, path, qs, fullPath }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default getResource
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function groupAttrs (attribs = {}, keys = [], removeEmpty = true) {
|
|
2
|
+
const { isString, filter, omit, kebabCase, camelCase, isEmpty } = this.app.bajo.lib._
|
|
3
|
+
if (isString(keys)) keys = [keys]
|
|
4
|
+
const attr = { _: {} }
|
|
5
|
+
for (const a in attribs) {
|
|
6
|
+
for (const k of keys) {
|
|
7
|
+
if (a === k) {
|
|
8
|
+
attr._[k] = attribs[a]
|
|
9
|
+
continue
|
|
10
|
+
}
|
|
11
|
+
attr[k] = attr[k] ?? {}
|
|
12
|
+
attr[k].class = attr[k].class ?? []
|
|
13
|
+
attr[k].style = attr[k].style ?? {}
|
|
14
|
+
const _k = kebabCase(k)
|
|
15
|
+
const name = camelCase(kebabCase(a).slice(_k.length + 1))
|
|
16
|
+
if (!kebabCase(a).startsWith(k + '-')) {
|
|
17
|
+
if (!keys.includes(a)) {
|
|
18
|
+
attr._[a] = attribs[a]
|
|
19
|
+
if (a === 'class' && isString(attribs[a])) attr._.class = this.attrToArray(attr._.class)
|
|
20
|
+
if (a === 'style' && isString(attribs[a])) attr._.style = this.attrToObject(attr._.style)
|
|
21
|
+
}
|
|
22
|
+
continue
|
|
23
|
+
}
|
|
24
|
+
attr[k][name] = attribs[a]
|
|
25
|
+
if (name === 'class' && isString(attribs[a])) attr[k].class = this.attrToArray(attr[k].class)
|
|
26
|
+
if (name === 'style' && isString(attribs[a])) attr[k].style = this.attrToObject(attr[k].style)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const deleted = filter(Object.keys(attr._), m => {
|
|
30
|
+
let match
|
|
31
|
+
m = kebabCase(m)
|
|
32
|
+
for (const k of keys) {
|
|
33
|
+
if (m.startsWith(k + '-')) match = true
|
|
34
|
+
}
|
|
35
|
+
return match
|
|
36
|
+
})
|
|
37
|
+
attr._ = omit(attr._, deleted)
|
|
38
|
+
for (const k of keys) {
|
|
39
|
+
const item = attr[k]
|
|
40
|
+
if (removeEmpty && !attr._[k] && Object.keys(item).length === 2 && isEmpty(item.class) && isEmpty(item.style)) delete attr[k]
|
|
41
|
+
}
|
|
42
|
+
return attr
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default groupAttrs
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// taken from: https://stackoverflow.com/questions/52928550/js-get-list-of-all-available-standard-html-tags
|
|
2
|
+
|
|
3
|
+
const tags = 'a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,blockquote,body,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,img,input,ins,kbd,label,legend,li,link,main,map,mark,menu,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture,pre,progress,q,rp,rt,ruby,s,samp,script,section,select,slot,small,source,span,strong,style,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,u,ul,var,video,wbr'
|
|
4
|
+
const htmlTags = tags.split(',')
|
|
5
|
+
|
|
6
|
+
export default htmlTags
|