@hkdigital/lib-core 0.5.92 → 0.5.94
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 +63 -9
- package/dist/browser/info/device.js +9 -7
- package/dist/config/generators/imagetools.d.ts +14 -0
- package/dist/config/generators/imagetools.js +55 -0
- package/dist/config/imagetools.d.ts +12 -0
- package/dist/logging/README.md +15 -53
- package/dist/meta/README.md +92 -0
- package/dist/meta/components/Favicons.svelte +30 -0
- package/dist/meta/components/Favicons.svelte.d.ts +103 -0
- package/dist/meta/components/PWA.svelte +51 -0
- package/dist/meta/components/PWA.svelte.d.ts +103 -0
- package/dist/meta/components/SEO.svelte +146 -0
- package/dist/meta/components/SEO.svelte.d.ts +108 -0
- package/dist/meta/components.d.ts +3 -0
- package/dist/meta/components.js +3 -0
- package/dist/meta/config.typedef.d.ts +98 -0
- package/dist/meta/config.typedef.js +44 -0
- package/dist/meta/typedef.d.ts +3 -0
- package/dist/meta/typedef.js +14 -0
- package/dist/meta/utils/lang.d.ts +29 -0
- package/dist/meta/utils/lang.js +84 -0
- package/dist/meta/utils/robots.d.ts +1 -0
- package/dist/meta/utils/robots.js +1 -0
- package/dist/meta/utils/sitemap.d.ts +1 -0
- package/dist/meta/utils/sitemap.js +1 -0
- package/dist/meta/utils.d.ts +3 -0
- package/dist/meta/utils.js +11 -0
- package/dist/services/PATTERNS.md +476 -0
- package/dist/services/PLUGINS.md +520 -0
- package/dist/services/README.md +156 -229
- package/package.json +1 -1
- package/dist/meta/robots.d.ts +0 -1
- package/dist/meta/robots.js +0 -5
- package/dist/meta/sitemap.d.ts +0 -1
- package/dist/meta/sitemap.js +0 -5
- /package/dist/meta/{robots/index.d.ts → utils/robots/robots.d.ts} +0 -0
- /package/dist/meta/{robots/index.js → utils/robots/robots.js} +0 -0
- /package/dist/meta/{robots → utils/robots}/typedef.d.ts +0 -0
- /package/dist/meta/{robots → utils/robots}/typedef.js +0 -0
- /package/dist/meta/{sitemap/index.d.ts → utils/sitemap/sitemap.d.ts} +0 -0
- /package/dist/meta/{sitemap/index.js → utils/sitemap/sitemap.js} +0 -0
- /package/dist/meta/{sitemap → utils/sitemap}/typedef.d.ts +0 -0
- /package/dist/meta/{sitemap → utils/sitemap}/typedef.js +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export default PWA;
|
|
2
|
+
type PWA = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const PWA: import("svelte").Component<{
|
|
7
|
+
config: import("../config.typedef.js").MetaConfig;
|
|
8
|
+
}, {}, "">;
|
|
9
|
+
type $$ComponentProps = {
|
|
10
|
+
config: {
|
|
11
|
+
/**
|
|
12
|
+
* - Full app name
|
|
13
|
+
*/
|
|
14
|
+
name: string;
|
|
15
|
+
/**
|
|
16
|
+
* - Short app name (max 12 characters)
|
|
17
|
+
*/
|
|
18
|
+
shortName: string;
|
|
19
|
+
/**
|
|
20
|
+
* - App description for search engines
|
|
21
|
+
*
|
|
22
|
+
* Language and locale
|
|
23
|
+
*/
|
|
24
|
+
description: string;
|
|
25
|
+
/**
|
|
26
|
+
* Language configurations
|
|
27
|
+
*/
|
|
28
|
+
languages: Record<string, {
|
|
29
|
+
lang: string;
|
|
30
|
+
locale: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* - Default language code
|
|
34
|
+
*/
|
|
35
|
+
defaultLanguage: string;
|
|
36
|
+
/**
|
|
37
|
+
* - Default locale
|
|
38
|
+
*
|
|
39
|
+
* PWA theme and colors
|
|
40
|
+
*/
|
|
41
|
+
defaultLocale: string;
|
|
42
|
+
/**
|
|
43
|
+
* - Theme color
|
|
44
|
+
*/
|
|
45
|
+
backgroundAndThemeColor: string;
|
|
46
|
+
/**
|
|
47
|
+
* - Theme color for browser UI
|
|
48
|
+
*/
|
|
49
|
+
themeColor: string;
|
|
50
|
+
/**
|
|
51
|
+
* - Background color
|
|
52
|
+
*/
|
|
53
|
+
backgroundColor: string;
|
|
54
|
+
/**
|
|
55
|
+
* - iOS status bar style
|
|
56
|
+
*/
|
|
57
|
+
statusBarStyle: string;
|
|
58
|
+
/**
|
|
59
|
+
* - Screen orientation
|
|
60
|
+
*/
|
|
61
|
+
orientation: string;
|
|
62
|
+
/**
|
|
63
|
+
* - Disable pinch-to-zoom
|
|
64
|
+
*
|
|
65
|
+
* SEO images
|
|
66
|
+
*/
|
|
67
|
+
disablePageZoom: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* - Landscape SEO image URL (1200×630)
|
|
70
|
+
*/
|
|
71
|
+
SeoImageLandscape?: string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* - Square SEO image URL (1200×1200)
|
|
74
|
+
*
|
|
75
|
+
* Favicon images (processed by imagetools)
|
|
76
|
+
*/
|
|
77
|
+
SeoImageSquare?: string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Processed favicon images
|
|
80
|
+
*/
|
|
81
|
+
faviconImages: Array<{
|
|
82
|
+
src: string;
|
|
83
|
+
width: number;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Processed apple-touch-icon images
|
|
87
|
+
*
|
|
88
|
+
* Site configuration
|
|
89
|
+
*/
|
|
90
|
+
appleTouchIcons: Array<{
|
|
91
|
+
src: string;
|
|
92
|
+
width: number;
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Routes for sitemap.xml
|
|
96
|
+
*/
|
|
97
|
+
siteRoutes: import("../typedef.js").SitemapRoute[];
|
|
98
|
+
/**
|
|
99
|
+
* Robots.txt configuration
|
|
100
|
+
*/
|
|
101
|
+
robotsConfig: import("../typedef.js").RobotsConfig;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* SEO component
|
|
4
|
+
*
|
|
5
|
+
* Generates SEO meta tags, Open Graph tags, and hreflang links.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {import('../typedef.js').MetaConfig} MetaConfig
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SEO component props
|
|
12
|
+
*
|
|
13
|
+
* @typedef {Object} SEOProps
|
|
14
|
+
* @property {MetaConfig} config - Configuration object
|
|
15
|
+
* @property {string} [title] - Page title (defaults to config name)
|
|
16
|
+
* @property {string} [description]
|
|
17
|
+
* Page description (defaults to config description)
|
|
18
|
+
* @property {string} [url] - Canonical URL for this page
|
|
19
|
+
* @property {string} [image]
|
|
20
|
+
* Social media preview image URL (defaults to landscape SEO image)
|
|
21
|
+
* @property {string} [imageAlt] - Alt text for social media image
|
|
22
|
+
* @property {string} [type] - Open Graph type (default: 'website')
|
|
23
|
+
* @property {string} [locale]
|
|
24
|
+
* Content locale (auto-detected from URL or defaults to config)
|
|
25
|
+
* @property {string} [siteName]
|
|
26
|
+
* Site name for Open Graph (defaults to config name)
|
|
27
|
+
* @property {Record<string, string>} [alternateUrls]
|
|
28
|
+
* Alternate language URLs for hreflang tags
|
|
29
|
+
* @property {string} [robots]
|
|
30
|
+
* Robots meta directives (e.g., 'noindex, nofollow')
|
|
31
|
+
* @property {boolean} [noAiTraining]
|
|
32
|
+
* Prevent AI training on this page content
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** @type {SEOProps} */
|
|
36
|
+
let {
|
|
37
|
+
config,
|
|
38
|
+
title,
|
|
39
|
+
description,
|
|
40
|
+
url = undefined,
|
|
41
|
+
image,
|
|
42
|
+
imageAlt,
|
|
43
|
+
type = 'website',
|
|
44
|
+
locale = undefined,
|
|
45
|
+
siteName,
|
|
46
|
+
alternateUrls = undefined,
|
|
47
|
+
robots = undefined,
|
|
48
|
+
noAiTraining = false
|
|
49
|
+
} = $props();
|
|
50
|
+
|
|
51
|
+
// Extract config values
|
|
52
|
+
const {
|
|
53
|
+
name: defaultTitle,
|
|
54
|
+
description: defaultDescription,
|
|
55
|
+
SeoImageLandscape,
|
|
56
|
+
SeoImageSquare,
|
|
57
|
+
defaultLocale,
|
|
58
|
+
languages
|
|
59
|
+
} = config;
|
|
60
|
+
|
|
61
|
+
// Use the landscape image as default (best for most platforms)
|
|
62
|
+
const defaultSeoImage = SeoImageLandscape || undefined;
|
|
63
|
+
|
|
64
|
+
// Apply defaults from config
|
|
65
|
+
title = title ?? defaultTitle;
|
|
66
|
+
description = description ?? defaultDescription;
|
|
67
|
+
image = image ?? defaultSeoImage;
|
|
68
|
+
imageAlt = imageAlt ?? title;
|
|
69
|
+
siteName = siteName ?? defaultTitle;
|
|
70
|
+
|
|
71
|
+
// Use locale from prop or fall back to config default
|
|
72
|
+
const finalLocale = locale || defaultLocale;
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<svelte:head>
|
|
76
|
+
<!-- Page title (overrides %title% from app.html) -->
|
|
77
|
+
<title>{title}</title>
|
|
78
|
+
|
|
79
|
+
<!-- Basic SEO -->
|
|
80
|
+
<meta name="description" content={description}>
|
|
81
|
+
|
|
82
|
+
<!-- Robots directives -->
|
|
83
|
+
{#if robots}
|
|
84
|
+
<meta name="robots" content={robots}>
|
|
85
|
+
{/if}
|
|
86
|
+
|
|
87
|
+
<!-- AI training and reading restrictions -->
|
|
88
|
+
{#if noAiTraining}
|
|
89
|
+
<!-- Google AI -->
|
|
90
|
+
<meta name="google-extended" content="noindex, nofollow">
|
|
91
|
+
<!-- OpenAI (ChatGPT) -->
|
|
92
|
+
<meta name="OAI-SearchBot" content="noindex, nofollow">
|
|
93
|
+
<!-- Common Crawl -->
|
|
94
|
+
<meta name="CCBot" content="noindex, nofollow">
|
|
95
|
+
<!-- Anthropic Claude -->
|
|
96
|
+
<meta name="anthropic-ai" content="noindex, nofollow">
|
|
97
|
+
<!-- General AI crawlers -->
|
|
98
|
+
<meta name="robots" content="noai, noimageai">
|
|
99
|
+
{/if}
|
|
100
|
+
|
|
101
|
+
<!-- Open Graph / Facebook / LinkedIn / Discord -->
|
|
102
|
+
<meta property="og:type" content={type}>
|
|
103
|
+
<meta property="og:title" content={title}>
|
|
104
|
+
<meta property="og:description" content={description}>
|
|
105
|
+
<meta property="og:site_name" content={siteName}>
|
|
106
|
+
<meta property="og:locale" content={finalLocale}>
|
|
107
|
+
|
|
108
|
+
{#if url}
|
|
109
|
+
<meta property="og:url" content={url}>
|
|
110
|
+
<link rel="canonical" href={url}>
|
|
111
|
+
{/if}
|
|
112
|
+
|
|
113
|
+
{#if image}
|
|
114
|
+
<meta property="og:image" content={image}>
|
|
115
|
+
<meta property="og:image:alt" content={imageAlt}>
|
|
116
|
+
<!-- Image metadata (dimensions from preprocessor) -->
|
|
117
|
+
{#if image === SeoImageLandscape}
|
|
118
|
+
<meta property="og:image:width" content="1200">
|
|
119
|
+
<meta property="og:image:height" content="630">
|
|
120
|
+
<meta property="og:image:type" content="image/jpeg">
|
|
121
|
+
{/if}
|
|
122
|
+
{/if}
|
|
123
|
+
|
|
124
|
+
<!-- Additional square image for platforms that prefer it -->
|
|
125
|
+
{#if SeoImageSquare && SeoImageSquare !== image}
|
|
126
|
+
<meta property="og:image" content={SeoImageSquare}>
|
|
127
|
+
<meta property="og:image:width" content="1200">
|
|
128
|
+
<meta property="og:image:height" content="1200">
|
|
129
|
+
<meta property="og:image:type" content="image/jpeg">
|
|
130
|
+
{/if}
|
|
131
|
+
|
|
132
|
+
<!-- Alternate locales for Open Graph -->
|
|
133
|
+
{#each Object.entries(languages) as [code, config]}
|
|
134
|
+
{#if config.locale !== finalLocale}
|
|
135
|
+
<meta property="og:locale:alternate" content={config.locale}>
|
|
136
|
+
{/if}
|
|
137
|
+
{/each}
|
|
138
|
+
|
|
139
|
+
<!-- Alternate language URLs (hreflang) -->
|
|
140
|
+
{#if alternateUrls}
|
|
141
|
+
{#each Object.entries(alternateUrls) as [lang, href]}
|
|
142
|
+
<link rel="alternate" hreflang={lang} href={href}>
|
|
143
|
+
{/each}
|
|
144
|
+
{/if}
|
|
145
|
+
|
|
146
|
+
</svelte:head>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export default SEO;
|
|
2
|
+
type SEO = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<SEOProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const SEO: import("svelte").Component<{
|
|
7
|
+
/**
|
|
8
|
+
* - Configuration object
|
|
9
|
+
*/
|
|
10
|
+
config: import("../config.typedef.js").MetaConfig;
|
|
11
|
+
/**
|
|
12
|
+
* - Page title (defaults to config name)
|
|
13
|
+
*/
|
|
14
|
+
title?: string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Page description (defaults to config description)
|
|
17
|
+
*/
|
|
18
|
+
description?: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* - Canonical URL for this page
|
|
21
|
+
*/
|
|
22
|
+
url?: string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Social media preview image URL (defaults to landscape SEO image)
|
|
25
|
+
*/
|
|
26
|
+
image?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* - Alt text for social media image
|
|
29
|
+
*/
|
|
30
|
+
imageAlt?: string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* - Open Graph type (default: 'website')
|
|
33
|
+
*/
|
|
34
|
+
type?: string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Content locale (auto-detected from URL or defaults to config)
|
|
37
|
+
*/
|
|
38
|
+
locale?: string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Site name for Open Graph (defaults to config name)
|
|
41
|
+
*/
|
|
42
|
+
siteName?: string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Alternate language URLs for hreflang tags
|
|
45
|
+
*/
|
|
46
|
+
alternateUrls?: Record<string, string> | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Robots meta directives (e.g., 'noindex, nofollow')
|
|
49
|
+
*/
|
|
50
|
+
robots?: string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Prevent AI training on this page content
|
|
53
|
+
*/
|
|
54
|
+
noAiTraining?: boolean | undefined;
|
|
55
|
+
}, {}, "">;
|
|
56
|
+
/**
|
|
57
|
+
* SEO component props
|
|
58
|
+
*/
|
|
59
|
+
type SEOProps = {
|
|
60
|
+
/**
|
|
61
|
+
* - Configuration object
|
|
62
|
+
*/
|
|
63
|
+
config: import("../config.typedef.js").MetaConfig;
|
|
64
|
+
/**
|
|
65
|
+
* - Page title (defaults to config name)
|
|
66
|
+
*/
|
|
67
|
+
title?: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Page description (defaults to config description)
|
|
70
|
+
*/
|
|
71
|
+
description?: string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* - Canonical URL for this page
|
|
74
|
+
*/
|
|
75
|
+
url?: string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Social media preview image URL (defaults to landscape SEO image)
|
|
78
|
+
*/
|
|
79
|
+
image?: string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* - Alt text for social media image
|
|
82
|
+
*/
|
|
83
|
+
imageAlt?: string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* - Open Graph type (default: 'website')
|
|
86
|
+
*/
|
|
87
|
+
type?: string | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Content locale (auto-detected from URL or defaults to config)
|
|
90
|
+
*/
|
|
91
|
+
locale?: string | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Site name for Open Graph (defaults to config name)
|
|
94
|
+
*/
|
|
95
|
+
siteName?: string | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* Alternate language URLs for hreflang tags
|
|
98
|
+
*/
|
|
99
|
+
alternateUrls?: Record<string, string> | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* Robots meta directives (e.g., 'noindex, nofollow')
|
|
102
|
+
*/
|
|
103
|
+
robots?: string | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Prevent AI training on this page content
|
|
106
|
+
*/
|
|
107
|
+
noAiTraining?: boolean | undefined;
|
|
108
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
declare const _default: {};
|
|
2
|
+
export default _default;
|
|
3
|
+
/**
|
|
4
|
+
* App identity
|
|
5
|
+
*/
|
|
6
|
+
export type MetaConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* - Full app name
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
/**
|
|
12
|
+
* - Short app name (max 12 characters)
|
|
13
|
+
*/
|
|
14
|
+
shortName: string;
|
|
15
|
+
/**
|
|
16
|
+
* - App description for search engines
|
|
17
|
+
*
|
|
18
|
+
* Language and locale
|
|
19
|
+
*/
|
|
20
|
+
description: string;
|
|
21
|
+
/**
|
|
22
|
+
* Language configurations
|
|
23
|
+
*/
|
|
24
|
+
languages: Record<string, {
|
|
25
|
+
lang: string;
|
|
26
|
+
locale: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* - Default language code
|
|
30
|
+
*/
|
|
31
|
+
defaultLanguage: string;
|
|
32
|
+
/**
|
|
33
|
+
* - Default locale
|
|
34
|
+
*
|
|
35
|
+
* PWA theme and colors
|
|
36
|
+
*/
|
|
37
|
+
defaultLocale: string;
|
|
38
|
+
/**
|
|
39
|
+
* - Theme color
|
|
40
|
+
*/
|
|
41
|
+
backgroundAndThemeColor: string;
|
|
42
|
+
/**
|
|
43
|
+
* - Theme color for browser UI
|
|
44
|
+
*/
|
|
45
|
+
themeColor: string;
|
|
46
|
+
/**
|
|
47
|
+
* - Background color
|
|
48
|
+
*/
|
|
49
|
+
backgroundColor: string;
|
|
50
|
+
/**
|
|
51
|
+
* - iOS status bar style
|
|
52
|
+
*/
|
|
53
|
+
statusBarStyle: string;
|
|
54
|
+
/**
|
|
55
|
+
* - Screen orientation
|
|
56
|
+
*/
|
|
57
|
+
orientation: string;
|
|
58
|
+
/**
|
|
59
|
+
* - Disable pinch-to-zoom
|
|
60
|
+
*
|
|
61
|
+
* SEO images
|
|
62
|
+
*/
|
|
63
|
+
disablePageZoom: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* - Landscape SEO image URL (1200×630)
|
|
66
|
+
*/
|
|
67
|
+
SeoImageLandscape?: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* - Square SEO image URL (1200×1200)
|
|
70
|
+
*
|
|
71
|
+
* Favicon images (processed by imagetools)
|
|
72
|
+
*/
|
|
73
|
+
SeoImageSquare?: string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Processed favicon images
|
|
76
|
+
*/
|
|
77
|
+
faviconImages: Array<{
|
|
78
|
+
src: string;
|
|
79
|
+
width: number;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Processed apple-touch-icon images
|
|
83
|
+
*
|
|
84
|
+
* Site configuration
|
|
85
|
+
*/
|
|
86
|
+
appleTouchIcons: Array<{
|
|
87
|
+
src: string;
|
|
88
|
+
width: number;
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* Routes for sitemap.xml
|
|
92
|
+
*/
|
|
93
|
+
siteRoutes: import("./utils/sitemap/typedef.js").SitemapRoute[];
|
|
94
|
+
/**
|
|
95
|
+
* Robots.txt configuration
|
|
96
|
+
*/
|
|
97
|
+
robotsConfig: import("./utils/robots/typedef.js").RobotsConfig;
|
|
98
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta configuration type definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} MetaConfig
|
|
7
|
+
*
|
|
8
|
+
* App identity
|
|
9
|
+
* @property {string} name - Full app name
|
|
10
|
+
* @property {string} shortName - Short app name (max 12 characters)
|
|
11
|
+
* @property {string} description - App description for search engines
|
|
12
|
+
*
|
|
13
|
+
* Language and locale
|
|
14
|
+
* @property {Record<string, {lang: string, locale: string}>} languages
|
|
15
|
+
* Language configurations
|
|
16
|
+
* @property {string} defaultLanguage - Default language code
|
|
17
|
+
* @property {string} defaultLocale - Default locale
|
|
18
|
+
*
|
|
19
|
+
* PWA theme and colors
|
|
20
|
+
* @property {string} backgroundAndThemeColor - Theme color
|
|
21
|
+
* @property {string} themeColor - Theme color for browser UI
|
|
22
|
+
* @property {string} backgroundColor - Background color
|
|
23
|
+
* @property {string} statusBarStyle - iOS status bar style
|
|
24
|
+
* @property {string} orientation - Screen orientation
|
|
25
|
+
* @property {boolean} disablePageZoom - Disable pinch-to-zoom
|
|
26
|
+
*
|
|
27
|
+
* SEO images
|
|
28
|
+
* @property {string} [SeoImageLandscape] - Landscape SEO image URL (1200×630)
|
|
29
|
+
* @property {string} [SeoImageSquare] - Square SEO image URL (1200×1200)
|
|
30
|
+
*
|
|
31
|
+
* Favicon images (processed by imagetools)
|
|
32
|
+
* @property {Array<{src: string, width: number}>} faviconImages
|
|
33
|
+
* Processed favicon images
|
|
34
|
+
* @property {Array<{src: string, width: number}>} appleTouchIcons
|
|
35
|
+
* Processed apple-touch-icon images
|
|
36
|
+
*
|
|
37
|
+
* Site configuration
|
|
38
|
+
* @property {import('./utils/sitemap/typedef.js').SitemapRoute[]} siteRoutes
|
|
39
|
+
* Routes for sitemap.xml
|
|
40
|
+
* @property {import('./utils/robots/typedef.js').RobotsConfig} robotsConfig
|
|
41
|
+
* Robots.txt configuration
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
export default {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for meta utilities
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all typedefs from utils subfolder for convenient importing
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Re-export config typedefs
|
|
8
|
+
export * from './config.typedef.js';
|
|
9
|
+
|
|
10
|
+
// Re-export robots typedefs
|
|
11
|
+
export * from './utils/robots/typedef.js';
|
|
12
|
+
|
|
13
|
+
// Re-export sitemap typedefs
|
|
14
|
+
export * from './utils/sitemap/typedef.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create language utilities configured with your app config
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} config - Configuration object
|
|
5
|
+
* @param {Record<string, {lang: string, locale: string}>} config.languages
|
|
6
|
+
* Language configurations
|
|
7
|
+
* @param {string} config.defaultLanguage - Default language code
|
|
8
|
+
* @param {string} config.name - App name (for %title% injection)
|
|
9
|
+
* @param {string} config.description - App description
|
|
10
|
+
*
|
|
11
|
+
* @returns {{
|
|
12
|
+
* getLangFromPath: Function,
|
|
13
|
+
* injectLang: Function,
|
|
14
|
+
* handleLang: Function
|
|
15
|
+
* }}
|
|
16
|
+
*/
|
|
17
|
+
export function createLangUtils(config: {
|
|
18
|
+
languages: Record<string, {
|
|
19
|
+
lang: string;
|
|
20
|
+
locale: string;
|
|
21
|
+
}>;
|
|
22
|
+
defaultLanguage: string;
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
}): {
|
|
26
|
+
getLangFromPath: Function;
|
|
27
|
+
injectLang: Function;
|
|
28
|
+
handleLang: Function;
|
|
29
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create language utilities configured with your app config
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} config - Configuration object
|
|
5
|
+
* @param {Record<string, {lang: string, locale: string}>} config.languages
|
|
6
|
+
* Language configurations
|
|
7
|
+
* @param {string} config.defaultLanguage - Default language code
|
|
8
|
+
* @param {string} config.name - App name (for %title% injection)
|
|
9
|
+
* @param {string} config.description - App description
|
|
10
|
+
*
|
|
11
|
+
* @returns {{
|
|
12
|
+
* getLangFromPath: Function,
|
|
13
|
+
* injectLang: Function,
|
|
14
|
+
* handleLang: Function
|
|
15
|
+
* }}
|
|
16
|
+
*/
|
|
17
|
+
export function createLangUtils(config) {
|
|
18
|
+
const { languages, defaultLanguage, name, description } = config;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Extract language code from URL pathname
|
|
22
|
+
*
|
|
23
|
+
* @param {string} pathname - URL pathname (e.g., '/en/shop')
|
|
24
|
+
*
|
|
25
|
+
* @returns {{
|
|
26
|
+
* langCode: string,
|
|
27
|
+
* lang: string,
|
|
28
|
+
* locale: string
|
|
29
|
+
* }}
|
|
30
|
+
*/
|
|
31
|
+
function getLangFromPath(pathname) {
|
|
32
|
+
const match = pathname.match(/^\/([a-z]{2}(?:-[a-z]{2})?)\//i);
|
|
33
|
+
const langCode = match ? match[1].toLowerCase() : defaultLanguage;
|
|
34
|
+
|
|
35
|
+
const langConfig = languages[langCode] || languages[defaultLanguage];
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
langCode,
|
|
39
|
+
lang: langConfig.lang,
|
|
40
|
+
locale: langConfig.locale
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Transform HTML to inject language, title, and description
|
|
46
|
+
*
|
|
47
|
+
* @param {string} html - HTML string with placeholders
|
|
48
|
+
* @param {string} lang - Language code (e.g., 'en-GB')
|
|
49
|
+
*
|
|
50
|
+
* @returns {string} HTML with values injected
|
|
51
|
+
*/
|
|
52
|
+
function injectLang(html, lang) {
|
|
53
|
+
return html
|
|
54
|
+
.replace('%lang%', lang)
|
|
55
|
+
.replace('%title%', name)
|
|
56
|
+
.replace('%description%', description);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* SvelteKit hook handler for language detection
|
|
61
|
+
*
|
|
62
|
+
* @param {object} event - SvelteKit event object
|
|
63
|
+
* @param {Function} resolve - SvelteKit resolve function
|
|
64
|
+
*
|
|
65
|
+
* @returns {Promise<Response>}
|
|
66
|
+
*/
|
|
67
|
+
async function handleLang(event, resolve) {
|
|
68
|
+
const { langCode, lang, locale } = getLangFromPath(event.url.pathname);
|
|
69
|
+
|
|
70
|
+
event.locals.langCode = langCode;
|
|
71
|
+
event.locals.lang = lang;
|
|
72
|
+
event.locals.locale = locale;
|
|
73
|
+
|
|
74
|
+
return resolve(event, {
|
|
75
|
+
transformPageChunk: ({ html }) => injectLang(html, lang)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
getLangFromPath,
|
|
81
|
+
injectLang,
|
|
82
|
+
handleLang
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateRobotsTxt, isHostAllowed } from "./robots/robots.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateRobotsTxt, isHostAllowed } from './robots/robots.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateSitemap } from "./sitemap/sitemap.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateSitemap } from './sitemap/sitemap.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta utilities for SEO, PWA, and favicons
|
|
3
|
+
*
|
|
4
|
+
* @module @hkdigital/lib-core/meta
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Language utilities
|
|
8
|
+
export { createLangUtils } from './utils/lang.js';
|
|
9
|
+
|
|
10
|
+
export { generateRobotsTxt, isHostAllowed } from './utils/robots.js';
|
|
11
|
+
export { generateSitemap } from './utils/sitemap.js';
|