@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.
Files changed (230) hide show
  1. package/package.json +7 -7
  2. package/src/classes/WikiStorybookItem.ts +24 -0
  3. package/src/media/descriptions/wikiDescriptions.ts +28 -0
  4. package/src/media/descriptions/wikiDescriptionsAccordion.ts +158 -0
  5. package/src/media/descriptions/wikiDescriptionsActionSheet.ts +211 -0
  6. package/src/media/descriptions/wikiDescriptionsActions.ts +161 -0
  7. package/src/media/descriptions/wikiDescriptionsAnchor.ts +42 -0
  8. package/src/media/descriptions/wikiDescriptionsArrow.ts +181 -0
  9. package/src/media/descriptions/wikiDescriptionsBlock.ts +97 -0
  10. package/src/media/descriptions/wikiDescriptionsButton.ts +0 -1
  11. package/src/media/descriptions/wikiDescriptionsCell.ts +2 -1
  12. package/src/media/descriptions/wikiDescriptionsChipGroup.ts +168 -0
  13. package/src/media/descriptions/wikiDescriptionsDialog.ts +182 -0
  14. package/src/media/descriptions/wikiDescriptionsField.ts +2 -0
  15. package/src/media/descriptions/wikiDescriptionsImage.ts +41 -6
  16. package/src/media/descriptions/wikiDescriptionsInput.ts +257 -0
  17. package/src/media/descriptions/wikiDescriptionsMenu.ts +123 -0
  18. package/src/media/descriptions/wikiDescriptionsModal.ts +145 -0
  19. package/src/media/descriptions/wikiDescriptionsMotionTransform.ts +2 -6
  20. package/src/media/descriptions/wikiDescriptionsSelect.ts +209 -0
  21. package/src/media/descriptions/wikiDescriptionsSelectValue.ts +78 -0
  22. package/src/media/descriptions/wikiDescriptionsTextareaAutosize.ts +50 -0
  23. package/src/media/descriptions/wikiDescriptionsTooltip.ts +89 -0
  24. package/src/media/functional/en/conversions.mdx +67 -0
  25. package/src/media/functional/en/dataUtils.mdx +25 -0
  26. package/src/media/functional/en/datetimeRef.mdx +1 -1
  27. package/src/media/functional/en/eventRef.mdx +1 -1
  28. package/src/media/functional/en/executionUtils.mdx +58 -0
  29. package/src/media/functional/en/geoFlagRef.mdx +1 -1
  30. package/src/media/functional/en/geoIntlRef.mdx +1 -1
  31. package/src/media/functional/en/geoRef.mdx +2 -2
  32. package/src/media/functional/en/meta.mdx +1206 -0
  33. package/src/media/functional/en/metaManager.mdx +376 -0
  34. package/src/media/functional/en/metaOg.mdx +694 -0
  35. package/src/media/functional/en/metaTwitter.mdx +853 -0
  36. package/src/media/functional/en/reactive.mdx +40 -0
  37. package/src/media/functional/en/refTypes.mdx +1 -1
  38. package/src/media/functional/en/useApiRef.mdx +5 -5
  39. package/src/media/functional/en/useMeta.mdx +431 -0
  40. package/src/media/functional/en/validationUtils.mdx +11 -0
  41. package/src/media/functional/ru/conversions.mdx +67 -0
  42. package/src/media/functional/ru/dataUtils.mdx +25 -0
  43. package/src/media/functional/ru/datetimeRef.mdx +2 -2
  44. package/src/media/functional/ru/eventRef.mdx +1 -1
  45. package/src/media/functional/ru/executionUtils.mdx +58 -0
  46. package/src/media/functional/ru/geoFlagRef.mdx +1 -1
  47. package/src/media/functional/ru/geoIntl.mdx +2 -2
  48. package/src/media/functional/ru/geoIntlRef.mdx +1 -1
  49. package/src/media/functional/ru/geoRef.mdx +2 -2
  50. package/src/media/functional/ru/listTypes.mdx +1 -1
  51. package/src/media/functional/ru/meta.mdx +1330 -0
  52. package/src/media/functional/ru/metaManager.mdx +376 -0
  53. package/src/media/functional/ru/metaOg.mdx +694 -0
  54. package/src/media/functional/ru/metaTwitter.mdx +853 -0
  55. package/src/media/functional/ru/reactive.mdx +40 -0
  56. package/src/media/functional/ru/refTypes.mdx +2 -2
  57. package/src/media/functional/ru/useApiRef.mdx +5 -5
  58. package/src/media/functional/ru/useMeta.mdx +431 -0
  59. package/src/media/functional/ru/validationUtils.mdx +11 -0
  60. package/src/media/mdx/Accordion/accordion.en.mdx +59 -0
  61. package/src/media/mdx/Accordion/accordion.ru.mdx +59 -0
  62. package/src/media/mdx/Accordion/slots.en.mdx +6 -0
  63. package/src/media/mdx/Accordion/slots.ru.mdx +6 -0
  64. package/src/media/mdx/Accordion/wikiMdxAccordion.ts +25 -0
  65. package/src/media/mdx/ActionSheet/actionSheet.en.mdx +61 -0
  66. package/src/media/mdx/ActionSheet/actionSheet.ru.mdx +61 -0
  67. package/src/media/mdx/ActionSheet/touchClose.en.mdx +21 -0
  68. package/src/media/mdx/ActionSheet/touchClose.ru.mdx +21 -0
  69. package/src/media/mdx/ActionSheet/wikiMdxActionSheet.ts +25 -0
  70. package/src/media/mdx/Actions/actions.en.mdx +48 -0
  71. package/src/media/mdx/Actions/actions.ru.mdx +48 -0
  72. package/src/media/mdx/Actions/flexible.en.mdx +19 -0
  73. package/src/media/mdx/Actions/flexible.ru.mdx +19 -0
  74. package/src/media/mdx/Actions/list.en.mdx +50 -0
  75. package/src/media/mdx/Actions/list.ru.mdx +50 -0
  76. package/src/media/mdx/Actions/wikiMdxActions.ts +31 -0
  77. package/src/media/mdx/Anchor/anchor.en.mdx +34 -0
  78. package/src/media/mdx/Anchor/anchor.ru.mdx +34 -0
  79. package/src/media/mdx/Anchor/expose.go.en.mdx +6 -0
  80. package/src/media/mdx/Anchor/expose.go.ru.mdx +6 -0
  81. package/src/media/mdx/Anchor/hide.en.mdx +28 -0
  82. package/src/media/mdx/Anchor/hide.ru.mdx +28 -0
  83. package/src/media/mdx/Anchor/isCopy.en.mdx +23 -0
  84. package/src/media/mdx/Anchor/isCopy.ru.mdx +23 -0
  85. package/src/media/mdx/Anchor/scroll.en.mdx +34 -0
  86. package/src/media/mdx/Anchor/scroll.ru.mdx +35 -0
  87. package/src/media/mdx/Anchor/wikiMdxAnchor.ts +43 -0
  88. package/src/media/mdx/Arrow/arrow.en.mdx +33 -0
  89. package/src/media/mdx/Arrow/arrow.ru.mdx +33 -0
  90. package/src/media/mdx/Arrow/wikiMdxArrow.ts +19 -0
  91. package/src/media/mdx/Block/block.en.mdx +42 -0
  92. package/src/media/mdx/Block/block.ru.mdx +42 -0
  93. package/src/media/mdx/Block/wikiMdxBlock.ts +19 -0
  94. package/src/media/mdx/ChipGroup/chipGroup.en.mdx +51 -0
  95. package/src/media/mdx/ChipGroup/chipGroup.ru.mdx +51 -0
  96. package/src/media/mdx/ChipGroup/selected.en.mdx +50 -0
  97. package/src/media/mdx/ChipGroup/selected.ru.mdx +50 -0
  98. package/src/media/mdx/ChipGroup/wikiMdxChipGroup.ts +25 -0
  99. package/src/media/mdx/Dialog/buttons.en.mdx +45 -0
  100. package/src/media/mdx/Dialog/buttons.ru.mdx +45 -0
  101. package/src/media/mdx/Dialog/dialog.en.mdx +66 -0
  102. package/src/media/mdx/Dialog/dialog.ru.mdx +65 -0
  103. package/src/media/mdx/Dialog/events.en.mdx +63 -0
  104. package/src/media/mdx/Dialog/events.ru.mdx +63 -0
  105. package/src/media/mdx/Dialog/states.en.mdx +58 -0
  106. package/src/media/mdx/Dialog/states.ru.mdx +57 -0
  107. package/src/media/mdx/Dialog/wikiMdxDialog.ts +37 -0
  108. package/src/media/mdx/Field/arrows.en.mdx +22 -6
  109. package/src/media/mdx/Field/arrows.ru.mdx +22 -6
  110. package/src/media/mdx/Field/slots.en.mdx +0 -13
  111. package/src/media/mdx/Field/slots.ru.mdx +0 -13
  112. package/src/media/mdx/Image/img-tag.en.mdx +105 -0
  113. package/src/media/mdx/Image/img-tag.ru.mdx +105 -0
  114. package/src/media/mdx/Image/wikiMdxImage.ts +6 -0
  115. package/src/media/mdx/Input/currency.en.mdx +38 -0
  116. package/src/media/mdx/Input/currency.ru.mdx +38 -0
  117. package/src/media/mdx/Input/date.en.mdx +53 -0
  118. package/src/media/mdx/Input/date.ru.mdx +53 -0
  119. package/src/media/mdx/Input/input.en.mdx +143 -0
  120. package/src/media/mdx/Input/input.ru.mdx +71 -0
  121. package/src/media/mdx/Input/mask.en.mdx +30 -0
  122. package/src/media/mdx/Input/mask.ru.mdx +30 -0
  123. package/src/media/mdx/Input/number.en.mdx +41 -0
  124. package/src/media/mdx/Input/number.ru.mdx +41 -0
  125. package/src/media/mdx/Input/type.en.mdx +26 -0
  126. package/src/media/mdx/Input/type.ru.mdx +26 -0
  127. package/src/media/mdx/Input/wikiMdxInput.ts +49 -0
  128. package/src/media/mdx/Menu/event.updateValue.en.mdx +29 -0
  129. package/src/media/mdx/Menu/event.updateValue.ru.mdx +30 -0
  130. package/src/media/mdx/Menu/expose.navigation.en.mdx +12 -0
  131. package/src/media/mdx/Menu/expose.navigation.ru.mdx +12 -0
  132. package/src/media/mdx/Menu/navigation.en.mdx +56 -0
  133. package/src/media/mdx/Menu/navigation.ru.mdx +56 -0
  134. package/src/media/mdx/Menu/slots.control.en.mdx +65 -0
  135. package/src/media/mdx/Menu/slots.control.ru.mdx +65 -0
  136. package/src/media/mdx/Menu/slots.en.mdx +2 -24
  137. package/src/media/mdx/Menu/slots.ru.mdx +2 -24
  138. package/src/media/mdx/Menu/wikiMdxMenu.ts +27 -3
  139. package/src/media/mdx/Modal/differences.en.mdx +130 -0
  140. package/src/media/mdx/Modal/differences.ru.mdx +65 -0
  141. package/src/media/mdx/Modal/modal.en.mdx +63 -0
  142. package/src/media/mdx/Modal/modal.ru.mdx +63 -0
  143. package/src/media/mdx/Modal/wikiMdxModal.ts +25 -0
  144. package/src/media/mdx/MotionTransform/expose.motionTransformElement.en.mdx +13 -0
  145. package/src/media/mdx/MotionTransform/expose.motionTransformElement.ru.mdx +14 -0
  146. package/src/media/mdx/MotionTransform/wikiMdxMotionTransform.ts +6 -0
  147. package/src/media/mdx/Select/select.en.mdx +69 -0
  148. package/src/media/mdx/Select/select.ru.mdx +69 -0
  149. package/src/media/mdx/Select/wikiMdxSelect.ts +19 -0
  150. package/src/media/mdx/SelectValue/selectValue.en.mdx +64 -0
  151. package/src/media/mdx/SelectValue/selectValue.ru.mdx +64 -0
  152. package/src/media/mdx/SelectValue/wikiMdxSelectValue.ts +19 -0
  153. package/src/media/mdx/TextareaAutosize/textarea-autosize.en.mdx +65 -0
  154. package/src/media/mdx/TextareaAutosize/textarea-autosize.ru.mdx +65 -0
  155. package/src/media/mdx/TextareaAutosize/wikiMdxTextareaAutosize.ts +19 -0
  156. package/src/media/mdx/Tooltip/event.tooltip.en.mdx +7 -0
  157. package/src/media/mdx/Tooltip/event.tooltip.ru.mdx +8 -0
  158. package/src/media/mdx/Tooltip/slot.control.en.mdx +14 -0
  159. package/src/media/mdx/Tooltip/slot.control.ru.mdx +14 -0
  160. package/src/media/mdx/Tooltip/tooltip.en.mdx +34 -0
  161. package/src/media/mdx/Tooltip/tooltip.ru.mdx +34 -0
  162. package/src/media/mdx/Tooltip/wikiMdxTooltip.ts +31 -0
  163. package/src/media/mdx/Window/classes.ru.mdx +1 -1
  164. package/src/media/mdx/event/events.actions.en.mdx +44 -0
  165. package/src/media/mdx/event/events.actions.ru.mdx +44 -0
  166. package/src/media/mdx/event/events.inputStandard.en.mdx +6 -0
  167. package/src/media/mdx/event/events.inputStandard.ru.mdx +6 -0
  168. package/src/media/mdx/event/wikiMdxEvent.ts +20 -8
  169. package/src/media/mdx/expose/expose.descriptionId.en.mdx +6 -0
  170. package/src/media/mdx/expose/expose.descriptionId.ru.mdx +6 -0
  171. package/src/media/mdx/expose/expose.id.en.mdx +6 -0
  172. package/src/media/mdx/expose/expose.id.ru.mdx +6 -0
  173. package/src/media/mdx/expose/expose.labelId.en.mdx +6 -0
  174. package/src/media/mdx/expose/expose.labelId.ru.mdx +6 -0
  175. package/src/media/mdx/expose/wikiMdxExpose.ts +18 -0
  176. package/src/media/mdx/slot/body.en.mdx +6 -0
  177. package/src/media/mdx/slot/body.ru.mdx +6 -0
  178. package/src/media/mdx/slot/headline.en.mdx +7 -0
  179. package/src/media/mdx/slot/headline.ru.mdx +6 -0
  180. package/src/media/mdx/slot/leading.en.mdx +7 -0
  181. package/src/media/mdx/slot/leading.ru.mdx +7 -0
  182. package/src/media/mdx/slot/secondary.en.mdx +5 -0
  183. package/src/media/mdx/slot/secondary.ru.mdx +5 -0
  184. package/src/media/mdx/slot/trailing.en.mdx +7 -0
  185. package/src/media/mdx/slot/trailing.ru.mdx +7 -0
  186. package/src/media/mdx/slot/wikiMdxSlot.ts +30 -0
  187. package/src/media/mdx/style/isSkeleton.en.mdx +2 -2
  188. package/src/media/mdx/style/isSkeleton.ru.mdx +2 -2
  189. package/src/media/mdx/value/v-model-selected.en.mdx +28 -0
  190. package/src/media/mdx/value/v-model-selected.ru.mdx +28 -0
  191. package/src/media/mdx/value/v-model.en.mdx +26 -0
  192. package/src/media/mdx/value/v-model.ru.mdx +26 -0
  193. package/src/media/mdx/value/wikiMdxValue.ts +24 -3
  194. package/src/media/mdx/wikiMdx.ts +29 -1
  195. package/src/media/props/wiki.ts +42 -0
  196. package/src/media/props/wikiActions.ts +43 -0
  197. package/src/media/props/wikiActionsInclude.ts +62 -0
  198. package/src/media/props/wikiAnchor.ts +84 -0
  199. package/src/media/props/wikiAria.ts +102 -0
  200. package/src/media/props/wikiArrow.ts +24 -0
  201. package/src/media/props/wikiArrowInclude.ts +45 -0
  202. package/src/media/props/wikiBarsInclude.ts +80 -0
  203. package/src/media/props/wikiChipGroup.ts +39 -0
  204. package/src/media/props/wikiDialog.ts +34 -0
  205. package/src/media/props/wikiField.ts +0 -21
  206. package/src/media/props/wikiFieldCounterInclude.ts +78 -0
  207. package/src/media/props/wikiForm.ts +248 -0
  208. package/src/media/props/wikiHook.ts +20 -0
  209. package/src/media/props/wikiIcon.ts +3 -3
  210. package/src/media/props/wikiIconInclude.ts +319 -0
  211. package/src/media/props/wikiImage.ts +71 -19
  212. package/src/media/props/wikiInformation.ts +160 -0
  213. package/src/media/props/wikiInput.ts +34 -0
  214. package/src/media/props/wikiListItem.ts +20 -0
  215. package/src/media/props/wikiMask.ts +0 -10
  216. package/src/media/props/wikiMaskInclude.ts +54 -0
  217. package/src/media/props/wikiMenu.ts +0 -10
  218. package/src/media/props/wikiMotionTransform.ts +0 -10
  219. package/src/media/props/wikiOption.ts +113 -0
  220. package/src/media/props/wikiSelect.ts +68 -0
  221. package/src/media/props/wikiSelectValue.ts +30 -0
  222. package/src/media/props/wikiStatus.ts +29 -41
  223. package/src/media/props/wikiStyle.ts +154 -243
  224. package/src/media/props/wikiTechnical.ts +65 -0
  225. package/src/media/props/wikiText.ts +57 -0
  226. package/src/media/props/wikiTooltip.ts +53 -0
  227. package/src/media/props/wikiValue.ts +14 -203
  228. package/src/media/props/wikiWindow.ts +0 -31
  229. package/src/styles/storybookStyle.scss +3 -1
  230. 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
+