@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,853 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/en/Classes/MetaTwitter'/>
4
+
5
+ # MetaTwitter Class
6
+
7
+ A class for working with Twitter Card meta-tags, ensuring beautiful content display when sharing links on Twitter (X). Inherits `MetaManager` functionality and provides type-safe methods for managing standard Twitter Card tags.
8
+
9
+ ## Key Features
10
+
11
+ - **Type Safety** — strict typing for all Twitter Card tags and card types
12
+ - **Automatic Synchronization** — updates meta-tags in the document `<head>`
13
+ - **Support for All Card Types** — summary, summary_large_image, app, player
14
+ - **Convenient API** — specialized methods for each tag
15
+ - **SSR Compatibility** — HTML generation for server-side rendering
16
+ - **Type Validation** — support for all official Twitter Card types
17
+ - **Chainable Methods** — ability to set values sequentially
18
+
19
+ ## Constructor
20
+
21
+ ### `constructor`
22
+
23
+ Creates a MetaTwitter instance with a preset list of all supported Twitter Card tags. Automatically reads existing tags from the DOM.
24
+
25
+ ```javascript
26
+ import { MetaTwitter } from '@dxtmisha/functional'
27
+
28
+ // Create an instance
29
+ const twitter = new MetaTwitter()
30
+
31
+ // The class automatically manages all standard Twitter Card tags:
32
+ // twitter:card, twitter:site, twitter:creator, twitter:title,
33
+ // twitter:description, twitter:image and others
34
+ ```
35
+
36
+ ## Data Retrieval Methods
37
+
38
+ ### `getCard`
39
+
40
+ Gets the Twitter Card type.
41
+
42
+ **Returns:** `MetaTwitterCard` — card type
43
+
44
+ ```javascript
45
+ const twitter = new MetaTwitter()
46
+
47
+ const cardType = twitter.getCard()
48
+ // 'summary_large_image'
49
+
50
+ // Check card type
51
+ if (twitter.getCard() === 'summary_large_image') {
52
+ console.log('Large image card')
53
+ }
54
+
55
+ // Conditional logic
56
+ switch (twitter.getCard()) {
57
+ case 'summary':
58
+ console.log('Standard card')
59
+ break
60
+ case 'summary_large_image':
61
+ console.log('Large image card')
62
+ break
63
+ case 'player':
64
+ console.log('Video player')
65
+ break
66
+ }
67
+ ```
68
+
69
+ ### `getSite`
70
+
71
+ Gets the Twitter account of the website or brand.
72
+
73
+ **Returns:** `string` — site's @username
74
+
75
+ ```javascript
76
+ const twitter = new MetaTwitter()
77
+
78
+ const site = twitter.getSite()
79
+ // '@mywebsite'
80
+
81
+ // Use for attribution
82
+ console.log('Site belongs to:', twitter.getSite())
83
+
84
+ // Check if set
85
+ if (twitter.getSite()) {
86
+ console.log('Twitter site account is set')
87
+ }
88
+
89
+ // Extract username without @
90
+ const username = twitter.getSite().replace('@', '')
91
+ ```
92
+
93
+ ### `getCreator`
94
+
95
+ Gets the Twitter account of the content creator.
96
+
97
+ **Returns:** `string` — creator's @username
98
+
99
+ ```javascript
100
+ const twitter = new MetaTwitter()
101
+
102
+ const creator = twitter.getCreator()
103
+ // '@john_doe'
104
+
105
+ // Display author
106
+ console.log('Author:', twitter.getCreator())
107
+
108
+ // Use in UI
109
+ const authorLink = `https://twitter.com/${twitter.getCreator().replace('@', '')}`
110
+
111
+ // Check authorship
112
+ if (twitter.getCreator()) {
113
+ console.log('Content has an author')
114
+ }
115
+ ```
116
+
117
+ ### `getUrl`
118
+
119
+ Gets the page URL for Twitter Card.
120
+
121
+ **Returns:** `string` — page URL
122
+
123
+ ```javascript
124
+ const twitter = new MetaTwitter()
125
+
126
+ const url = twitter.getUrl()
127
+ // 'https://example.com/article/my-post'
128
+
129
+ // Get domain
130
+ const domain = new URL(twitter.getUrl()).hostname
131
+
132
+ // Check match with current URL
133
+ if (twitter.getUrl() !== window.location.href) {
134
+ console.warn('Twitter URL does not match current URL')
135
+ }
136
+
137
+ // Create share link
138
+ const shareUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(twitter.getUrl())}`
139
+ ```
140
+
141
+ ### `getTitle`
142
+
143
+ Gets the card title.
144
+
145
+ **Returns:** `string` — card title
146
+
147
+ ```javascript
148
+ const twitter = new MetaTwitter()
149
+
150
+ const title = twitter.getTitle()
151
+ // 'Amazing Article About Web Development'
152
+
153
+ // Use for debugging
154
+ console.log('Twitter Title:', twitter.getTitle())
155
+
156
+ // Check length (recommended up to 70 characters)
157
+ if (twitter.getTitle().length > 70) {
158
+ console.warn('Title is too long for Twitter')
159
+ }
160
+
161
+ // Use in preview
162
+ const previewTitle = twitter.getTitle()
163
+ ```
164
+
165
+ ### `getDescription`
166
+
167
+ Gets the card description.
168
+
169
+ **Returns:** `string` — card description
170
+
171
+ ```javascript
172
+ const twitter = new MetaTwitter()
173
+
174
+ const description = twitter.getDescription()
175
+ // 'Complete guide to building...'
176
+
177
+ // Check length (recommended up to 200 characters)
178
+ if (twitter.getDescription().length > 200) {
179
+ console.warn('Description is too long')
180
+ }
181
+
182
+ // Truncate for preview
183
+ const shortDesc = twitter.getDescription().substring(0, 150) + '...'
184
+
185
+ // Use in metadata
186
+ console.log('Twitter Description:', twitter.getDescription())
187
+ ```
188
+
189
+ ### `getImage`
190
+
191
+ Gets the card image URL.
192
+
193
+ **Returns:** `string` — image URL
194
+
195
+ ```javascript
196
+ const twitter = new MetaTwitter()
197
+
198
+ const imageUrl = twitter.getImage()
199
+ // 'https://example.com/images/twitter-card.jpg'
200
+
201
+ // Preload image
202
+ const img = new Image()
203
+ img.src = twitter.getImage()
204
+
205
+ // Check if set
206
+ if (!twitter.getImage()) {
207
+ console.warn('Twitter image is not set')
208
+ }
209
+
210
+ // Use for preview
211
+ const previewImage = twitter.getImage()
212
+ ```
213
+
214
+ ## Data Setting Methods
215
+
216
+ ### `setCard`
217
+
218
+ Sets the Twitter Card type.
219
+
220
+ **Parameters:**
221
+ - `card: MetaTwitterCard` — card type
222
+
223
+ **Returns:** `this` — for chaining calls
224
+
225
+ **Available types:**
226
+ - `summary` — summary card with small image
227
+ - `summary_large_image` — card with large image (most popular)
228
+ - `app` — app card (for iOS/Android)
229
+ - `player` — card with video/audio player
230
+
231
+ ```javascript
232
+ import { MetaTwitter, MetaTwitterCard } from '@dxtmisha/functional'
233
+
234
+ const twitter = new MetaTwitter()
235
+
236
+ // Set standard card
237
+ twitter.setCard(MetaTwitterCard.summary)
238
+
239
+ // Large image card (recommended)
240
+ twitter.setCard(MetaTwitterCard.summaryLargeImage)
241
+
242
+ // For apps
243
+ twitter.setCard(MetaTwitterCard.app)
244
+
245
+ // For video content
246
+ twitter.setCard(MetaTwitterCard.player)
247
+
248
+ // Conditional setting
249
+ const cardType = hasLargeImage
250
+ ? MetaTwitterCard.summaryLargeImage
251
+ : MetaTwitterCard.summary
252
+
253
+ twitter.setCard(cardType)
254
+ ```
255
+
256
+ ### `setSite`
257
+
258
+ Sets the Twitter account of the website or brand.
259
+
260
+ **Parameters:**
261
+ - `site: string` — site's @username
262
+
263
+ **Returns:** `this` — for chaining calls
264
+
265
+ ```javascript
266
+ const twitter = new MetaTwitter()
267
+
268
+ // Set site account
269
+ twitter.setSite('@mywebsite')
270
+
271
+ // Can be without @
272
+ twitter.setSite('mywebsite')
273
+
274
+ // From configuration
275
+ twitter.setSite(config.twitterHandle)
276
+
277
+ // Chain methods
278
+ twitter
279
+ .setSite('@mywebsite')
280
+ .setCreator('@author')
281
+
282
+ // Recommendations:
283
+ // - Use official brand account
284
+ // - Format: @username (with or without @)
285
+ // - Twitter will show "via @username" in the card
286
+ ```
287
+
288
+ ### `setCreator`
289
+
290
+ Sets the Twitter account of the content creator.
291
+
292
+ **Parameters:**
293
+ - `creator: string` — creator's @username
294
+
295
+ **Returns:** `this` — for chaining calls
296
+
297
+ ```javascript
298
+ const twitter = new MetaTwitter()
299
+
300
+ // Set creator
301
+ twitter.setCreator('@john_doe')
302
+
303
+ // From user data
304
+ twitter.setCreator(article.author.twitterHandle)
305
+
306
+ // Dynamic update
307
+ const updateAuthor = (author) => {
308
+ if (author.twitter) {
309
+ twitter.setCreator(author.twitter)
310
+ }
311
+ }
312
+
313
+ // Chain
314
+ twitter
315
+ .setCreator('@author_name')
316
+ .setTitle('Article Title')
317
+
318
+ // Recommendations:
319
+ // - Use for author attribution
320
+ // - Twitter will show "by @username"
321
+ // - Different from site (site - for website, creator - for author)
322
+ ```
323
+
324
+ ### `setUrl`
325
+
326
+ Sets the page URL for Twitter Card.
327
+
328
+ **Parameters:**
329
+ - `url: string` — page URL
330
+
331
+ **Returns:** `this` — for chaining calls
332
+
333
+ ```javascript
334
+ const twitter = new MetaTwitter()
335
+
336
+ // Set URL
337
+ twitter.setUrl('https://example.com/article/my-post')
338
+
339
+ // Use current URL
340
+ twitter.setUrl(window.location.href)
341
+
342
+ // Clean query parameters
343
+ const cleanUrl = window.location.origin + window.location.pathname
344
+ twitter.setUrl(cleanUrl)
345
+
346
+ // For SPA
347
+ router.afterEach((to) => {
348
+ twitter.setUrl(`https://example.com${to.fullPath}`)
349
+ })
350
+
351
+ // Absolute URL from relative
352
+ const absoluteUrl = new URL('/article', window.location.origin).href
353
+ twitter.setUrl(absoluteUrl)
354
+
355
+ // Recommendations:
356
+ // - Always use absolute URLs
357
+ // - URL must be accessible to Twitter bot
358
+ // - Avoid redirects
359
+ ```
360
+
361
+ ### `setTitle`
362
+
363
+ Sets the card title.
364
+
365
+ **Parameters:**
366
+ - `title: string` — card title
367
+
368
+ **Returns:** `this` — for chaining calls
369
+
370
+ ```javascript
371
+ const twitter = new MetaTwitter()
372
+
373
+ // Set title
374
+ twitter.setTitle('Amazing Article About Web Development')
375
+
376
+ // Chain methods
377
+ twitter
378
+ .setTitle('New Title')
379
+ .setDescription('New Description')
380
+
381
+ // Dynamic update
382
+ const updateTitle = (newTitle) => {
383
+ twitter.setTitle(newTitle)
384
+ }
385
+
386
+ // Automatic generation
387
+ twitter.setTitle(`${article.title} - ${siteName}`)
388
+
389
+ // Truncate long title
390
+ const maxLength = 70
391
+ const shortTitle = article.title.length > maxLength
392
+ ? article.title.substring(0, maxLength - 3) + '...'
393
+ : article.title
394
+
395
+ twitter.setTitle(shortTitle)
396
+
397
+ // Recommendations:
398
+ // - Maximum 70 characters
399
+ // - Will be displayed in bold
400
+ // - Avoid duplication with description
401
+ ```
402
+
403
+ ### `setDescription`
404
+
405
+ Sets the card description.
406
+
407
+ **Parameters:**
408
+ - `description: string` — card description
409
+
410
+ **Returns:** `this` — for chaining calls
411
+
412
+ ```javascript
413
+ const twitter = new MetaTwitter()
414
+
415
+ // Set description
416
+ twitter.setDescription('Complete guide to building web applications using modern technologies')
417
+
418
+ // Truncate long text
419
+ const shortDesc = article.content.substring(0, 200)
420
+ twitter.setDescription(shortDesc)
421
+
422
+ // Remove HTML tags
423
+ const plainText = article.html.replace(/<[^>]*>/g, '')
424
+ twitter.setDescription(plainText.substring(0, 200))
425
+
426
+ // From excerpt
427
+ twitter.setDescription(article.excerpt || article.content.substring(0, 200))
428
+
429
+ // Chain
430
+ twitter
431
+ .setDescription('Article description')
432
+ .setImage('https://example.com/image.jpg')
433
+
434
+ // Recommendations:
435
+ // - Maximum 200 characters
436
+ // - Twitter may truncate text
437
+ // - Add call-to-action
438
+ // - Avoid special characters
439
+ ```
440
+
441
+ ### `setImage`
442
+
443
+ Sets the card image URL.
444
+
445
+ **Parameters:**
446
+ - `image: string` — image URL
447
+
448
+ **Returns:** `this` — for chaining calls
449
+
450
+ ```javascript
451
+ const twitter = new MetaTwitter()
452
+
453
+ // Set image
454
+ twitter.setImage('https://example.com/images/twitter-card.jpg')
455
+
456
+ // Absolute URL
457
+ const imageUrl = new URL('/images/twitter-image.jpg', window.location.origin).href
458
+ twitter.setImage(imageUrl)
459
+
460
+ // From content data
461
+ twitter.setImage(article.featuredImage)
462
+
463
+ // Fallback image
464
+ twitter.setImage(article.image || '/images/default-twitter.jpg')
465
+
466
+ // For summary card (square image)
467
+ twitter
468
+ .setCard(MetaTwitterCard.summary)
469
+ .setImage('https://example.com/square-image.jpg') // 1:1 ratio
470
+
471
+ // For summary_large_image (wide image)
472
+ twitter
473
+ .setCard(MetaTwitterCard.summaryLargeImage)
474
+ .setImage('https://example.com/wide-image.jpg') // 2:1 ratio
475
+
476
+ // Recommended sizes:
477
+ // summary: 120x120 - 1:1 (minimum)
478
+ // 280x150 - optimal
479
+ // summary_large_image: 300x157 - minimum
480
+ // 1200x628 - optimal (like OG)
481
+ // Ratio 2:1 or 1.91:1
482
+ // Formats: JPG, PNG, WebP, GIF
483
+ // Maximum size: 5 MB
484
+ ```
485
+
486
+ ## Practical Examples
487
+
488
+ ### Complete Article Page Setup
489
+
490
+ ```javascript
491
+ import { MetaTwitter, MetaTwitterCard } from '@dxtmisha/functional'
492
+
493
+ const twitter = new MetaTwitter()
494
+
495
+ // Set all main tags
496
+ twitter
497
+ .setCard(MetaTwitterCard.summaryLargeImage)
498
+ .setTitle('Complete Guide to Twitter Cards')
499
+ .setDescription('Learn how to properly configure Twitter Card tags for your site and improve Twitter sharing')
500
+ .setUrl('https://example.com/articles/twitter-cards-guide')
501
+ .setImage('https://example.com/images/twitter-guide.jpg')
502
+ .setSite('@mywebsite')
503
+ .setCreator('@author_name')
504
+
505
+ // Now when shared on Twitter:
506
+ // - A beautiful card with large image will be displayed
507
+ // - Title and description will be shown
508
+ // - Attribution will appear as "via @mywebsite by @author_name"
509
+ ```
510
+
511
+ ### Dynamic Updates for SPA
512
+
513
+ ```javascript
514
+ // Vue Router
515
+ router.afterEach((to) => {
516
+ const twitter = new MetaTwitter()
517
+
518
+ twitter
519
+ .setCard(MetaTwitterCard.summaryLargeImage)
520
+ .setTitle(to.meta.twitterTitle || to.meta.title)
521
+ .setDescription(to.meta.twitterDescription || to.meta.description)
522
+ .setUrl(`https://example.com${to.path}`)
523
+ .setImage(to.meta.twitterImage || '/images/default-twitter.jpg')
524
+ .setSite('@mywebsite')
525
+ })
526
+
527
+ // React Router
528
+ useEffect(() => {
529
+ const twitter = new MetaTwitter()
530
+
531
+ twitter
532
+ .setCard(MetaTwitterCard.summaryLargeImage)
533
+ .setTitle(page.title)
534
+ .setDescription(page.description)
535
+ .setUrl(window.location.href)
536
+ .setImage(page.image)
537
+ .setSite(config.twitterSite)
538
+ .setCreator(page.author?.twitter)
539
+
540
+ return () => {
541
+ // Cleanup if needed
542
+ }
543
+ }, [page])
544
+ ```
545
+
546
+ ### Setup for Different Content Types
547
+
548
+ ```javascript
549
+ import { MetaTwitter, MetaTwitterCard } from '@dxtmisha/functional'
550
+
551
+ const twitter = new MetaTwitter()
552
+
553
+ // For blog post
554
+ const setupBlogPost = (post) => {
555
+ twitter
556
+ .setCard(MetaTwitterCard.summaryLargeImage)
557
+ .setTitle(post.title)
558
+ .setDescription(post.excerpt)
559
+ .setUrl(`https://example.com/blog/${post.slug}`)
560
+ .setImage(post.coverImage)
561
+ .setSite('@myblog')
562
+ .setCreator(post.author.twitter)
563
+ }
564
+
565
+ // For news (with small image)
566
+ const setupNews = (news) => {
567
+ twitter
568
+ .setCard(MetaTwitterCard.summary)
569
+ .setTitle(news.headline)
570
+ .setDescription(news.summary)
571
+ .setUrl(`https://example.com/news/${news.id}`)
572
+ .setImage(news.thumbnail)
573
+ .setSite('@mynews')
574
+ }
575
+
576
+ // For video
577
+ const setupVideo = (video) => {
578
+ twitter
579
+ .setCard(MetaTwitterCard.player)
580
+ .setTitle(video.title)
581
+ .setDescription(video.description)
582
+ .setUrl(`https://example.com/videos/${video.id}`)
583
+ .setImage(video.thumbnail)
584
+ .setSite('@myvideos')
585
+ }
586
+
587
+ // For homepage
588
+ const setupHomePage = () => {
589
+ twitter
590
+ .setCard(MetaTwitterCard.summaryLargeImage)
591
+ .setTitle('Welcome to Our Website')
592
+ .setDescription('The best content about web development and technology')
593
+ .setUrl('https://example.com')
594
+ .setImage('https://example.com/images/home-twitter.jpg')
595
+ .setSite('@mywebsite')
596
+ }
597
+ ```
598
+
599
+ ### HTML Generation for SSR
600
+
601
+ ```javascript
602
+ import { MetaTwitter, MetaTwitterCard } from '@dxtmisha/functional'
603
+
604
+ // Express.js server
605
+ app.get('/article/:id', async (req, res) => {
606
+ const article = await getArticle(req.params.id)
607
+
608
+ const twitter = new MetaTwitter()
609
+ twitter
610
+ .setCard(MetaTwitterCard.summaryLargeImage)
611
+ .setTitle(article.title)
612
+ .setDescription(article.excerpt)
613
+ .setUrl(`https://example.com/article/${article.id}`)
614
+ .setImage(article.coverImage)
615
+ .setSite('@mywebsite')
616
+ .setCreator(article.author.twitter)
617
+
618
+ const html = `
619
+ <!DOCTYPE html>
620
+ <html>
621
+ <head>
622
+ <title>${article.title}</title>
623
+ ${twitter.html()}
624
+ </head>
625
+ <body>
626
+ ${article.content}
627
+ </body>
628
+ </html>
629
+ `
630
+
631
+ res.send(html)
632
+ })
633
+
634
+ // Result in HTML:
635
+ // <meta property="twitter:card" content="summary_large_image">
636
+ // <meta property="twitter:title" content="Article Title">
637
+ // <meta property="twitter:description" content="Description...">
638
+ // <meta property="twitter:url" content="https://example.com/article/123">
639
+ // <meta property="twitter:image" content="https://example.com/images/cover.jpg">
640
+ // <meta property="twitter:site" content="@mywebsite">
641
+ // <meta property="twitter:creator" content="@author">
642
+ ```
643
+
644
+ ### Combining with Open Graph
645
+
646
+ ```javascript
647
+ import { MetaTwitter, MetaOg, MetaTwitterCard, MetaOpenGraphType } from '@dxtmisha/functional'
648
+
649
+ const twitter = new MetaTwitter()
650
+ const og = new MetaOg()
651
+
652
+ // Common update function
653
+ const updateSocialMeta = (data) => {
654
+ // Twitter Cards
655
+ twitter
656
+ .setCard(MetaTwitterCard.summaryLargeImage)
657
+ .setTitle(data.title)
658
+ .setDescription(data.description)
659
+ .setUrl(data.url)
660
+ .setImage(data.image)
661
+ .setSite(data.twitterSite)
662
+ .setCreator(data.twitterCreator)
663
+
664
+ // Open Graph
665
+ og
666
+ .setType(MetaOpenGraphType.article)
667
+ .setTitle(data.title)
668
+ .setDescription(data.description)
669
+ .setUrl(data.url)
670
+ .setImage(data.image)
671
+ .setSiteName(data.siteName)
672
+ .setLocale('en_US')
673
+ }
674
+
675
+ // Usage
676
+ updateSocialMeta({
677
+ title: 'Article Title',
678
+ description: 'Article description',
679
+ url: 'https://example.com/article/123',
680
+ image: 'https://example.com/images/cover.jpg',
681
+ twitterSite: '@mywebsite',
682
+ twitterCreator: '@author',
683
+ siteName: 'My Website'
684
+ })
685
+
686
+ // For SSR - combined HTML
687
+ const allSocialMetaHTML = twitter.html() + og.html()
688
+ ```
689
+
690
+ ### CMS Integration
691
+
692
+ ```javascript
693
+ import { MetaTwitter, MetaTwitterCard } from '@dxtmisha/functional'
694
+
695
+ // Function to update Twitter Card from CMS data
696
+ const updateTwitterFromCMS = (pageData) => {
697
+ const twitter = new MetaTwitter()
698
+
699
+ // Determine card type
700
+ const cardMap = {
701
+ 'post': MetaTwitterCard.summaryLargeImage,
702
+ 'news': MetaTwitterCard.summary,
703
+ 'video': MetaTwitterCard.player
704
+ }
705
+
706
+ twitter
707
+ .setCard(cardMap[pageData.contentType] || MetaTwitterCard.summaryLargeImage)
708
+ .setTitle(pageData.seo?.twitterTitle || pageData.title)
709
+ .setDescription(pageData.seo?.twitterDescription || pageData.excerpt)
710
+ .setUrl(pageData.canonicalUrl)
711
+ .setImage(pageData.seo?.twitterImage || pageData.featuredImage)
712
+ .setSite(pageData.site.twitterHandle)
713
+
714
+ // Add author if available
715
+ if (pageData.author?.twitter) {
716
+ twitter.setCreator(pageData.author.twitter)
717
+ }
718
+
719
+ return twitter
720
+ }
721
+
722
+ // Usage
723
+ const page = await cms.getPage(pageId)
724
+ updateTwitterFromCMS(page)
725
+ ```
726
+
727
+ ### Validation and Debugging
728
+
729
+ ```javascript
730
+ import { MetaTwitter } from '@dxtmisha/functional'
731
+
732
+ const twitter = new MetaTwitter()
733
+
734
+ // Check required fields
735
+ const validateTwitterCard = () => {
736
+ const errors = []
737
+
738
+ if (!twitter.getCard()) errors.push('Missing twitter:card')
739
+ if (!twitter.getTitle()) errors.push('Missing twitter:title')
740
+ if (!twitter.getDescription()) errors.push('Missing twitter:description')
741
+ if (!twitter.getImage()) errors.push('Missing twitter:image')
742
+
743
+ // Check length
744
+ if (twitter.getTitle().length > 70) {
745
+ errors.push('twitter:title is too long (>70 characters)')
746
+ }
747
+
748
+ if (twitter.getDescription().length > 200) {
749
+ errors.push('twitter:description is too long (>200 characters)')
750
+ }
751
+
752
+ if (errors.length > 0) {
753
+ console.error('Twitter Card errors:', errors)
754
+ }
755
+
756
+ return errors.length === 0
757
+ }
758
+
759
+ // Output all Twitter Card tags for debugging
760
+ const debugTwitterCard = () => {
761
+ console.group('Twitter Card Tags')
762
+ console.log('Card Type:', twitter.getCard())
763
+ console.log('Title:', twitter.getTitle())
764
+ console.log('Description:', twitter.getDescription())
765
+ console.log('Image:', twitter.getImage())
766
+ console.log('URL:', twitter.getUrl())
767
+ console.log('Site:', twitter.getSite())
768
+ console.log('Creator:', twitter.getCreator())
769
+ console.groupEnd()
770
+ }
771
+
772
+ // Export for testing
773
+ const exportTwitterData = () => {
774
+ return twitter.getItems()
775
+ }
776
+
777
+ // Check before publishing
778
+ const checkBeforePublish = () => {
779
+ const isValid = validateTwitterCard()
780
+
781
+ if (isValid) {
782
+ console.log('✓ Twitter Card configured correctly')
783
+ } else {
784
+ console.warn('⚠ Twitter Card needs attention')
785
+ debugTwitterCard()
786
+ }
787
+
788
+ return isValid
789
+ }
790
+ ```
791
+
792
+ ## Usage Recommendations
793
+
794
+ ### Required Tags
795
+ For correct Twitter Card display, set at minimum:
796
+ - `twitter:card` — card type
797
+ - `twitter:title` — title
798
+ - `twitter:description` — description
799
+ - `twitter:image` — image
800
+
801
+ ### Image Sizes
802
+
803
+ **summary card:**
804
+ - **Recommended size:** 120×120 px (minimum)
805
+ - **Optimal size:** 280×150 px
806
+ - **Aspect ratio:** 1:1 (square)
807
+
808
+ **summary_large_image card:**
809
+ - **Minimum size:** 300×157 px
810
+ - **Optimal size:** 1200×628 px (like Open Graph)
811
+ - **Aspect ratio:** 2:1 or 1.91:1
812
+ - **Maximum file size:** 5 MB
813
+ - **Formats:** JPG, PNG, WebP, GIF
814
+
815
+ ### Text Length
816
+ - **twitter:title:** up to 70 characters
817
+ - **twitter:description:** up to 200 characters
818
+ - **twitter:site:** @username format
819
+ - **twitter:creator:** @username format
820
+
821
+ ### @username Attributes
822
+ - **twitter:site** — official Twitter account of the site/brand
823
+ - Shows as "via @username"
824
+ - Used for site attribution
825
+ - **twitter:creator** — Twitter account of the content author
826
+ - Shows as "by @username"
827
+ - Used for author attribution
828
+
829
+ ### Testing
830
+ Check Twitter Card tags using:
831
+ - [Twitter Card Validator](https://cards-dev.twitter.com/validator) (legacy)
832
+ - Test by posting a test link on Twitter
833
+ - Use preview mode when creating a tweet
834
+
835
+ ### Differences from Open Graph
836
+ Twitter Cards can use Open Graph tags as fallback:
837
+ - If `twitter:title` is missing, uses `og:title`
838
+ - If `twitter:description` is missing, uses `og:description`
839
+ - If `twitter:image` is missing, uses `og:image`
840
+
841
+ However, it's recommended to set Twitter Card tags explicitly for better control.
842
+
843
+ ## Notes
844
+
845
+ - The class inherits all methods from `MetaManager`, including `html()`, `getItems()`, `setByList()`
846
+ - Automatically uses the `property` attribute (like Open Graph)
847
+ - All changes are immediately reflected in the DOM tree
848
+ - When creating an instance, existing Twitter Card tags from the page are automatically read
849
+ - For SSR, use the `html()` method to generate meta tags in the server template
850
+ - Content is automatically escaped to prevent XSS
851
+ - Twitter may cache cards, use Card Validator to clear cache
852
+ - Supports all official Twitter Card types
853
+