@stellar-expert/ui-framework 1.14.13 → 1.14.15
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/interaction/qr-code.js +2 -12
- package/meta/page-meta-tags.js +78 -54
- package/package.json +1 -1
package/interaction/qr-code.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, {useMemo, useRef} from 'react'
|
|
2
|
-
import
|
|
2
|
+
import {QRCodeCanvas} from 'qrcode.react'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* QrCode renderer
|
|
@@ -14,7 +14,7 @@ export const QrCode = React.memo(function QrCode({value, caption, size = 320, em
|
|
|
14
14
|
const foreground = useMemo(() => getComputedStyle(document.documentElement).getPropertyValue('--color-primary'))
|
|
15
15
|
const containerRef = useRef()
|
|
16
16
|
return <div className="text-center" ref={containerRef}>
|
|
17
|
-
<
|
|
17
|
+
<QRCodeCanvas value={value} size={256} level="Q" includeMargin imageSettings={embedImage(embeddedImage, embeddedSize, size)}
|
|
18
18
|
fgColor={foreground} style={{width: size + 'px', height: size + 'px', display: 'block', margin: 'auto'}}/>
|
|
19
19
|
{!!caption && <div className="text-small dimmed condensed word-break">{caption}</div>}
|
|
20
20
|
</div>
|
|
@@ -32,14 +32,4 @@ function embedImage(src, size, qrSize) {
|
|
|
32
32
|
width: size,
|
|
33
33
|
excavate: true
|
|
34
34
|
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function download(container, caption) {
|
|
38
|
-
const canvas = container.querySelector('canvas')
|
|
39
|
-
const link = document.createElement('a')
|
|
40
|
-
link.href = canvas.toDataURL()
|
|
41
|
-
link.download = caption ? caption.replace(/\W+/g, '-') + '-qr.png' : `qr${new Date().getTime()}.png`
|
|
42
|
-
document.body.appendChild(link)
|
|
43
|
-
link.click()
|
|
44
|
-
document.body.removeChild(link)
|
|
45
35
|
}
|
package/meta/page-meta-tags.js
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
import {useEffect} from 'react'
|
|
2
2
|
import isEqual from 'react-fast-compare'
|
|
3
3
|
|
|
4
|
-
const {origin} = window.location
|
|
5
|
-
const domain = origin.replace(/https?:\/\//, '')
|
|
6
|
-
|
|
7
4
|
const metaProps = {
|
|
8
5
|
serviceTitle: '',
|
|
9
6
|
description: '',
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
image: '',
|
|
8
|
+
imageEndpoint: '',
|
|
9
|
+
origin: '',
|
|
10
|
+
domain: ''
|
|
13
11
|
}
|
|
14
12
|
|
|
13
|
+
setOrigin(window.location.origin)
|
|
14
|
+
|
|
15
15
|
/**
|
|
16
16
|
* Initialize default meta properties for the application
|
|
17
|
-
* @param {{serviceTitle: String, description: String,
|
|
17
|
+
* @param {{serviceTitle: String, description: String, origin: String, [image]: String, [imageEndpoint]: String}} appMetaProps
|
|
18
18
|
*/
|
|
19
19
|
export function initMeta(appMetaProps) {
|
|
20
|
-
|
|
20
|
+
const {origin, ...props} = appMetaProps
|
|
21
|
+
Object.assign(metaProps, props)
|
|
22
|
+
if (origin) {
|
|
23
|
+
setOrigin(origin)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setOrigin(origin) {
|
|
28
|
+
metaProps.origin = origin
|
|
29
|
+
metaProps.domain = origin.replace(/https?:\/\//, '')
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
function formatPageTitle(title) {
|
|
@@ -47,48 +56,35 @@ function generateDescriptionMeta({description}) {
|
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
|
|
50
|
-
function
|
|
59
|
+
function generateOpenGraphMeta({description, title, image}, canonicalUrl) {
|
|
60
|
+
//imageEndpoint
|
|
51
61
|
return {
|
|
52
|
-
locator: '
|
|
62
|
+
locator: 'property',
|
|
53
63
|
tags: [
|
|
54
|
-
{name: '
|
|
55
|
-
{name: '
|
|
56
|
-
{name: '
|
|
57
|
-
{name: '
|
|
58
|
-
{name: '
|
|
64
|
+
{name: 'og:title', content: formatPageTitle(title)},
|
|
65
|
+
{name: 'og:url', content: canonicalUrl},
|
|
66
|
+
{name: 'og:site_name', content: formatPageTitle(metaProps.serviceTitle)},
|
|
67
|
+
{name: 'og:description', content: description || metaProps.description},
|
|
68
|
+
{name: 'og:type', content: 'website'},
|
|
69
|
+
{name: 'og:image:width', content: 1200},
|
|
70
|
+
{name: 'og:image:height', content: 630},
|
|
71
|
+
{name: 'og:image', content: formatPageImage(image, canonicalUrl)}
|
|
59
72
|
]
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
|
|
63
|
-
function generateOpenGraphMeta({description, title, facebookImage}, canonicalUrl) {
|
|
64
|
-
let tags = [
|
|
65
|
-
{name: 'og:title', content: formatPageTitle(title)},
|
|
66
|
-
{name: 'og:url', content: canonicalUrl},
|
|
67
|
-
{name: 'og:site_name', content: formatPageTitle(metaProps.serviceTitle)},
|
|
68
|
-
{name: 'og:description', content: description || metaProps.description},
|
|
69
|
-
{name: 'og:type', content: 'website'},
|
|
70
|
-
{name: 'og:image:width', content: 1200},
|
|
71
|
-
{name: 'og:image:height', content: 630},
|
|
72
|
-
{name: 'og:image', content: facebookImage || metaProps.facebookImage}
|
|
73
|
-
]
|
|
74
|
-
return {
|
|
75
|
-
locator: 'property',
|
|
76
|
-
tags
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
76
|
function generateItemPropSchema({description, title, image}) {
|
|
81
77
|
return {
|
|
82
78
|
locator: 'itemprop',
|
|
83
79
|
tags: [
|
|
84
80
|
{name: 'name', content: title},
|
|
85
81
|
{name: 'description', content: description || metaProps.description},
|
|
86
|
-
{name: 'image', content: image || metaProps.
|
|
82
|
+
{name: 'image', content: image || metaProps.image}
|
|
87
83
|
]
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
function generateLdJsonSchema({title}) {
|
|
87
|
+
function generateLdJsonSchema({title, description, image}, canonicalUrl) {
|
|
92
88
|
return {
|
|
93
89
|
tag: 'script',
|
|
94
90
|
locator: 'type',
|
|
@@ -97,10 +93,15 @@ function generateLdJsonSchema({title}) {
|
|
|
97
93
|
name: 'application/ld+json',
|
|
98
94
|
content: JSON.stringify({
|
|
99
95
|
'@context': 'http://schema.org',
|
|
100
|
-
'@type': '
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
'@type': 'WebPage',
|
|
97
|
+
name: formatPageTitle(title),
|
|
98
|
+
description: description || metaProps.description,
|
|
99
|
+
url: canonicalUrl,
|
|
100
|
+
thumbnailUrl: formatPageImage(image, canonicalUrl),
|
|
101
|
+
publisher: {
|
|
102
|
+
'@type': 'ProfilePage',
|
|
103
|
+
name: metaProps.serviceTitle
|
|
104
|
+
}
|
|
104
105
|
})
|
|
105
106
|
}
|
|
106
107
|
]
|
|
@@ -145,23 +146,37 @@ function removeTag(selector) {
|
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
|
|
149
|
+
function formatCanonicalUrl() {
|
|
150
|
+
return metaProps.origin + window.location.pathname// + location.search
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function formatPageImage(image, canonicalUrl) {
|
|
154
|
+
if (image)
|
|
155
|
+
return image
|
|
156
|
+
if (metaProps.imageEndpoint)
|
|
157
|
+
return metaProps.imageEndpoint + canonicalUrl.replace(metaProps.origin, '')
|
|
158
|
+
return metaProps.image
|
|
159
|
+
}
|
|
160
|
+
|
|
148
161
|
let pageMeta = {}
|
|
149
162
|
|
|
150
|
-
const tagReplacerPipeline = [
|
|
163
|
+
const tagReplacerPipeline = [
|
|
164
|
+
generateCanonicalLink,
|
|
165
|
+
generateDescriptionMeta,
|
|
166
|
+
generateOpenGraphMeta,
|
|
167
|
+
generateLdJsonSchema
|
|
168
|
+
] // generateItemPropSchema
|
|
151
169
|
|
|
152
170
|
/**
|
|
153
171
|
* Update page metadata tags
|
|
154
172
|
* @param {PageMeta} meta - Page metadata
|
|
155
173
|
*/
|
|
156
|
-
|
|
174
|
+
function setPageMetadata(meta) {
|
|
157
175
|
if (isEqual(pageMeta, meta))
|
|
158
176
|
return
|
|
159
|
-
|
|
177
|
+
//generate canonical URL
|
|
178
|
+
const canonicalUrl = formatCanonicalUrl()
|
|
160
179
|
document.title = formatPageTitle(meta.title)
|
|
161
|
-
if (meta.image) {
|
|
162
|
-
meta.facebookImage = meta.image
|
|
163
|
-
meta.twitterImage = meta.image
|
|
164
|
-
}
|
|
165
180
|
for (const replacer of tagReplacerPipeline) {
|
|
166
181
|
replaceMetaTags(replacer(meta, canonicalUrl))
|
|
167
182
|
}
|
|
@@ -175,12 +190,11 @@ export function setPageMetadata(meta) {
|
|
|
175
190
|
* Reset page metadata tags to their default values
|
|
176
191
|
* @param {PageMeta} meta - Page metadata
|
|
177
192
|
*/
|
|
178
|
-
|
|
193
|
+
function resetPageMetadata(meta) {
|
|
179
194
|
setPageMetadata({
|
|
180
195
|
title: metaProps.serviceTitle,
|
|
181
196
|
description: metaProps.description,
|
|
182
|
-
|
|
183
|
-
facebookImage: metaProps.facebookImage
|
|
197
|
+
image: metaProps.image
|
|
184
198
|
})
|
|
185
199
|
//TODO: add logic to cleanup custom page meta tags on page unload
|
|
186
200
|
}
|
|
@@ -188,22 +202,32 @@ export function resetPageMetadata(meta) {
|
|
|
188
202
|
/**
|
|
189
203
|
* React hook for setting page metadata
|
|
190
204
|
* @param {PageMeta} meta - Page metadata
|
|
191
|
-
* @param {*[]} dependencies
|
|
192
205
|
*/
|
|
193
|
-
export function usePageMetadata(meta
|
|
206
|
+
export function usePageMetadata(meta) {
|
|
194
207
|
useEffect(() => {
|
|
195
208
|
setPageMetadata(meta)
|
|
196
209
|
return () => resetPageMetadata(meta)
|
|
197
|
-
}, [JSON.stringify(meta),
|
|
210
|
+
}, [JSON.stringify(meta), [formatCanonicalUrl()]])
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function setPageNoIndex(noIndex) {
|
|
214
|
+
if (!noIndex) {
|
|
215
|
+
removeTag('meta[name=robots]')
|
|
216
|
+
} else {
|
|
217
|
+
replaceMetaTags({
|
|
218
|
+
locator: 'name',
|
|
219
|
+
tags: [
|
|
220
|
+
{name: 'robots', content: 'noindex,nofollow'}
|
|
221
|
+
]
|
|
222
|
+
})
|
|
223
|
+
}
|
|
198
224
|
}
|
|
199
225
|
|
|
200
226
|
/**
|
|
201
227
|
* @typedef {Object} PageMeta
|
|
202
228
|
* @property {String} title - Page title
|
|
203
229
|
* @property {String} description - Contents description
|
|
204
|
-
* @property {String} [
|
|
205
|
-
* @property {String} [facebookImage] - Facebook image url
|
|
206
|
-
* @property {String} [image] - Sets the image for both the Twitter image and the Facebook image
|
|
230
|
+
* @property {String} [image] - Page image url
|
|
207
231
|
* @property {MetaTagReplacement} [customMeta] - Custom metadata tags
|
|
208
232
|
*/
|
|
209
233
|
|