@dxtmisha/wiki 0.24.3 → 0.25.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.
- package/package.json +7 -7
- package/src/classes/WikiStorybookItem.ts +24 -0
- package/src/media/descriptions/wikiDescriptions.ts +28 -0
- package/src/media/descriptions/wikiDescriptionsAccordion.ts +158 -0
- package/src/media/descriptions/wikiDescriptionsActionSheet.ts +211 -0
- package/src/media/descriptions/wikiDescriptionsActions.ts +161 -0
- package/src/media/descriptions/wikiDescriptionsAnchor.ts +42 -0
- package/src/media/descriptions/wikiDescriptionsArrow.ts +181 -0
- package/src/media/descriptions/wikiDescriptionsBlock.ts +97 -0
- package/src/media/descriptions/wikiDescriptionsButton.ts +0 -1
- package/src/media/descriptions/wikiDescriptionsCell.ts +2 -1
- package/src/media/descriptions/wikiDescriptionsChipGroup.ts +168 -0
- package/src/media/descriptions/wikiDescriptionsDialog.ts +182 -0
- package/src/media/descriptions/wikiDescriptionsField.ts +2 -0
- package/src/media/descriptions/wikiDescriptionsImage.ts +41 -6
- package/src/media/descriptions/wikiDescriptionsInput.ts +257 -0
- package/src/media/descriptions/wikiDescriptionsMenu.ts +123 -0
- package/src/media/descriptions/wikiDescriptionsModal.ts +145 -0
- package/src/media/descriptions/wikiDescriptionsMotionTransform.ts +2 -6
- package/src/media/descriptions/wikiDescriptionsSelect.ts +209 -0
- package/src/media/descriptions/wikiDescriptionsSelectValue.ts +78 -0
- package/src/media/descriptions/wikiDescriptionsTextareaAutosize.ts +50 -0
- package/src/media/descriptions/wikiDescriptionsTooltip.ts +89 -0
- package/src/media/functional/en/conversions.mdx +67 -0
- package/src/media/functional/en/dataUtils.mdx +25 -0
- package/src/media/functional/en/datetimeRef.mdx +1 -1
- package/src/media/functional/en/eventRef.mdx +1 -1
- package/src/media/functional/en/executionUtils.mdx +58 -0
- package/src/media/functional/en/geoFlagRef.mdx +1 -1
- package/src/media/functional/en/geoIntlRef.mdx +1 -1
- package/src/media/functional/en/geoRef.mdx +2 -2
- package/src/media/functional/en/meta.mdx +1206 -0
- package/src/media/functional/en/metaManager.mdx +376 -0
- package/src/media/functional/en/metaOg.mdx +694 -0
- package/src/media/functional/en/metaTwitter.mdx +853 -0
- package/src/media/functional/en/reactive.mdx +40 -0
- package/src/media/functional/en/refTypes.mdx +1 -1
- package/src/media/functional/en/useApiRef.mdx +5 -5
- package/src/media/functional/en/useMeta.mdx +431 -0
- package/src/media/functional/en/validationUtils.mdx +11 -0
- package/src/media/functional/ru/conversions.mdx +67 -0
- package/src/media/functional/ru/dataUtils.mdx +25 -0
- package/src/media/functional/ru/datetimeRef.mdx +2 -2
- package/src/media/functional/ru/eventRef.mdx +1 -1
- package/src/media/functional/ru/executionUtils.mdx +58 -0
- package/src/media/functional/ru/geoFlagRef.mdx +1 -1
- package/src/media/functional/ru/geoIntl.mdx +2 -2
- package/src/media/functional/ru/geoIntlRef.mdx +1 -1
- package/src/media/functional/ru/geoRef.mdx +2 -2
- package/src/media/functional/ru/listTypes.mdx +1 -1
- package/src/media/functional/ru/meta.mdx +1330 -0
- package/src/media/functional/ru/metaManager.mdx +376 -0
- package/src/media/functional/ru/metaOg.mdx +694 -0
- package/src/media/functional/ru/metaTwitter.mdx +853 -0
- package/src/media/functional/ru/reactive.mdx +40 -0
- package/src/media/functional/ru/refTypes.mdx +2 -2
- package/src/media/functional/ru/useApiRef.mdx +5 -5
- package/src/media/functional/ru/useMeta.mdx +431 -0
- package/src/media/functional/ru/validationUtils.mdx +11 -0
- package/src/media/mdx/Accordion/accordion.en.mdx +59 -0
- package/src/media/mdx/Accordion/accordion.ru.mdx +59 -0
- package/src/media/mdx/Accordion/slots.en.mdx +6 -0
- package/src/media/mdx/Accordion/slots.ru.mdx +6 -0
- package/src/media/mdx/Accordion/wikiMdxAccordion.ts +25 -0
- package/src/media/mdx/ActionSheet/actionSheet.en.mdx +61 -0
- package/src/media/mdx/ActionSheet/actionSheet.ru.mdx +61 -0
- package/src/media/mdx/ActionSheet/touchClose.en.mdx +21 -0
- package/src/media/mdx/ActionSheet/touchClose.ru.mdx +21 -0
- package/src/media/mdx/ActionSheet/wikiMdxActionSheet.ts +25 -0
- package/src/media/mdx/Actions/actions.en.mdx +48 -0
- package/src/media/mdx/Actions/actions.ru.mdx +48 -0
- package/src/media/mdx/Actions/flexible.en.mdx +19 -0
- package/src/media/mdx/Actions/flexible.ru.mdx +19 -0
- package/src/media/mdx/Actions/list.en.mdx +50 -0
- package/src/media/mdx/Actions/list.ru.mdx +50 -0
- package/src/media/mdx/Actions/wikiMdxActions.ts +31 -0
- package/src/media/mdx/Anchor/anchor.en.mdx +34 -0
- package/src/media/mdx/Anchor/anchor.ru.mdx +34 -0
- package/src/media/mdx/Anchor/expose.go.en.mdx +6 -0
- package/src/media/mdx/Anchor/expose.go.ru.mdx +6 -0
- package/src/media/mdx/Anchor/hide.en.mdx +28 -0
- package/src/media/mdx/Anchor/hide.ru.mdx +28 -0
- package/src/media/mdx/Anchor/isCopy.en.mdx +23 -0
- package/src/media/mdx/Anchor/isCopy.ru.mdx +23 -0
- package/src/media/mdx/Anchor/scroll.en.mdx +34 -0
- package/src/media/mdx/Anchor/scroll.ru.mdx +35 -0
- package/src/media/mdx/Anchor/wikiMdxAnchor.ts +43 -0
- package/src/media/mdx/Arrow/arrow.en.mdx +33 -0
- package/src/media/mdx/Arrow/arrow.ru.mdx +33 -0
- package/src/media/mdx/Arrow/wikiMdxArrow.ts +19 -0
- package/src/media/mdx/Block/block.en.mdx +42 -0
- package/src/media/mdx/Block/block.ru.mdx +42 -0
- package/src/media/mdx/Block/wikiMdxBlock.ts +19 -0
- package/src/media/mdx/ChipGroup/chipGroup.en.mdx +51 -0
- package/src/media/mdx/ChipGroup/chipGroup.ru.mdx +51 -0
- package/src/media/mdx/ChipGroup/selected.en.mdx +50 -0
- package/src/media/mdx/ChipGroup/selected.ru.mdx +50 -0
- package/src/media/mdx/ChipGroup/wikiMdxChipGroup.ts +25 -0
- package/src/media/mdx/Dialog/buttons.en.mdx +45 -0
- package/src/media/mdx/Dialog/buttons.ru.mdx +45 -0
- package/src/media/mdx/Dialog/dialog.en.mdx +66 -0
- package/src/media/mdx/Dialog/dialog.ru.mdx +65 -0
- package/src/media/mdx/Dialog/events.en.mdx +63 -0
- package/src/media/mdx/Dialog/events.ru.mdx +63 -0
- package/src/media/mdx/Dialog/states.en.mdx +58 -0
- package/src/media/mdx/Dialog/states.ru.mdx +57 -0
- package/src/media/mdx/Dialog/wikiMdxDialog.ts +37 -0
- package/src/media/mdx/Field/arrows.en.mdx +22 -6
- package/src/media/mdx/Field/arrows.ru.mdx +22 -6
- package/src/media/mdx/Field/slots.en.mdx +0 -13
- package/src/media/mdx/Field/slots.ru.mdx +0 -13
- package/src/media/mdx/Image/img-tag.en.mdx +105 -0
- package/src/media/mdx/Image/img-tag.ru.mdx +105 -0
- package/src/media/mdx/Image/wikiMdxImage.ts +6 -0
- package/src/media/mdx/Input/currency.en.mdx +38 -0
- package/src/media/mdx/Input/currency.ru.mdx +38 -0
- package/src/media/mdx/Input/date.en.mdx +53 -0
- package/src/media/mdx/Input/date.ru.mdx +53 -0
- package/src/media/mdx/Input/input.en.mdx +143 -0
- package/src/media/mdx/Input/input.ru.mdx +71 -0
- package/src/media/mdx/Input/mask.en.mdx +30 -0
- package/src/media/mdx/Input/mask.ru.mdx +30 -0
- package/src/media/mdx/Input/number.en.mdx +41 -0
- package/src/media/mdx/Input/number.ru.mdx +41 -0
- package/src/media/mdx/Input/type.en.mdx +26 -0
- package/src/media/mdx/Input/type.ru.mdx +26 -0
- package/src/media/mdx/Input/wikiMdxInput.ts +49 -0
- package/src/media/mdx/Menu/event.updateValue.en.mdx +29 -0
- package/src/media/mdx/Menu/event.updateValue.ru.mdx +30 -0
- package/src/media/mdx/Menu/expose.navigation.en.mdx +12 -0
- package/src/media/mdx/Menu/expose.navigation.ru.mdx +12 -0
- package/src/media/mdx/Menu/navigation.en.mdx +56 -0
- package/src/media/mdx/Menu/navigation.ru.mdx +56 -0
- package/src/media/mdx/Menu/slots.control.en.mdx +65 -0
- package/src/media/mdx/Menu/slots.control.ru.mdx +65 -0
- package/src/media/mdx/Menu/slots.en.mdx +2 -24
- package/src/media/mdx/Menu/slots.ru.mdx +2 -24
- package/src/media/mdx/Menu/wikiMdxMenu.ts +27 -3
- package/src/media/mdx/Modal/differences.en.mdx +130 -0
- package/src/media/mdx/Modal/differences.ru.mdx +65 -0
- package/src/media/mdx/Modal/modal.en.mdx +63 -0
- package/src/media/mdx/Modal/modal.ru.mdx +63 -0
- package/src/media/mdx/Modal/wikiMdxModal.ts +25 -0
- package/src/media/mdx/MotionTransform/expose.motionTransformElement.en.mdx +13 -0
- package/src/media/mdx/MotionTransform/expose.motionTransformElement.ru.mdx +14 -0
- package/src/media/mdx/MotionTransform/wikiMdxMotionTransform.ts +6 -0
- package/src/media/mdx/Select/select.en.mdx +69 -0
- package/src/media/mdx/Select/select.ru.mdx +69 -0
- package/src/media/mdx/Select/wikiMdxSelect.ts +19 -0
- package/src/media/mdx/SelectValue/selectValue.en.mdx +64 -0
- package/src/media/mdx/SelectValue/selectValue.ru.mdx +64 -0
- package/src/media/mdx/SelectValue/wikiMdxSelectValue.ts +19 -0
- package/src/media/mdx/TextareaAutosize/textarea-autosize.en.mdx +65 -0
- package/src/media/mdx/TextareaAutosize/textarea-autosize.ru.mdx +65 -0
- package/src/media/mdx/TextareaAutosize/wikiMdxTextareaAutosize.ts +19 -0
- package/src/media/mdx/Tooltip/event.tooltip.en.mdx +7 -0
- package/src/media/mdx/Tooltip/event.tooltip.ru.mdx +8 -0
- package/src/media/mdx/Tooltip/slot.control.en.mdx +14 -0
- package/src/media/mdx/Tooltip/slot.control.ru.mdx +14 -0
- package/src/media/mdx/Tooltip/tooltip.en.mdx +34 -0
- package/src/media/mdx/Tooltip/tooltip.ru.mdx +34 -0
- package/src/media/mdx/Tooltip/wikiMdxTooltip.ts +31 -0
- package/src/media/mdx/Window/classes.ru.mdx +1 -1
- package/src/media/mdx/event/events.actions.en.mdx +44 -0
- package/src/media/mdx/event/events.actions.ru.mdx +44 -0
- package/src/media/mdx/event/events.inputStandard.en.mdx +6 -0
- package/src/media/mdx/event/events.inputStandard.ru.mdx +6 -0
- package/src/media/mdx/event/wikiMdxEvent.ts +20 -8
- package/src/media/mdx/expose/expose.descriptionId.en.mdx +6 -0
- package/src/media/mdx/expose/expose.descriptionId.ru.mdx +6 -0
- package/src/media/mdx/expose/expose.id.en.mdx +6 -0
- package/src/media/mdx/expose/expose.id.ru.mdx +6 -0
- package/src/media/mdx/expose/expose.labelId.en.mdx +6 -0
- package/src/media/mdx/expose/expose.labelId.ru.mdx +6 -0
- package/src/media/mdx/expose/wikiMdxExpose.ts +18 -0
- package/src/media/mdx/slot/body.en.mdx +6 -0
- package/src/media/mdx/slot/body.ru.mdx +6 -0
- package/src/media/mdx/slot/headline.en.mdx +7 -0
- package/src/media/mdx/slot/headline.ru.mdx +6 -0
- package/src/media/mdx/slot/leading.en.mdx +7 -0
- package/src/media/mdx/slot/leading.ru.mdx +7 -0
- package/src/media/mdx/slot/secondary.en.mdx +5 -0
- package/src/media/mdx/slot/secondary.ru.mdx +5 -0
- package/src/media/mdx/slot/trailing.en.mdx +7 -0
- package/src/media/mdx/slot/trailing.ru.mdx +7 -0
- package/src/media/mdx/slot/wikiMdxSlot.ts +30 -0
- package/src/media/mdx/style/isSkeleton.en.mdx +2 -2
- package/src/media/mdx/style/isSkeleton.ru.mdx +2 -2
- package/src/media/mdx/value/v-model-selected.en.mdx +28 -0
- package/src/media/mdx/value/v-model-selected.ru.mdx +28 -0
- package/src/media/mdx/value/v-model.en.mdx +26 -0
- package/src/media/mdx/value/v-model.ru.mdx +26 -0
- package/src/media/mdx/value/wikiMdxValue.ts +24 -3
- package/src/media/mdx/wikiMdx.ts +29 -1
- package/src/media/props/wiki.ts +42 -0
- package/src/media/props/wikiActions.ts +43 -0
- package/src/media/props/wikiActionsInclude.ts +62 -0
- package/src/media/props/wikiAnchor.ts +84 -0
- package/src/media/props/wikiAria.ts +102 -0
- package/src/media/props/wikiArrow.ts +24 -0
- package/src/media/props/wikiArrowInclude.ts +45 -0
- package/src/media/props/wikiBarsInclude.ts +80 -0
- package/src/media/props/wikiChipGroup.ts +39 -0
- package/src/media/props/wikiDialog.ts +34 -0
- package/src/media/props/wikiField.ts +0 -21
- package/src/media/props/wikiFieldCounterInclude.ts +78 -0
- package/src/media/props/wikiForm.ts +248 -0
- package/src/media/props/wikiHook.ts +20 -0
- package/src/media/props/wikiIcon.ts +3 -3
- package/src/media/props/wikiIconInclude.ts +319 -0
- package/src/media/props/wikiImage.ts +71 -19
- package/src/media/props/wikiInformation.ts +160 -0
- package/src/media/props/wikiInput.ts +34 -0
- package/src/media/props/wikiListItem.ts +20 -0
- package/src/media/props/wikiMask.ts +0 -10
- package/src/media/props/wikiMaskInclude.ts +54 -0
- package/src/media/props/wikiMenu.ts +0 -10
- package/src/media/props/wikiMotionTransform.ts +0 -10
- package/src/media/props/wikiOption.ts +113 -0
- package/src/media/props/wikiSelect.ts +68 -0
- package/src/media/props/wikiSelectValue.ts +30 -0
- package/src/media/props/wikiStatus.ts +29 -41
- package/src/media/props/wikiStyle.ts +154 -243
- package/src/media/props/wikiTechnical.ts +65 -0
- package/src/media/props/wikiText.ts +57 -0
- package/src/media/props/wikiTooltip.ts +53 -0
- package/src/media/props/wikiValue.ts +14 -203
- package/src/media/props/wikiWindow.ts +0 -31
- package/src/styles/storybookStyle.scss +3 -1
- package/src/types/storybookTypes.ts +26 -4
|
@@ -0,0 +1,1206 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/en/Classes/Meta'/>
|
|
4
|
+
|
|
5
|
+
# Meta Class
|
|
6
|
+
|
|
7
|
+
A unified class for managing all types of meta tags: standard HTML, Open Graph, and Twitter Card. Provides a single interface for working with SEO optimization and social networks, automatically synchronizing changes across all platforms.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Unified API** — single entry point for all types of meta tags
|
|
12
|
+
- **Automatic Synchronization** — changes in Meta are automatically applied to Open Graph and Twitter Card
|
|
13
|
+
- **Title Management** — support for title suffix (e.g., "Title - Site Name")
|
|
14
|
+
- **Full Integration** — combines MetaManager, MetaOg, and MetaTwitter
|
|
15
|
+
- **Simplified Interface** — reduces code needed to set meta tags
|
|
16
|
+
- **Keywords Support** — works with keywords as string or array
|
|
17
|
+
- **Robots Directives** — manages indexing and crawling
|
|
18
|
+
- **SSR Compatible** — generates HTML for server-side rendering
|
|
19
|
+
|
|
20
|
+
## Constructor
|
|
21
|
+
|
|
22
|
+
### `constructor`
|
|
23
|
+
|
|
24
|
+
Creates a Meta instance with integrated Open Graph and Twitter Card support. Automatically initializes internal MetaOg and MetaTwitter instances.
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import { Meta } from '@dxtmisha/functional'
|
|
28
|
+
|
|
29
|
+
// Create a unified meta tags manager
|
|
30
|
+
const meta = new Meta()
|
|
31
|
+
|
|
32
|
+
// The class automatically manages:
|
|
33
|
+
// - Standard HTML meta tags (description, keywords, author, robots, canonical)
|
|
34
|
+
// - Open Graph tags (og:title, og:description, og:image, og:url, og:site_name, og:locale)
|
|
35
|
+
// - Twitter Card tags (twitter:card, twitter:title, twitter:description, twitter:image, twitter:site)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Data Retrieval Methods
|
|
39
|
+
|
|
40
|
+
### `getTitle`
|
|
41
|
+
|
|
42
|
+
Gets the page title without suffix.
|
|
43
|
+
|
|
44
|
+
**Returns:** `string` — page title
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const meta = new Meta()
|
|
48
|
+
|
|
49
|
+
// Set title with suffix
|
|
50
|
+
meta.setSuffix('My Site')
|
|
51
|
+
meta.setTitle('Home Page')
|
|
52
|
+
|
|
53
|
+
// document.title = "Home Page - My Site"
|
|
54
|
+
|
|
55
|
+
// Get clean title (without suffix)
|
|
56
|
+
const title = meta.getTitle()
|
|
57
|
+
// "Home Page"
|
|
58
|
+
|
|
59
|
+
// Use in navigation
|
|
60
|
+
const breadcrumb = meta.getTitle()
|
|
61
|
+
|
|
62
|
+
// Check if set
|
|
63
|
+
if (meta.getTitle()) {
|
|
64
|
+
console.log('Title is set')
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `getKeywords`
|
|
69
|
+
|
|
70
|
+
Gets the keywords meta tag.
|
|
71
|
+
|
|
72
|
+
**Returns:** `string` — comma-separated keywords
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
const meta = new Meta()
|
|
76
|
+
|
|
77
|
+
const keywords = meta.getKeywords()
|
|
78
|
+
// "web development, javascript, vue, react"
|
|
79
|
+
|
|
80
|
+
// Convert to array
|
|
81
|
+
const keywordsArray = keywords.split(', ')
|
|
82
|
+
|
|
83
|
+
// Check for keyword
|
|
84
|
+
if (meta.getKeywords().includes('javascript')) {
|
|
85
|
+
console.log('Page about JavaScript')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Use for filtering
|
|
89
|
+
const tags = meta.getKeywords().split(', ')
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `getDescription`
|
|
93
|
+
|
|
94
|
+
Gets the description meta tag.
|
|
95
|
+
|
|
96
|
+
**Returns:** `string` — page description
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const meta = new Meta()
|
|
100
|
+
|
|
101
|
+
const description = meta.getDescription()
|
|
102
|
+
// "Complete guide to web development"
|
|
103
|
+
|
|
104
|
+
// Check length
|
|
105
|
+
if (meta.getDescription().length > 160) {
|
|
106
|
+
console.warn('Description too long for Google')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Use in preview
|
|
110
|
+
const preview = meta.getDescription().substring(0, 100)
|
|
111
|
+
|
|
112
|
+
// For structured data
|
|
113
|
+
const schema = {
|
|
114
|
+
description: meta.getDescription()
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `getImage`
|
|
119
|
+
|
|
120
|
+
Gets the Open Graph image URL.
|
|
121
|
+
|
|
122
|
+
**Returns:** `string` — image URL
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const meta = new Meta()
|
|
126
|
+
|
|
127
|
+
const imageUrl = meta.getImage()
|
|
128
|
+
// "https://example.com/images/preview.jpg"
|
|
129
|
+
|
|
130
|
+
// Preload
|
|
131
|
+
const img = new Image()
|
|
132
|
+
img.src = meta.getImage()
|
|
133
|
+
|
|
134
|
+
// Use in sharing
|
|
135
|
+
const shareData = {
|
|
136
|
+
title: meta.getTitle(),
|
|
137
|
+
text: meta.getDescription(),
|
|
138
|
+
image: meta.getImage()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Check if set
|
|
142
|
+
if (!meta.getImage()) {
|
|
143
|
+
console.warn('Social media image not set')
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### `getCanonical`
|
|
148
|
+
|
|
149
|
+
Gets the canonical URL.
|
|
150
|
+
|
|
151
|
+
**Returns:** `string` — canonical URL
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const meta = new Meta()
|
|
155
|
+
|
|
156
|
+
const canonicalUrl = meta.getCanonical()
|
|
157
|
+
// "https://example.com/page"
|
|
158
|
+
|
|
159
|
+
// Check match with current URL
|
|
160
|
+
if (meta.getCanonical() !== window.location.href) {
|
|
161
|
+
console.log('Canonical URL differs from current')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Use for redirects
|
|
165
|
+
const canonical = meta.getCanonical()
|
|
166
|
+
|
|
167
|
+
// For sitemap
|
|
168
|
+
const url = meta.getCanonical()
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `getRobots`
|
|
172
|
+
|
|
173
|
+
Gets the robots meta tag value.
|
|
174
|
+
|
|
175
|
+
**Returns:** `MetaRobots` — robots directive
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
const meta = new Meta()
|
|
179
|
+
|
|
180
|
+
const robots = meta.getRobots()
|
|
181
|
+
// "index, follow"
|
|
182
|
+
|
|
183
|
+
// Check indexing
|
|
184
|
+
if (meta.getRobots().includes('noindex')) {
|
|
185
|
+
console.log('Page should not be indexed')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Conditional logic
|
|
189
|
+
const isIndexable = !meta.getRobots().includes('noindex')
|
|
190
|
+
|
|
191
|
+
// For debugging
|
|
192
|
+
console.log('Robots directive:', meta.getRobots())
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### `getAuthor`
|
|
196
|
+
|
|
197
|
+
Gets the author meta tag.
|
|
198
|
+
|
|
199
|
+
**Returns:** `string` — author name
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
const meta = new Meta()
|
|
203
|
+
|
|
204
|
+
const author = meta.getAuthor()
|
|
205
|
+
// "John Doe"
|
|
206
|
+
|
|
207
|
+
// Display author info
|
|
208
|
+
console.log(`Author: ${meta.getAuthor()}`)
|
|
209
|
+
|
|
210
|
+
// For structured data
|
|
211
|
+
const articleSchema = {
|
|
212
|
+
author: {
|
|
213
|
+
name: meta.getAuthor()
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check authorship
|
|
218
|
+
if (meta.getAuthor()) {
|
|
219
|
+
console.log('Content has an author')
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `getSiteName`
|
|
224
|
+
|
|
225
|
+
Gets the Open Graph site name.
|
|
226
|
+
|
|
227
|
+
**Returns:** `string` — site name
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
const meta = new Meta()
|
|
231
|
+
|
|
232
|
+
const siteName = meta.getSiteName()
|
|
233
|
+
// "My Blog"
|
|
234
|
+
|
|
235
|
+
// Use in title
|
|
236
|
+
document.title = `${meta.getTitle()} | ${meta.getSiteName()}`
|
|
237
|
+
|
|
238
|
+
// For branding
|
|
239
|
+
const brandName = meta.getSiteName()
|
|
240
|
+
|
|
241
|
+
// In footer
|
|
242
|
+
const footerText = `© 2024 ${meta.getSiteName()}`
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `getLocale`
|
|
246
|
+
|
|
247
|
+
Gets the Open Graph locale.
|
|
248
|
+
|
|
249
|
+
**Returns:** `string` — locale (e.g., 'en_US')
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
const meta = new Meta()
|
|
253
|
+
|
|
254
|
+
const locale = meta.getLocale()
|
|
255
|
+
// "en_US"
|
|
256
|
+
|
|
257
|
+
// Determine language
|
|
258
|
+
const language = meta.getLocale().split('_')[0] // "en"
|
|
259
|
+
|
|
260
|
+
// Use for i18n
|
|
261
|
+
if (meta.getLocale().startsWith('en')) {
|
|
262
|
+
console.log('English content')
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// For hreflang
|
|
266
|
+
const lang = meta.getLocale().replace('_', '-').toLowerCase()
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### `getOg`
|
|
270
|
+
|
|
271
|
+
Gets the MetaOg instance for advanced Open Graph operations.
|
|
272
|
+
|
|
273
|
+
**Returns:** `MetaOg` — MetaOg class instance
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
const meta = new Meta()
|
|
277
|
+
|
|
278
|
+
// Get access to MetaOg
|
|
279
|
+
const og = meta.getOg()
|
|
280
|
+
|
|
281
|
+
// Use specific Open Graph methods
|
|
282
|
+
og.setType(MetaOpenGraphType.article)
|
|
283
|
+
|
|
284
|
+
// Access all MetaOg methods
|
|
285
|
+
og.getType() // 'article'
|
|
286
|
+
|
|
287
|
+
// Set additional OG tags
|
|
288
|
+
meta.getOg().setType(MetaOpenGraphType.video)
|
|
289
|
+
|
|
290
|
+
// Chaining calls
|
|
291
|
+
meta.getOg()
|
|
292
|
+
.setType(MetaOpenGraphType.article)
|
|
293
|
+
.setLocale('en_US')
|
|
294
|
+
|
|
295
|
+
// Use for specific settings
|
|
296
|
+
const setupArticle = () => {
|
|
297
|
+
meta.setTitle('Article')
|
|
298
|
+
meta.setDescription('Description')
|
|
299
|
+
|
|
300
|
+
// Specific Open Graph settings
|
|
301
|
+
meta.getOg().setType(MetaOpenGraphType.article)
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### `getTwitter`
|
|
306
|
+
|
|
307
|
+
Gets the MetaTwitter instance for advanced Twitter Card operations.
|
|
308
|
+
|
|
309
|
+
**Returns:** `MetaTwitter` — MetaTwitter class instance
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
const meta = new Meta()
|
|
313
|
+
|
|
314
|
+
// Get access to MetaTwitter
|
|
315
|
+
const twitter = meta.getTwitter()
|
|
316
|
+
|
|
317
|
+
// Use specific Twitter Card methods
|
|
318
|
+
twitter.setCard(MetaTwitterCard.summaryLargeImage)
|
|
319
|
+
|
|
320
|
+
// Access all MetaTwitter methods
|
|
321
|
+
twitter.getCard() // 'summary_large_image'
|
|
322
|
+
|
|
323
|
+
// Set additional Twitter tags
|
|
324
|
+
meta.getTwitter().setCard(MetaTwitterCard.player)
|
|
325
|
+
|
|
326
|
+
// Chaining calls
|
|
327
|
+
meta.getTwitter()
|
|
328
|
+
.setCard(MetaTwitterCard.summaryLargeImage)
|
|
329
|
+
.setCreator('@author')
|
|
330
|
+
|
|
331
|
+
// Use for specific settings
|
|
332
|
+
const setupVideo = () => {
|
|
333
|
+
meta.setTitle('Video')
|
|
334
|
+
meta.setDescription('Video description')
|
|
335
|
+
|
|
336
|
+
// Specific Twitter Card settings
|
|
337
|
+
meta.getTwitter().setCard(MetaTwitterCard.player)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Set creator (not available directly through Meta)
|
|
341
|
+
meta.getTwitter().setCreator('@john_doe')
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Data Setting Methods
|
|
345
|
+
|
|
346
|
+
### `setTitle`
|
|
347
|
+
|
|
348
|
+
Sets the page title with automatic suffix addition and updates Open Graph and Twitter Card.
|
|
349
|
+
|
|
350
|
+
**Parameters:**
|
|
351
|
+
- `title: string` — page title (without suffix)
|
|
352
|
+
|
|
353
|
+
**Returns:** `this` — for chaining calls
|
|
354
|
+
|
|
355
|
+
```javascript
|
|
356
|
+
const meta = new Meta()
|
|
357
|
+
|
|
358
|
+
// Set suffix (usually site name)
|
|
359
|
+
meta.setSuffix('My Site')
|
|
360
|
+
|
|
361
|
+
// Set title
|
|
362
|
+
meta.setTitle('Home Page')
|
|
363
|
+
// document.title = "Home Page - My Site"
|
|
364
|
+
// og:title = "Home Page - My Site"
|
|
365
|
+
// twitter:title = "Home Page - My Site"
|
|
366
|
+
|
|
367
|
+
// Without suffix
|
|
368
|
+
const meta2 = new Meta()
|
|
369
|
+
meta2.setTitle('Page without suffix')
|
|
370
|
+
// document.title = "Page without suffix"
|
|
371
|
+
|
|
372
|
+
// Dynamic update
|
|
373
|
+
router.afterEach((to) => {
|
|
374
|
+
meta.setTitle(to.meta.title)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
// For different pages
|
|
378
|
+
meta.setTitle('About Us')
|
|
379
|
+
meta.setTitle('Contact')
|
|
380
|
+
meta.setTitle('Blog')
|
|
381
|
+
|
|
382
|
+
// Chaining
|
|
383
|
+
meta
|
|
384
|
+
.setTitle('New Page')
|
|
385
|
+
.setDescription('Page description')
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### `setKeywords`
|
|
389
|
+
|
|
390
|
+
Sets the keywords meta tag. Accepts string or array.
|
|
391
|
+
|
|
392
|
+
**Parameters:**
|
|
393
|
+
- `keywords: string | string[]` — keywords
|
|
394
|
+
|
|
395
|
+
**Returns:** `this` — for chaining calls
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
const meta = new Meta()
|
|
399
|
+
|
|
400
|
+
// String
|
|
401
|
+
meta.setKeywords('web development, javascript, vue, react')
|
|
402
|
+
|
|
403
|
+
// Array
|
|
404
|
+
meta.setKeywords(['web development', 'javascript', 'vue', 'react'])
|
|
405
|
+
// Result: "web development, javascript, vue, react"
|
|
406
|
+
|
|
407
|
+
// From page data
|
|
408
|
+
const page = {
|
|
409
|
+
tags: ['javascript', 'tutorial', 'web']
|
|
410
|
+
}
|
|
411
|
+
meta.setKeywords(page.tags)
|
|
412
|
+
|
|
413
|
+
// Dynamic addition
|
|
414
|
+
const existingKeywords = meta.getKeywords().split(', ')
|
|
415
|
+
const newKeywords = [...existingKeywords, 'new', 'keywords']
|
|
416
|
+
meta.setKeywords(newKeywords)
|
|
417
|
+
|
|
418
|
+
// Conditional addition
|
|
419
|
+
const keywords = ['web']
|
|
420
|
+
if (isJavaScriptArticle) {
|
|
421
|
+
keywords.push('javascript')
|
|
422
|
+
}
|
|
423
|
+
meta.setKeywords(keywords)
|
|
424
|
+
|
|
425
|
+
// Note: while keywords are less important for modern SEO,
|
|
426
|
+
// they can be used for internal search
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### `setDescription`
|
|
430
|
+
|
|
431
|
+
Sets the description meta tag.
|
|
432
|
+
|
|
433
|
+
**Parameters:**
|
|
434
|
+
- `description: string` — page description
|
|
435
|
+
|
|
436
|
+
**Returns:** `this` — for chaining calls
|
|
437
|
+
|
|
438
|
+
```javascript
|
|
439
|
+
const meta = new Meta()
|
|
440
|
+
|
|
441
|
+
// Set description
|
|
442
|
+
meta.setDescription('Complete guide to web development with code examples and practical exercises')
|
|
443
|
+
|
|
444
|
+
// From content data
|
|
445
|
+
meta.setDescription(article.excerpt)
|
|
446
|
+
|
|
447
|
+
// Truncate long text
|
|
448
|
+
const longDescription = article.content
|
|
449
|
+
const shortDescription = longDescription.substring(0, 160)
|
|
450
|
+
meta.setDescription(shortDescription)
|
|
451
|
+
|
|
452
|
+
// Remove HTML tags
|
|
453
|
+
const plainText = article.html.replace(/<[^>]*>/g, '')
|
|
454
|
+
meta.setDescription(plainText.substring(0, 160))
|
|
455
|
+
|
|
456
|
+
// Chaining
|
|
457
|
+
meta
|
|
458
|
+
.setDescription('Page description')
|
|
459
|
+
.setKeywords(['web', 'dev'])
|
|
460
|
+
|
|
461
|
+
// Recommendations:
|
|
462
|
+
// - Google displays ~155-160 characters
|
|
463
|
+
// - Should contain keywords
|
|
464
|
+
// - Should be unique for each page
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### `setImage`
|
|
468
|
+
|
|
469
|
+
Sets the image for Open Graph and Twitter Card simultaneously.
|
|
470
|
+
|
|
471
|
+
**Parameters:**
|
|
472
|
+
- `image: string` — image URL
|
|
473
|
+
|
|
474
|
+
**Returns:** `this` — for chaining calls
|
|
475
|
+
|
|
476
|
+
```javascript
|
|
477
|
+
const meta = new Meta()
|
|
478
|
+
|
|
479
|
+
// Set image
|
|
480
|
+
meta.setImage('https://example.com/images/preview.jpg')
|
|
481
|
+
// Updates og:image and twitter:image
|
|
482
|
+
|
|
483
|
+
// Absolute URL
|
|
484
|
+
const imageUrl = new URL('/images/social-preview.jpg', window.location.origin).href
|
|
485
|
+
meta.setImage(imageUrl)
|
|
486
|
+
|
|
487
|
+
// From content data
|
|
488
|
+
meta.setImage(article.coverImage)
|
|
489
|
+
|
|
490
|
+
// Fallback image
|
|
491
|
+
meta.setImage(page.image || '/images/default-preview.jpg')
|
|
492
|
+
|
|
493
|
+
// For different pages
|
|
494
|
+
if (isHomePage) {
|
|
495
|
+
meta.setImage('/images/home-preview.jpg')
|
|
496
|
+
} else if (isArticle) {
|
|
497
|
+
meta.setImage(article.image)
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Chaining
|
|
501
|
+
meta
|
|
502
|
+
.setImage('https://example.com/image.jpg')
|
|
503
|
+
.setTitle('Title')
|
|
504
|
+
|
|
505
|
+
// Recommended size: 1200x630 px
|
|
506
|
+
// Minimum size: 600x315 px
|
|
507
|
+
// Formats: JPG, PNG, WebP
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### `setCanonical`
|
|
511
|
+
|
|
512
|
+
Sets the canonical URL and automatically updates og:url and twitter:url.
|
|
513
|
+
|
|
514
|
+
**Parameters:**
|
|
515
|
+
- `canonical: string` — canonical URL
|
|
516
|
+
|
|
517
|
+
**Returns:** `this` — for chaining calls
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
const meta = new Meta()
|
|
521
|
+
|
|
522
|
+
// Set canonical
|
|
523
|
+
meta.setCanonical('https://example.com/page')
|
|
524
|
+
// Updates:
|
|
525
|
+
// - <link rel="canonical" href="https://example.com/page">
|
|
526
|
+
// - og:url = "https://example.com/page"
|
|
527
|
+
// - twitter:url = "https://example.com/page"
|
|
528
|
+
|
|
529
|
+
// Current URL
|
|
530
|
+
meta.setCanonical(window.location.href)
|
|
531
|
+
|
|
532
|
+
// Clean parameters
|
|
533
|
+
const cleanUrl = `${window.location.origin}${window.location.pathname}`
|
|
534
|
+
meta.setCanonical(cleanUrl)
|
|
535
|
+
|
|
536
|
+
// For pagination (all pages point to first)
|
|
537
|
+
meta.setCanonical('https://example.com/articles')
|
|
538
|
+
|
|
539
|
+
// For SPA
|
|
540
|
+
router.afterEach((to) => {
|
|
541
|
+
const url = `https://example.com${to.path}`
|
|
542
|
+
meta.setCanonical(url)
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
// For duplicate content
|
|
546
|
+
meta.setCanonical(originalArticleUrl)
|
|
547
|
+
|
|
548
|
+
// Chaining
|
|
549
|
+
meta
|
|
550
|
+
.setCanonical('https://example.com/page')
|
|
551
|
+
.setTitle('Title')
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### `setRobots`
|
|
555
|
+
|
|
556
|
+
Sets the robots meta tag to control indexing.
|
|
557
|
+
|
|
558
|
+
**Parameters:**
|
|
559
|
+
- `robots: MetaRobots` — robots directive
|
|
560
|
+
|
|
561
|
+
**Returns:** `this` — for chaining calls
|
|
562
|
+
|
|
563
|
+
```javascript
|
|
564
|
+
import { Meta, MetaRobots } from '@dxtmisha/functional'
|
|
565
|
+
|
|
566
|
+
const meta = new Meta()
|
|
567
|
+
|
|
568
|
+
// Allow indexing (default)
|
|
569
|
+
meta.setRobots(MetaRobots.indexFollow)
|
|
570
|
+
// <meta name="robots" content="index, follow">
|
|
571
|
+
|
|
572
|
+
// Prevent indexing
|
|
573
|
+
meta.setRobots(MetaRobots.noindexNofollow)
|
|
574
|
+
// <meta name="robots" content="noindex, nofollow">
|
|
575
|
+
|
|
576
|
+
// Index but don't follow links
|
|
577
|
+
meta.setRobots(MetaRobots.indexNofollow)
|
|
578
|
+
|
|
579
|
+
// Don't index but follow links
|
|
580
|
+
meta.setRobots(MetaRobots.noindexFollow)
|
|
581
|
+
|
|
582
|
+
// Prevent caching
|
|
583
|
+
meta.setRobots(MetaRobots.noarchive)
|
|
584
|
+
|
|
585
|
+
// Don't show snippet
|
|
586
|
+
meta.setRobots(MetaRobots.nosnippet)
|
|
587
|
+
|
|
588
|
+
// Conditional setting
|
|
589
|
+
if (isDraftPage) {
|
|
590
|
+
meta.setRobots(MetaRobots.noindexNofollow)
|
|
591
|
+
} else {
|
|
592
|
+
meta.setRobots(MetaRobots.indexFollow)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// For private pages
|
|
596
|
+
meta.setRobots(MetaRobots.noindexNofollow)
|
|
597
|
+
|
|
598
|
+
// For pages with duplicate content
|
|
599
|
+
meta.setRobots(MetaRobots.noindex)
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### `setAuthor`
|
|
603
|
+
|
|
604
|
+
Sets the author meta tag.
|
|
605
|
+
|
|
606
|
+
**Parameters:**
|
|
607
|
+
- `author: string` — author name
|
|
608
|
+
|
|
609
|
+
**Returns:** `this` — for chaining calls
|
|
610
|
+
|
|
611
|
+
```javascript
|
|
612
|
+
const meta = new Meta()
|
|
613
|
+
|
|
614
|
+
// Set author
|
|
615
|
+
meta.setAuthor('John Doe')
|
|
616
|
+
|
|
617
|
+
// From user data
|
|
618
|
+
meta.setAuthor(article.author.name)
|
|
619
|
+
|
|
620
|
+
// Full name
|
|
621
|
+
meta.setAuthor(`${user.firstName} ${user.lastName}`)
|
|
622
|
+
|
|
623
|
+
// For blog
|
|
624
|
+
meta.setAuthor(post.author)
|
|
625
|
+
|
|
626
|
+
// Conditional setting
|
|
627
|
+
if (article.author) {
|
|
628
|
+
meta.setAuthor(article.author.name)
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Chaining
|
|
632
|
+
meta
|
|
633
|
+
.setAuthor('John Doe')
|
|
634
|
+
.setTitle('Article')
|
|
635
|
+
.setDescription('Description')
|
|
636
|
+
|
|
637
|
+
// For structured data
|
|
638
|
+
meta.setAuthor(author.name)
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### `setSiteName`
|
|
642
|
+
|
|
643
|
+
Sets the site name for Open Graph and Twitter Card simultaneously.
|
|
644
|
+
|
|
645
|
+
**Parameters:**
|
|
646
|
+
- `siteName: string` — site name
|
|
647
|
+
|
|
648
|
+
**Returns:** `this` — for chaining calls
|
|
649
|
+
|
|
650
|
+
```javascript
|
|
651
|
+
const meta = new Meta()
|
|
652
|
+
|
|
653
|
+
// Set site name
|
|
654
|
+
meta.setSiteName('My Blog')
|
|
655
|
+
// Updates og:site_name and twitter:site
|
|
656
|
+
|
|
657
|
+
// From configuration
|
|
658
|
+
meta.setSiteName(config.siteName)
|
|
659
|
+
|
|
660
|
+
// Constant
|
|
661
|
+
const SITE_NAME = 'WebDev Journal'
|
|
662
|
+
meta.setSiteName(SITE_NAME)
|
|
663
|
+
|
|
664
|
+
// For branding
|
|
665
|
+
meta.setSiteName('TechBlog')
|
|
666
|
+
|
|
667
|
+
// Once during initialization
|
|
668
|
+
const meta = new Meta()
|
|
669
|
+
meta.setSiteName('My Site')
|
|
670
|
+
meta.setSuffix('My Site')
|
|
671
|
+
|
|
672
|
+
// Chaining
|
|
673
|
+
meta
|
|
674
|
+
.setSiteName('Site Name')
|
|
675
|
+
.setTitle('Home')
|
|
676
|
+
|
|
677
|
+
// Recommendations:
|
|
678
|
+
// - Short and recognizable
|
|
679
|
+
// - Matches the brand
|
|
680
|
+
// - Used in social networks
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### `setLocale`
|
|
684
|
+
|
|
685
|
+
Sets the locale for Open Graph.
|
|
686
|
+
|
|
687
|
+
**Parameters:**
|
|
688
|
+
- `locale: string` — locale in language_TERRITORY format
|
|
689
|
+
|
|
690
|
+
**Returns:** `this` — for chaining calls
|
|
691
|
+
|
|
692
|
+
```javascript
|
|
693
|
+
const meta = new Meta()
|
|
694
|
+
|
|
695
|
+
// Set English locale
|
|
696
|
+
meta.setLocale('en_US')
|
|
697
|
+
|
|
698
|
+
// Other locales
|
|
699
|
+
meta.setLocale('en_GB') // English (United Kingdom)
|
|
700
|
+
meta.setLocale('ru_RU') // Russian
|
|
701
|
+
meta.setLocale('uk_UA') // Ukrainian
|
|
702
|
+
meta.setLocale('de_DE') // German
|
|
703
|
+
meta.setLocale('fr_FR') // French
|
|
704
|
+
|
|
705
|
+
// Automatic detection
|
|
706
|
+
const userLocale = navigator.language.replace('-', '_')
|
|
707
|
+
meta.setLocale(userLocale)
|
|
708
|
+
|
|
709
|
+
// From i18n settings
|
|
710
|
+
meta.setLocale(i18n.locale.replace('-', '_'))
|
|
711
|
+
|
|
712
|
+
// Conditional setting
|
|
713
|
+
const locale = isEnglish ? 'en_US' : 'ru_RU'
|
|
714
|
+
meta.setLocale(locale)
|
|
715
|
+
|
|
716
|
+
// On language change
|
|
717
|
+
const changeLanguage = (lang) => {
|
|
718
|
+
const localeMap = {
|
|
719
|
+
'en': 'en_US',
|
|
720
|
+
'ru': 'ru_RU',
|
|
721
|
+
'de': 'de_DE'
|
|
722
|
+
}
|
|
723
|
+
meta.setLocale(localeMap[lang])
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Chaining
|
|
727
|
+
meta
|
|
728
|
+
.setLocale('en_US')
|
|
729
|
+
.setSiteName('My Site')
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### `setSuffix`
|
|
733
|
+
|
|
734
|
+
Sets the suffix to automatically append to page title.
|
|
735
|
+
|
|
736
|
+
**Parameters:**
|
|
737
|
+
- `suffix?: string` — title suffix (optional)
|
|
738
|
+
|
|
739
|
+
```javascript
|
|
740
|
+
const meta = new Meta()
|
|
741
|
+
|
|
742
|
+
// Set suffix
|
|
743
|
+
meta.setSuffix('My Site')
|
|
744
|
+
meta.setTitle('Home')
|
|
745
|
+
// document.title = "Home - My Site"
|
|
746
|
+
|
|
747
|
+
// From configuration
|
|
748
|
+
meta.setSuffix(config.siteName)
|
|
749
|
+
|
|
750
|
+
// Remove suffix
|
|
751
|
+
meta.setSuffix()
|
|
752
|
+
meta.setTitle('Page')
|
|
753
|
+
// document.title = "Page"
|
|
754
|
+
|
|
755
|
+
// Conditional setting
|
|
756
|
+
if (showBranding) {
|
|
757
|
+
meta.setSuffix('Site Name')
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// Different suffixes for different sections
|
|
761
|
+
if (isBlog) {
|
|
762
|
+
meta.setSuffix('Blog | My Site')
|
|
763
|
+
} else {
|
|
764
|
+
meta.setSuffix('My Site')
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Usually set once during initialization
|
|
768
|
+
const initMeta = () => {
|
|
769
|
+
const meta = new Meta()
|
|
770
|
+
meta.setSuffix('My Site')
|
|
771
|
+
meta.setSiteName('My Site')
|
|
772
|
+
return meta
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Note: suffix is automatically added
|
|
776
|
+
// in format: "Title - Suffix"
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### `html`
|
|
780
|
+
|
|
781
|
+
Generates the complete HTML for all meta tags, including Open Graph and Twitter Card.
|
|
782
|
+
|
|
783
|
+
**Returns:** `string` — HTML string with all meta tags
|
|
784
|
+
|
|
785
|
+
```javascript
|
|
786
|
+
const meta = new Meta()
|
|
787
|
+
|
|
788
|
+
// Setup meta tags
|
|
789
|
+
meta.setSuffix('My Site')
|
|
790
|
+
meta.setSiteName('My Site')
|
|
791
|
+
meta.setLocale('en_US')
|
|
792
|
+
meta
|
|
793
|
+
.setTitle('Article')
|
|
794
|
+
.setDescription('Article description')
|
|
795
|
+
.setKeywords(['web', 'javascript'])
|
|
796
|
+
.setImage('https://example.com/image.jpg')
|
|
797
|
+
.setCanonical('https://example.com/article')
|
|
798
|
+
.setAuthor('John Doe')
|
|
799
|
+
|
|
800
|
+
// Get HTML of all meta tags
|
|
801
|
+
const metaHTML = meta.html()
|
|
802
|
+
|
|
803
|
+
// Result includes:
|
|
804
|
+
// - Standard HTML meta tags (description, keywords, author, canonical)
|
|
805
|
+
// - Open Graph tags (og:title, og:description, og:image, og:url, og:site_name, og:locale)
|
|
806
|
+
// - Twitter Card tags (twitter:title, twitter:description, twitter:image, twitter:site)
|
|
807
|
+
|
|
808
|
+
// Use in SSR (Server-Side Rendering)
|
|
809
|
+
// Express.js
|
|
810
|
+
app.get('/page', (req, res) => {
|
|
811
|
+
const meta = new Meta()
|
|
812
|
+
meta
|
|
813
|
+
.setTitle('Page Title')
|
|
814
|
+
.setDescription('Description')
|
|
815
|
+
.setImage('https://example.com/og-image.jpg')
|
|
816
|
+
|
|
817
|
+
const html = `
|
|
818
|
+
<!DOCTYPE html>
|
|
819
|
+
<html>
|
|
820
|
+
<head>
|
|
821
|
+
<meta charset="UTF-8">
|
|
822
|
+
${meta.html()}
|
|
823
|
+
<title>Title - Site</title>
|
|
824
|
+
</head>
|
|
825
|
+
<body>
|
|
826
|
+
<h1>Content</h1>
|
|
827
|
+
</body>
|
|
828
|
+
</html>
|
|
829
|
+
`
|
|
830
|
+
|
|
831
|
+
res.send(html)
|
|
832
|
+
})
|
|
833
|
+
|
|
834
|
+
// Next.js getServerSideProps
|
|
835
|
+
export async function getServerSideProps() {
|
|
836
|
+
const meta = new Meta()
|
|
837
|
+
meta
|
|
838
|
+
.setTitle('Article')
|
|
839
|
+
.setDescription('Article description')
|
|
840
|
+
|
|
841
|
+
return {
|
|
842
|
+
props: {
|
|
843
|
+
metaTags: meta.html()
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// Nuxt.js (in composable)
|
|
849
|
+
const meta = new Meta()
|
|
850
|
+
meta.setTitle('Page')
|
|
851
|
+
|
|
852
|
+
const metaHTML = meta.html()
|
|
853
|
+
// Insert into head via useHead() or template
|
|
854
|
+
|
|
855
|
+
// Benefits of html() method:
|
|
856
|
+
// - Automatic escaping of special characters
|
|
857
|
+
// - Combines all three types of meta tags (standard, OG, Twitter)
|
|
858
|
+
// - Ready for insertion into server template
|
|
859
|
+
// - Safe from XSS attacks
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
## Practical Examples
|
|
863
|
+
|
|
864
|
+
### Complete Page Setup
|
|
865
|
+
|
|
866
|
+
```javascript
|
|
867
|
+
import { Meta, MetaRobots } from '@dxtmisha/functional'
|
|
868
|
+
|
|
869
|
+
const meta = new Meta()
|
|
870
|
+
|
|
871
|
+
// Setup during app initialization
|
|
872
|
+
meta.setSuffix('My Site')
|
|
873
|
+
meta.setSiteName('My Site')
|
|
874
|
+
meta.setLocale('en_US')
|
|
875
|
+
|
|
876
|
+
// Setup specific page
|
|
877
|
+
meta
|
|
878
|
+
.setTitle('Complete Guide to Web Development')
|
|
879
|
+
.setDescription('Learn web development from scratch: HTML, CSS, JavaScript, frameworks and tools')
|
|
880
|
+
.setKeywords(['web development', 'html', 'css', 'javascript', 'guide'])
|
|
881
|
+
.setImage('https://example.com/images/web-dev-guide.jpg')
|
|
882
|
+
.setCanonical('https://example.com/guides/web-development')
|
|
883
|
+
.setAuthor('John Doe')
|
|
884
|
+
.setRobots(MetaRobots.indexFollow)
|
|
885
|
+
|
|
886
|
+
// Result:
|
|
887
|
+
// <title>Complete Guide to Web Development - My Site</title>
|
|
888
|
+
// <meta name="description" content="Learn web development...">
|
|
889
|
+
// <meta name="keywords" content="web development, html, css, javascript, guide">
|
|
890
|
+
// <meta name="author" content="John Doe">
|
|
891
|
+
// <meta name="robots" content="index, follow">
|
|
892
|
+
// <link rel="canonical" href="https://example.com/guides/web-development">
|
|
893
|
+
// <meta property="og:title" content="Complete Guide... - My Site">
|
|
894
|
+
// <meta property="og:description" content="Learn web development...">
|
|
895
|
+
// <meta property="og:image" content="https://example.com/images/web-dev-guide.jpg">
|
|
896
|
+
// <meta property="og:url" content="https://example.com/guides/web-development">
|
|
897
|
+
// <meta property="og:site_name" content="My Site">
|
|
898
|
+
// <meta property="og:locale" content="en_US">
|
|
899
|
+
// <meta property="twitter:title" content="Complete Guide... - My Site">
|
|
900
|
+
// <meta property="twitter:description" content="Learn web development...">
|
|
901
|
+
// <meta property="twitter:image" content="https://example.com/images/web-dev-guide.jpg">
|
|
902
|
+
// <meta property="twitter:site" content="My Site">
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
### Vue Router Integration
|
|
906
|
+
|
|
907
|
+
```javascript
|
|
908
|
+
import { Meta } from '@dxtmisha/functional'
|
|
909
|
+
|
|
910
|
+
const meta = new Meta()
|
|
911
|
+
|
|
912
|
+
// Initialization
|
|
913
|
+
meta.setSuffix('My Site')
|
|
914
|
+
meta.setSiteName('My Site')
|
|
915
|
+
meta.setLocale('en_US')
|
|
916
|
+
|
|
917
|
+
// Update on route change
|
|
918
|
+
router.afterEach((to) => {
|
|
919
|
+
meta
|
|
920
|
+
.setTitle(to.meta.title || 'Page Not Found')
|
|
921
|
+
.setDescription(to.meta.description || '')
|
|
922
|
+
.setKeywords(to.meta.keywords || [])
|
|
923
|
+
.setCanonical(`https://example.com${to.path}`)
|
|
924
|
+
|
|
925
|
+
// Image if available
|
|
926
|
+
if (to.meta.image) {
|
|
927
|
+
meta.setImage(to.meta.image)
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// Author if available
|
|
931
|
+
if (to.meta.author) {
|
|
932
|
+
meta.setAuthor(to.meta.author)
|
|
933
|
+
}
|
|
934
|
+
})
|
|
935
|
+
|
|
936
|
+
// Define meta in routes
|
|
937
|
+
const routes = [
|
|
938
|
+
{
|
|
939
|
+
path: '/',
|
|
940
|
+
component: Home,
|
|
941
|
+
meta: {
|
|
942
|
+
title: 'Home',
|
|
943
|
+
description: 'Welcome to our website',
|
|
944
|
+
keywords: ['home', 'website'],
|
|
945
|
+
image: '/images/home.jpg'
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
path: '/about',
|
|
950
|
+
component: About,
|
|
951
|
+
meta: {
|
|
952
|
+
title: 'About Us',
|
|
953
|
+
description: 'Information about our company',
|
|
954
|
+
keywords: ['about', 'company'],
|
|
955
|
+
image: '/images/about.jpg'
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
]
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
### React Integration
|
|
962
|
+
|
|
963
|
+
```javascript
|
|
964
|
+
import { Meta } from '@dxtmisha/functional'
|
|
965
|
+
import { useEffect } from 'react'
|
|
966
|
+
|
|
967
|
+
const meta = new Meta()
|
|
968
|
+
|
|
969
|
+
// Initialization in App.js
|
|
970
|
+
function App() {
|
|
971
|
+
useEffect(() => {
|
|
972
|
+
meta.setSuffix('My Site')
|
|
973
|
+
meta.setSiteName('My Site')
|
|
974
|
+
meta.setLocale('en_US')
|
|
975
|
+
}, [])
|
|
976
|
+
|
|
977
|
+
return <Router />
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// Page component
|
|
981
|
+
function ArticlePage({ article }) {
|
|
982
|
+
useEffect(() => {
|
|
983
|
+
meta
|
|
984
|
+
.setTitle(article.title)
|
|
985
|
+
.setDescription(article.excerpt)
|
|
986
|
+
.setKeywords(article.tags)
|
|
987
|
+
.setImage(article.coverImage)
|
|
988
|
+
.setCanonical(`https://example.com/articles/${article.slug}`)
|
|
989
|
+
.setAuthor(article.author.name)
|
|
990
|
+
|
|
991
|
+
return () => {
|
|
992
|
+
// Cleanup on unmount (optional)
|
|
993
|
+
}
|
|
994
|
+
}, [article])
|
|
995
|
+
|
|
996
|
+
return <div>{/* content */}</div>
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Custom hook for meta tags
|
|
1000
|
+
function useMeta(metaData) {
|
|
1001
|
+
useEffect(() => {
|
|
1002
|
+
if (metaData.title) meta.setTitle(metaData.title)
|
|
1003
|
+
if (metaData.description) meta.setDescription(metaData.description)
|
|
1004
|
+
if (metaData.keywords) meta.setKeywords(metaData.keywords)
|
|
1005
|
+
if (metaData.image) meta.setImage(metaData.image)
|
|
1006
|
+
if (metaData.canonical) meta.setCanonical(metaData.canonical)
|
|
1007
|
+
if (metaData.author) meta.setAuthor(metaData.author)
|
|
1008
|
+
}, [metaData])
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// Using hook
|
|
1012
|
+
function BlogPost({ post }) {
|
|
1013
|
+
useMeta({
|
|
1014
|
+
title: post.title,
|
|
1015
|
+
description: post.excerpt,
|
|
1016
|
+
keywords: post.tags,
|
|
1017
|
+
image: post.image,
|
|
1018
|
+
author: post.author.name
|
|
1019
|
+
})
|
|
1020
|
+
|
|
1021
|
+
return <article>{/* content */}</article>
|
|
1022
|
+
}
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
### SSR (Server-Side Rendering)
|
|
1026
|
+
|
|
1027
|
+
```javascript
|
|
1028
|
+
import { Meta } from '@dxtmisha/functional'
|
|
1029
|
+
|
|
1030
|
+
// Express.js server
|
|
1031
|
+
app.get('/article/:id', async (req, res) => {
|
|
1032
|
+
const article = await getArticle(req.params.id)
|
|
1033
|
+
|
|
1034
|
+
const meta = new Meta()
|
|
1035
|
+
meta.setSuffix('My Blog')
|
|
1036
|
+
meta.setSiteName('My Blog')
|
|
1037
|
+
meta.setLocale('en_US')
|
|
1038
|
+
|
|
1039
|
+
meta
|
|
1040
|
+
.setTitle(article.title)
|
|
1041
|
+
.setDescription(article.excerpt)
|
|
1042
|
+
.setKeywords(article.tags)
|
|
1043
|
+
.setImage(article.coverImage)
|
|
1044
|
+
.setCanonical(`https://example.com/article/${article.id}`)
|
|
1045
|
+
.setAuthor(article.author.name)
|
|
1046
|
+
|
|
1047
|
+
const html = `
|
|
1048
|
+
<!DOCTYPE html>
|
|
1049
|
+
<html lang="en">
|
|
1050
|
+
<head>
|
|
1051
|
+
<meta charset="UTF-8">
|
|
1052
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1053
|
+
<title>${article.title} - My Blog</title>
|
|
1054
|
+
${meta.html()}
|
|
1055
|
+
</head>
|
|
1056
|
+
<body>
|
|
1057
|
+
<article>${article.content}</article>
|
|
1058
|
+
</body>
|
|
1059
|
+
</html>
|
|
1060
|
+
`
|
|
1061
|
+
|
|
1062
|
+
res.send(html)
|
|
1063
|
+
})
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
### Using Advanced Open Graph and Twitter Card Features
|
|
1067
|
+
|
|
1068
|
+
```javascript
|
|
1069
|
+
import { Meta, MetaOpenGraphType, MetaTwitterCard } from '@dxtmisha/functional'
|
|
1070
|
+
|
|
1071
|
+
const meta = new Meta()
|
|
1072
|
+
|
|
1073
|
+
// Basic setup through Meta
|
|
1074
|
+
meta
|
|
1075
|
+
.setTitle('Video: Introduction to JavaScript')
|
|
1076
|
+
.setDescription('Complete JavaScript video guide for beginners')
|
|
1077
|
+
.setImage('https://example.com/images/js-video-thumb.jpg')
|
|
1078
|
+
.setCanonical('https://example.com/videos/js-intro')
|
|
1079
|
+
|
|
1080
|
+
// Advanced Open Graph setup through getOg()
|
|
1081
|
+
meta.getOg()
|
|
1082
|
+
.setType(MetaOpenGraphType.videoMovie) // Type: video
|
|
1083
|
+
.setLocale('en_US')
|
|
1084
|
+
|
|
1085
|
+
// Advanced Twitter Card setup through getTwitter()
|
|
1086
|
+
meta.getTwitter()
|
|
1087
|
+
.setCard(MetaTwitterCard.player) // Card with player
|
|
1088
|
+
.setCreator('@javascript_guru') // Video author
|
|
1089
|
+
|
|
1090
|
+
// Combined setup for different content types
|
|
1091
|
+
const setupContentMeta = (content) => {
|
|
1092
|
+
// Common settings
|
|
1093
|
+
meta
|
|
1094
|
+
.setTitle(content.title)
|
|
1095
|
+
.setDescription(content.description)
|
|
1096
|
+
.setImage(content.image)
|
|
1097
|
+
.setCanonical(content.url)
|
|
1098
|
+
|
|
1099
|
+
// Specific settings depending on type
|
|
1100
|
+
switch (content.type) {
|
|
1101
|
+
case 'article':
|
|
1102
|
+
meta.getOg().setType(MetaOpenGraphType.article)
|
|
1103
|
+
meta.getTwitter().setCard(MetaTwitterCard.summaryLargeImage)
|
|
1104
|
+
if (content.author?.twitter) {
|
|
1105
|
+
meta.getTwitter().setCreator(content.author.twitter)
|
|
1106
|
+
}
|
|
1107
|
+
break
|
|
1108
|
+
|
|
1109
|
+
case 'video':
|
|
1110
|
+
meta.getOg().setType(MetaOpenGraphType.videoMovie)
|
|
1111
|
+
meta.getTwitter().setCard(MetaTwitterCard.player)
|
|
1112
|
+
break
|
|
1113
|
+
|
|
1114
|
+
case 'product':
|
|
1115
|
+
meta.getOg().setType(MetaOpenGraphType.product)
|
|
1116
|
+
meta.getTwitter().setCard(MetaTwitterCard.summaryLargeImage)
|
|
1117
|
+
break
|
|
1118
|
+
|
|
1119
|
+
case 'music':
|
|
1120
|
+
meta.getOg().setType(MetaOpenGraphType.musicSong)
|
|
1121
|
+
meta.getTwitter().setCard(MetaTwitterCard.player)
|
|
1122
|
+
break
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// Usage
|
|
1127
|
+
setupContentMeta({
|
|
1128
|
+
type: 'video',
|
|
1129
|
+
title: 'JavaScript Tutorial',
|
|
1130
|
+
description: 'Learn JavaScript from scratch',
|
|
1131
|
+
image: 'https://example.com/thumb.jpg',
|
|
1132
|
+
url: 'https://example.com/videos/js-tutorial',
|
|
1133
|
+
author: {
|
|
1134
|
+
twitter: '@instructor'
|
|
1135
|
+
}
|
|
1136
|
+
})
|
|
1137
|
+
|
|
1138
|
+
// Access specific methods
|
|
1139
|
+
const getFullMetaInfo = () => {
|
|
1140
|
+
return {
|
|
1141
|
+
// Through Meta
|
|
1142
|
+
title: meta.getTitle(),
|
|
1143
|
+
description: meta.getDescription(),
|
|
1144
|
+
image: meta.getImage(),
|
|
1145
|
+
|
|
1146
|
+
// Through MetaOg
|
|
1147
|
+
ogType: meta.getOg().getType(),
|
|
1148
|
+
ogLocale: meta.getOg().getLocale(),
|
|
1149
|
+
|
|
1150
|
+
// Through MetaTwitter
|
|
1151
|
+
twitterCard: meta.getTwitter().getCard(),
|
|
1152
|
+
twitterCreator: meta.getTwitter().getCreator()
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
## Usage Recommendations
|
|
1158
|
+
|
|
1159
|
+
### Initialization
|
|
1160
|
+
Set common parameters once at app startup:
|
|
1161
|
+
```javascript
|
|
1162
|
+
const meta = new Meta()
|
|
1163
|
+
meta.setSuffix('Site Name')
|
|
1164
|
+
meta.setSiteName('Site Name')
|
|
1165
|
+
meta.setLocale('en_US')
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
### Update on Navigation
|
|
1169
|
+
Update meta tags on page change:
|
|
1170
|
+
```javascript
|
|
1171
|
+
router.afterEach((to) => {
|
|
1172
|
+
meta
|
|
1173
|
+
.setTitle(to.meta.title)
|
|
1174
|
+
.setDescription(to.meta.description)
|
|
1175
|
+
.setCanonical(`https://example.com${to.path}`)
|
|
1176
|
+
})
|
|
1177
|
+
```
|
|
1178
|
+
|
|
1179
|
+
### Text Length
|
|
1180
|
+
- **Title:** up to 60 characters (without suffix)
|
|
1181
|
+
- **Description:** 150-160 characters
|
|
1182
|
+
- **Keywords:** 10-15 keywords
|
|
1183
|
+
|
|
1184
|
+
### Required Tags
|
|
1185
|
+
Minimum necessary meta tags:
|
|
1186
|
+
- Title (via `setTitle`)
|
|
1187
|
+
- Description (via `setDescription`)
|
|
1188
|
+
- Canonical (via `setCanonical`)
|
|
1189
|
+
- Image for social media (via `setImage`)
|
|
1190
|
+
|
|
1191
|
+
### Images
|
|
1192
|
+
- Size: 1200×630 px (optimal)
|
|
1193
|
+
- Format: JPG, PNG, WebP
|
|
1194
|
+
- Maximum: 8 MB
|
|
1195
|
+
|
|
1196
|
+
## Notes
|
|
1197
|
+
|
|
1198
|
+
- Class combines functionality of MetaManager, MetaOg, and MetaTwitter
|
|
1199
|
+
- Changes in Meta are automatically applied to all related meta tags
|
|
1200
|
+
- Suffix is added only to document.title and social tags
|
|
1201
|
+
- `html()` method is inherited from MetaManager and generates HTML for all managed tags
|
|
1202
|
+
- Class is SSR compatible — checks for DOM presence before accessing document
|
|
1203
|
+
- Keywords are less important for modern SEO but can be used for internal search
|
|
1204
|
+
- For advanced Open Graph work, use `meta.og` directly
|
|
1205
|
+
- For advanced Twitter Card work, use `meta.twitter` directly
|
|
1206
|
+
|