@ckeditor/ckeditor5-bookmark 0.0.1 → 44.0.0-alpha.0

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 (408) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +4 -5
  3. package/README.md +31 -3
  4. package/build/bookmark.js +5 -0
  5. package/build/translations/af.js +1 -0
  6. package/build/translations/ar.js +1 -0
  7. package/build/translations/ast.js +1 -0
  8. package/build/translations/az.js +1 -0
  9. package/build/translations/bg.js +1 -0
  10. package/build/translations/bn.js +1 -0
  11. package/build/translations/bs.js +1 -0
  12. package/build/translations/ca.js +1 -0
  13. package/build/translations/cs.js +1 -0
  14. package/build/translations/da.js +1 -0
  15. package/build/translations/de-ch.js +1 -0
  16. package/build/translations/de.js +1 -0
  17. package/build/translations/el.js +1 -0
  18. package/build/translations/en-au.js +1 -0
  19. package/build/translations/en-gb.js +1 -0
  20. package/build/translations/eo.js +1 -0
  21. package/build/translations/es-co.js +1 -0
  22. package/build/translations/es.js +1 -0
  23. package/build/translations/et.js +1 -0
  24. package/build/translations/eu.js +1 -0
  25. package/build/translations/fa.js +1 -0
  26. package/build/translations/fi.js +1 -0
  27. package/build/translations/fr.js +1 -0
  28. package/build/translations/gl.js +1 -0
  29. package/build/translations/gu.js +1 -0
  30. package/build/translations/he.js +1 -0
  31. package/build/translations/hi.js +1 -0
  32. package/build/translations/hr.js +1 -0
  33. package/build/translations/hu.js +1 -0
  34. package/build/translations/hy.js +1 -0
  35. package/build/translations/id.js +1 -0
  36. package/build/translations/it.js +1 -0
  37. package/build/translations/ja.js +1 -0
  38. package/build/translations/jv.js +1 -0
  39. package/build/translations/kk.js +1 -0
  40. package/build/translations/km.js +1 -0
  41. package/build/translations/kn.js +1 -0
  42. package/build/translations/ko.js +1 -0
  43. package/build/translations/ku.js +1 -0
  44. package/build/translations/lt.js +1 -0
  45. package/build/translations/lv.js +1 -0
  46. package/build/translations/ms.js +1 -0
  47. package/build/translations/nb.js +1 -0
  48. package/build/translations/ne.js +1 -0
  49. package/build/translations/nl.js +1 -0
  50. package/build/translations/no.js +1 -0
  51. package/build/translations/oc.js +1 -0
  52. package/build/translations/pl.js +1 -0
  53. package/build/translations/pt-br.js +1 -0
  54. package/build/translations/pt.js +1 -0
  55. package/build/translations/ro.js +1 -0
  56. package/build/translations/ru.js +1 -0
  57. package/build/translations/si.js +1 -0
  58. package/build/translations/sk.js +1 -0
  59. package/build/translations/sl.js +1 -0
  60. package/build/translations/sq.js +1 -0
  61. package/build/translations/sr-latn.js +1 -0
  62. package/build/translations/sr.js +1 -0
  63. package/build/translations/sv.js +1 -0
  64. package/build/translations/th.js +1 -0
  65. package/build/translations/ti.js +1 -0
  66. package/build/translations/tk.js +1 -0
  67. package/build/translations/tr.js +1 -0
  68. package/build/translations/tt.js +1 -0
  69. package/build/translations/ug.js +1 -0
  70. package/build/translations/uk.js +1 -0
  71. package/build/translations/ur.js +1 -0
  72. package/build/translations/uz.js +1 -0
  73. package/build/translations/vi.js +1 -0
  74. package/build/translations/zh-cn.js +1 -0
  75. package/build/translations/zh.js +1 -0
  76. package/ckeditor5-metadata.json +24 -0
  77. package/dist/augmentation.d.ts +28 -0
  78. package/dist/bookmark.d.ts +34 -0
  79. package/dist/bookmarkconfig.d.ts +52 -0
  80. package/dist/bookmarkediting.d.ts +55 -0
  81. package/dist/bookmarkui.d.ts +170 -0
  82. package/dist/index-content.css +4 -0
  83. package/dist/index-editor.css +150 -0
  84. package/dist/index.css +195 -0
  85. package/dist/index.css.map +1 -0
  86. package/dist/index.d.ts +18 -0
  87. package/dist/index.js +1320 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/insertbookmarkcommand.d.ts +42 -0
  90. package/dist/translations/af.d.ts +8 -0
  91. package/dist/translations/af.js +5 -0
  92. package/dist/translations/af.umd.js +11 -0
  93. package/dist/translations/ar.d.ts +8 -0
  94. package/dist/translations/ar.js +5 -0
  95. package/dist/translations/ar.umd.js +11 -0
  96. package/dist/translations/ast.d.ts +8 -0
  97. package/dist/translations/ast.js +5 -0
  98. package/dist/translations/ast.umd.js +11 -0
  99. package/dist/translations/az.d.ts +8 -0
  100. package/dist/translations/az.js +5 -0
  101. package/dist/translations/az.umd.js +11 -0
  102. package/dist/translations/bg.d.ts +8 -0
  103. package/dist/translations/bg.js +5 -0
  104. package/dist/translations/bg.umd.js +11 -0
  105. package/dist/translations/bn.d.ts +8 -0
  106. package/dist/translations/bn.js +5 -0
  107. package/dist/translations/bn.umd.js +11 -0
  108. package/dist/translations/bs.d.ts +8 -0
  109. package/dist/translations/bs.js +5 -0
  110. package/dist/translations/bs.umd.js +11 -0
  111. package/dist/translations/ca.d.ts +8 -0
  112. package/dist/translations/ca.js +5 -0
  113. package/dist/translations/ca.umd.js +11 -0
  114. package/dist/translations/cs.d.ts +8 -0
  115. package/dist/translations/cs.js +5 -0
  116. package/dist/translations/cs.umd.js +11 -0
  117. package/dist/translations/da.d.ts +8 -0
  118. package/dist/translations/da.js +5 -0
  119. package/dist/translations/da.umd.js +11 -0
  120. package/dist/translations/de-ch.d.ts +8 -0
  121. package/dist/translations/de-ch.js +5 -0
  122. package/dist/translations/de-ch.umd.js +11 -0
  123. package/dist/translations/de.d.ts +8 -0
  124. package/dist/translations/de.js +5 -0
  125. package/dist/translations/de.umd.js +11 -0
  126. package/dist/translations/el.d.ts +8 -0
  127. package/dist/translations/el.js +5 -0
  128. package/dist/translations/el.umd.js +11 -0
  129. package/dist/translations/en-au.d.ts +8 -0
  130. package/dist/translations/en-au.js +5 -0
  131. package/dist/translations/en-au.umd.js +11 -0
  132. package/dist/translations/en-gb.d.ts +8 -0
  133. package/dist/translations/en-gb.js +5 -0
  134. package/dist/translations/en-gb.umd.js +11 -0
  135. package/dist/translations/en.d.ts +8 -0
  136. package/dist/translations/en.js +5 -0
  137. package/dist/translations/en.umd.js +11 -0
  138. package/dist/translations/eo.d.ts +8 -0
  139. package/dist/translations/eo.js +5 -0
  140. package/dist/translations/eo.umd.js +11 -0
  141. package/dist/translations/es-co.d.ts +8 -0
  142. package/dist/translations/es-co.js +5 -0
  143. package/dist/translations/es-co.umd.js +11 -0
  144. package/dist/translations/es.d.ts +8 -0
  145. package/dist/translations/es.js +5 -0
  146. package/dist/translations/es.umd.js +11 -0
  147. package/dist/translations/et.d.ts +8 -0
  148. package/dist/translations/et.js +5 -0
  149. package/dist/translations/et.umd.js +11 -0
  150. package/dist/translations/eu.d.ts +8 -0
  151. package/dist/translations/eu.js +5 -0
  152. package/dist/translations/eu.umd.js +11 -0
  153. package/dist/translations/fa.d.ts +8 -0
  154. package/dist/translations/fa.js +5 -0
  155. package/dist/translations/fa.umd.js +11 -0
  156. package/dist/translations/fi.d.ts +8 -0
  157. package/dist/translations/fi.js +5 -0
  158. package/dist/translations/fi.umd.js +11 -0
  159. package/dist/translations/fr.d.ts +8 -0
  160. package/dist/translations/fr.js +5 -0
  161. package/dist/translations/fr.umd.js +11 -0
  162. package/dist/translations/gl.d.ts +8 -0
  163. package/dist/translations/gl.js +5 -0
  164. package/dist/translations/gl.umd.js +11 -0
  165. package/dist/translations/gu.d.ts +8 -0
  166. package/dist/translations/gu.js +5 -0
  167. package/dist/translations/gu.umd.js +11 -0
  168. package/dist/translations/he.d.ts +8 -0
  169. package/dist/translations/he.js +5 -0
  170. package/dist/translations/he.umd.js +11 -0
  171. package/dist/translations/hi.d.ts +8 -0
  172. package/dist/translations/hi.js +5 -0
  173. package/dist/translations/hi.umd.js +11 -0
  174. package/dist/translations/hr.d.ts +8 -0
  175. package/dist/translations/hr.js +5 -0
  176. package/dist/translations/hr.umd.js +11 -0
  177. package/dist/translations/hu.d.ts +8 -0
  178. package/dist/translations/hu.js +5 -0
  179. package/dist/translations/hu.umd.js +11 -0
  180. package/dist/translations/hy.d.ts +8 -0
  181. package/dist/translations/hy.js +5 -0
  182. package/dist/translations/hy.umd.js +11 -0
  183. package/dist/translations/id.d.ts +8 -0
  184. package/dist/translations/id.js +5 -0
  185. package/dist/translations/id.umd.js +11 -0
  186. package/dist/translations/it.d.ts +8 -0
  187. package/dist/translations/it.js +5 -0
  188. package/dist/translations/it.umd.js +11 -0
  189. package/dist/translations/ja.d.ts +8 -0
  190. package/dist/translations/ja.js +5 -0
  191. package/dist/translations/ja.umd.js +11 -0
  192. package/dist/translations/jv.d.ts +8 -0
  193. package/dist/translations/jv.js +5 -0
  194. package/dist/translations/jv.umd.js +11 -0
  195. package/dist/translations/kk.d.ts +8 -0
  196. package/dist/translations/kk.js +5 -0
  197. package/dist/translations/kk.umd.js +11 -0
  198. package/dist/translations/km.d.ts +8 -0
  199. package/dist/translations/km.js +5 -0
  200. package/dist/translations/km.umd.js +11 -0
  201. package/dist/translations/kn.d.ts +8 -0
  202. package/dist/translations/kn.js +5 -0
  203. package/dist/translations/kn.umd.js +11 -0
  204. package/dist/translations/ko.d.ts +8 -0
  205. package/dist/translations/ko.js +5 -0
  206. package/dist/translations/ko.umd.js +11 -0
  207. package/dist/translations/ku.d.ts +8 -0
  208. package/dist/translations/ku.js +5 -0
  209. package/dist/translations/ku.umd.js +11 -0
  210. package/dist/translations/lt.d.ts +8 -0
  211. package/dist/translations/lt.js +5 -0
  212. package/dist/translations/lt.umd.js +11 -0
  213. package/dist/translations/lv.d.ts +8 -0
  214. package/dist/translations/lv.js +5 -0
  215. package/dist/translations/lv.umd.js +11 -0
  216. package/dist/translations/ms.d.ts +8 -0
  217. package/dist/translations/ms.js +5 -0
  218. package/dist/translations/ms.umd.js +11 -0
  219. package/dist/translations/nb.d.ts +8 -0
  220. package/dist/translations/nb.js +5 -0
  221. package/dist/translations/nb.umd.js +11 -0
  222. package/dist/translations/ne.d.ts +8 -0
  223. package/dist/translations/ne.js +5 -0
  224. package/dist/translations/ne.umd.js +11 -0
  225. package/dist/translations/nl.d.ts +8 -0
  226. package/dist/translations/nl.js +5 -0
  227. package/dist/translations/nl.umd.js +11 -0
  228. package/dist/translations/no.d.ts +8 -0
  229. package/dist/translations/no.js +5 -0
  230. package/dist/translations/no.umd.js +11 -0
  231. package/dist/translations/oc.d.ts +8 -0
  232. package/dist/translations/oc.js +5 -0
  233. package/dist/translations/oc.umd.js +11 -0
  234. package/dist/translations/pl.d.ts +8 -0
  235. package/dist/translations/pl.js +5 -0
  236. package/dist/translations/pl.umd.js +11 -0
  237. package/dist/translations/pt-br.d.ts +8 -0
  238. package/dist/translations/pt-br.js +5 -0
  239. package/dist/translations/pt-br.umd.js +11 -0
  240. package/dist/translations/pt.d.ts +8 -0
  241. package/dist/translations/pt.js +5 -0
  242. package/dist/translations/pt.umd.js +11 -0
  243. package/dist/translations/ro.d.ts +8 -0
  244. package/dist/translations/ro.js +5 -0
  245. package/dist/translations/ro.umd.js +11 -0
  246. package/dist/translations/ru.d.ts +8 -0
  247. package/dist/translations/ru.js +5 -0
  248. package/dist/translations/ru.umd.js +11 -0
  249. package/dist/translations/si.d.ts +8 -0
  250. package/dist/translations/si.js +5 -0
  251. package/dist/translations/si.umd.js +11 -0
  252. package/dist/translations/sk.d.ts +8 -0
  253. package/dist/translations/sk.js +5 -0
  254. package/dist/translations/sk.umd.js +11 -0
  255. package/dist/translations/sl.d.ts +8 -0
  256. package/dist/translations/sl.js +5 -0
  257. package/dist/translations/sl.umd.js +11 -0
  258. package/dist/translations/sq.d.ts +8 -0
  259. package/dist/translations/sq.js +5 -0
  260. package/dist/translations/sq.umd.js +11 -0
  261. package/dist/translations/sr-latn.d.ts +8 -0
  262. package/dist/translations/sr-latn.js +5 -0
  263. package/dist/translations/sr-latn.umd.js +11 -0
  264. package/dist/translations/sr.d.ts +8 -0
  265. package/dist/translations/sr.js +5 -0
  266. package/dist/translations/sr.umd.js +11 -0
  267. package/dist/translations/sv.d.ts +8 -0
  268. package/dist/translations/sv.js +5 -0
  269. package/dist/translations/sv.umd.js +11 -0
  270. package/dist/translations/th.d.ts +8 -0
  271. package/dist/translations/th.js +5 -0
  272. package/dist/translations/th.umd.js +11 -0
  273. package/dist/translations/ti.d.ts +8 -0
  274. package/dist/translations/ti.js +5 -0
  275. package/dist/translations/ti.umd.js +11 -0
  276. package/dist/translations/tk.d.ts +8 -0
  277. package/dist/translations/tk.js +5 -0
  278. package/dist/translations/tk.umd.js +11 -0
  279. package/dist/translations/tr.d.ts +8 -0
  280. package/dist/translations/tr.js +5 -0
  281. package/dist/translations/tr.umd.js +11 -0
  282. package/dist/translations/tt.d.ts +8 -0
  283. package/dist/translations/tt.js +5 -0
  284. package/dist/translations/tt.umd.js +11 -0
  285. package/dist/translations/ug.d.ts +8 -0
  286. package/dist/translations/ug.js +5 -0
  287. package/dist/translations/ug.umd.js +11 -0
  288. package/dist/translations/uk.d.ts +8 -0
  289. package/dist/translations/uk.js +5 -0
  290. package/dist/translations/uk.umd.js +11 -0
  291. package/dist/translations/ur.d.ts +8 -0
  292. package/dist/translations/ur.js +5 -0
  293. package/dist/translations/ur.umd.js +11 -0
  294. package/dist/translations/uz.d.ts +8 -0
  295. package/dist/translations/uz.js +5 -0
  296. package/dist/translations/uz.umd.js +11 -0
  297. package/dist/translations/vi.d.ts +8 -0
  298. package/dist/translations/vi.js +5 -0
  299. package/dist/translations/vi.umd.js +11 -0
  300. package/dist/translations/zh-cn.d.ts +8 -0
  301. package/dist/translations/zh-cn.js +5 -0
  302. package/dist/translations/zh-cn.umd.js +11 -0
  303. package/dist/translations/zh.d.ts +8 -0
  304. package/dist/translations/zh.js +5 -0
  305. package/dist/translations/zh.umd.js +11 -0
  306. package/dist/ui/bookmarkactionsview.d.ts +106 -0
  307. package/dist/ui/bookmarkformview.d.ts +122 -0
  308. package/dist/updatebookmarkcommand.d.ts +46 -0
  309. package/dist/utils.d.ts +15 -0
  310. package/lang/contexts.json +13 -0
  311. package/lang/translations/af.po +56 -0
  312. package/lang/translations/ar.po +56 -0
  313. package/lang/translations/ast.po +56 -0
  314. package/lang/translations/az.po +56 -0
  315. package/lang/translations/bg.po +56 -0
  316. package/lang/translations/bn.po +56 -0
  317. package/lang/translations/bs.po +56 -0
  318. package/lang/translations/ca.po +56 -0
  319. package/lang/translations/cs.po +56 -0
  320. package/lang/translations/da.po +56 -0
  321. package/lang/translations/de-ch.po +56 -0
  322. package/lang/translations/de.po +56 -0
  323. package/lang/translations/el.po +56 -0
  324. package/lang/translations/en-au.po +56 -0
  325. package/lang/translations/en-gb.po +56 -0
  326. package/lang/translations/en.po +56 -0
  327. package/lang/translations/eo.po +56 -0
  328. package/lang/translations/es-co.po +56 -0
  329. package/lang/translations/es.po +56 -0
  330. package/lang/translations/et.po +56 -0
  331. package/lang/translations/eu.po +56 -0
  332. package/lang/translations/fa.po +56 -0
  333. package/lang/translations/fi.po +56 -0
  334. package/lang/translations/fr.po +56 -0
  335. package/lang/translations/gl.po +56 -0
  336. package/lang/translations/gu.po +56 -0
  337. package/lang/translations/he.po +56 -0
  338. package/lang/translations/hi.po +56 -0
  339. package/lang/translations/hr.po +56 -0
  340. package/lang/translations/hu.po +56 -0
  341. package/lang/translations/hy.po +56 -0
  342. package/lang/translations/id.po +56 -0
  343. package/lang/translations/it.po +56 -0
  344. package/lang/translations/ja.po +56 -0
  345. package/lang/translations/jv.po +56 -0
  346. package/lang/translations/kk.po +56 -0
  347. package/lang/translations/km.po +56 -0
  348. package/lang/translations/kn.po +56 -0
  349. package/lang/translations/ko.po +56 -0
  350. package/lang/translations/ku.po +56 -0
  351. package/lang/translations/lt.po +56 -0
  352. package/lang/translations/lv.po +56 -0
  353. package/lang/translations/ms.po +56 -0
  354. package/lang/translations/nb.po +56 -0
  355. package/lang/translations/ne.po +56 -0
  356. package/lang/translations/nl.po +56 -0
  357. package/lang/translations/no.po +56 -0
  358. package/lang/translations/oc.po +56 -0
  359. package/lang/translations/pl.po +56 -0
  360. package/lang/translations/pt-br.po +56 -0
  361. package/lang/translations/pt.po +56 -0
  362. package/lang/translations/ro.po +56 -0
  363. package/lang/translations/ru.po +56 -0
  364. package/lang/translations/si.po +56 -0
  365. package/lang/translations/sk.po +56 -0
  366. package/lang/translations/sl.po +56 -0
  367. package/lang/translations/sq.po +56 -0
  368. package/lang/translations/sr-latn.po +56 -0
  369. package/lang/translations/sr.po +56 -0
  370. package/lang/translations/sv.po +56 -0
  371. package/lang/translations/th.po +56 -0
  372. package/lang/translations/ti.po +56 -0
  373. package/lang/translations/tk.po +56 -0
  374. package/lang/translations/tr.po +56 -0
  375. package/lang/translations/tt.po +56 -0
  376. package/lang/translations/ug.po +56 -0
  377. package/lang/translations/uk.po +56 -0
  378. package/lang/translations/ur.po +56 -0
  379. package/lang/translations/uz.po +56 -0
  380. package/lang/translations/vi.po +56 -0
  381. package/lang/translations/zh-cn.po +56 -0
  382. package/lang/translations/zh.po +56 -0
  383. package/package.json +32 -3
  384. package/src/augmentation.d.ts +24 -0
  385. package/src/augmentation.js +5 -0
  386. package/src/bookmark.d.ts +30 -0
  387. package/src/bookmark.js +36 -0
  388. package/src/bookmarkconfig.d.ts +48 -0
  389. package/src/bookmarkconfig.js +5 -0
  390. package/src/bookmarkediting.d.ts +51 -0
  391. package/src/bookmarkediting.js +211 -0
  392. package/src/bookmarkui.d.ts +166 -0
  393. package/src/bookmarkui.js +582 -0
  394. package/src/index.d.ts +14 -0
  395. package/src/index.js +13 -0
  396. package/src/insertbookmarkcommand.d.ts +38 -0
  397. package/src/insertbookmarkcommand.js +113 -0
  398. package/src/ui/bookmarkactionsview.d.ts +102 -0
  399. package/src/ui/bookmarkactionsview.js +154 -0
  400. package/src/ui/bookmarkformview.d.ts +118 -0
  401. package/src/ui/bookmarkformview.js +203 -0
  402. package/src/updatebookmarkcommand.d.ts +42 -0
  403. package/src/updatebookmarkcommand.js +75 -0
  404. package/src/utils.d.ts +11 -0
  405. package/src/utils.js +19 -0
  406. package/theme/bookmark.css +50 -0
  407. package/theme/bookmarkactions.css +44 -0
  408. package/theme/bookmarkform.css +42 -0
@@ -0,0 +1,582 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module bookmark/bookmarkui
7
+ */
8
+ import { Plugin, icons } from 'ckeditor5/src/core.js';
9
+ import { ButtonView, ContextualBalloon, CssTransitionDisablerMixin, MenuBarMenuListItemButtonView, clickOutsideHandler } from 'ckeditor5/src/ui.js';
10
+ import { ClickObserver } from 'ckeditor5/src/engine.js';
11
+ import BookmarkFormView from './ui/bookmarkformview.js';
12
+ import BookmarkActionsView from './ui/bookmarkactionsview.js';
13
+ import BookmarkEditing from './bookmarkediting.js';
14
+ const VISUAL_SELECTION_MARKER_NAME = 'bookmark-ui';
15
+ /**
16
+ * The UI plugin of the bookmark feature.
17
+ *
18
+ * It registers the `'bookmark'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
19
+ * which inserts the `bookmark` element upon selection.
20
+ */
21
+ export default class BookmarkUI extends Plugin {
22
+ constructor() {
23
+ super(...arguments);
24
+ /**
25
+ * The actions view displayed inside of the balloon.
26
+ */
27
+ this.actionsView = null;
28
+ /**
29
+ * The form view displayed inside the balloon.
30
+ */
31
+ this.formView = null;
32
+ }
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ static get requires() {
37
+ return [BookmarkEditing, ContextualBalloon];
38
+ }
39
+ /**
40
+ * @inheritDoc
41
+ */
42
+ static get pluginName() {
43
+ return 'BookmarkUI';
44
+ }
45
+ /**
46
+ * @inheritDoc
47
+ */
48
+ static get isOfficialPlugin() {
49
+ return true;
50
+ }
51
+ /**
52
+ * @inheritDoc
53
+ */
54
+ init() {
55
+ const editor = this.editor;
56
+ editor.editing.view.addObserver(ClickObserver);
57
+ this._balloon = editor.plugins.get(ContextualBalloon);
58
+ // Create toolbar buttons.
59
+ this._createToolbarBookmarkButton();
60
+ this._enableBalloonActivators();
61
+ // Renders a fake visual selection marker on an expanded selection.
62
+ editor.conversion.for('editingDowncast').markerToHighlight({
63
+ model: VISUAL_SELECTION_MARKER_NAME,
64
+ view: {
65
+ classes: ['ck-fake-bookmark-selection']
66
+ }
67
+ });
68
+ // Renders a fake visual selection marker on a collapsed selection.
69
+ editor.conversion.for('editingDowncast').markerToElement({
70
+ model: VISUAL_SELECTION_MARKER_NAME,
71
+ view: (data, { writer }) => {
72
+ if (!data.markerRange.isCollapsed) {
73
+ return null;
74
+ }
75
+ const markerElement = writer.createUIElement('span');
76
+ writer.addClass(['ck-fake-bookmark-selection', 'ck-fake-bookmark-selection_collapsed'], markerElement);
77
+ return markerElement;
78
+ }
79
+ });
80
+ }
81
+ /**
82
+ * @inheritDoc
83
+ */
84
+ destroy() {
85
+ super.destroy();
86
+ // Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).
87
+ if (this.formView) {
88
+ this.formView.destroy();
89
+ }
90
+ if (this.actionsView) {
91
+ this.actionsView.destroy();
92
+ }
93
+ }
94
+ /**
95
+ * Creates views.
96
+ */
97
+ _createViews() {
98
+ this.actionsView = this._createActionsView();
99
+ this.formView = this._createFormView();
100
+ // Attach lifecycle actions to the the balloon.
101
+ this._enableUserBalloonInteractions();
102
+ }
103
+ /**
104
+ * Creates the {@link module:bookmark/ui/bookmarkactionsview~BookmarkActionsView} instance.
105
+ */
106
+ _createActionsView() {
107
+ const editor = this.editor;
108
+ const actionsView = new BookmarkActionsView(editor.locale);
109
+ const updateBookmarkCommand = editor.commands.get('updateBookmark');
110
+ const deleteCommand = editor.commands.get('delete');
111
+ actionsView.bind('id').to(updateBookmarkCommand, 'value');
112
+ actionsView.editButtonView.bind('isEnabled').to(updateBookmarkCommand);
113
+ actionsView.removeButtonView.bind('isEnabled').to(deleteCommand);
114
+ // Display edit form view after clicking on the "Edit" button.
115
+ this.listenTo(actionsView, 'edit', () => {
116
+ this._addFormView();
117
+ });
118
+ // Execute remove command after clicking on the "Remove" button.
119
+ this.listenTo(actionsView, 'remove', () => {
120
+ this._hideUI();
121
+ editor.execute('delete');
122
+ });
123
+ // Close the panel on esc key press when the **actions have focus**.
124
+ actionsView.keystrokes.set('Esc', (data, cancel) => {
125
+ this._hideUI();
126
+ cancel();
127
+ });
128
+ return actionsView;
129
+ }
130
+ /**
131
+ * Creates the {@link module:bookmark/ui/bookmarkformview~BookmarkFormView} instance.
132
+ */
133
+ _createFormView() {
134
+ const editor = this.editor;
135
+ const locale = editor.locale;
136
+ const insertBookmarkCommand = editor.commands.get('insertBookmark');
137
+ const updateBookmarkCommand = editor.commands.get('updateBookmark');
138
+ const commands = [insertBookmarkCommand, updateBookmarkCommand];
139
+ const formView = new (CssTransitionDisablerMixin(BookmarkFormView))(locale, getFormValidators(editor));
140
+ formView.idInputView.fieldView.bind('value').to(updateBookmarkCommand, 'value');
141
+ // Form elements should be read-only when corresponding commands are disabled.
142
+ formView.idInputView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
143
+ // Disable the "save" button if the command is disabled.
144
+ formView.buttonView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
145
+ // Execute link command after clicking the "Save" button.
146
+ this.listenTo(formView, 'submit', () => {
147
+ if (formView.isValid()) {
148
+ const value = formView.id;
149
+ if (this._getSelectedBookmarkElement()) {
150
+ editor.execute('updateBookmark', { bookmarkId: value });
151
+ }
152
+ else {
153
+ editor.execute('insertBookmark', { bookmarkId: value });
154
+ }
155
+ this._closeFormView();
156
+ }
157
+ });
158
+ // Update balloon position when form error changes.
159
+ this.listenTo(formView.idInputView, 'change:errorText', () => {
160
+ editor.ui.update();
161
+ });
162
+ // Close the panel on esc key press when the **form has focus**.
163
+ formView.keystrokes.set('Esc', (data, cancel) => {
164
+ this._closeFormView();
165
+ cancel();
166
+ });
167
+ return formView;
168
+ }
169
+ /**
170
+ * Creates a toolbar Bookmark button. Clicking this button will show
171
+ * a {@link #_balloon} attached to the selection.
172
+ */
173
+ _createToolbarBookmarkButton() {
174
+ const editor = this.editor;
175
+ editor.ui.componentFactory.add('bookmark', () => {
176
+ const buttonView = this._createButton(ButtonView);
177
+ buttonView.set({
178
+ tooltip: true
179
+ });
180
+ return buttonView;
181
+ });
182
+ editor.ui.componentFactory.add('menuBar:bookmark', () => {
183
+ return this._createButton(MenuBarMenuListItemButtonView);
184
+ });
185
+ }
186
+ /**
187
+ * Creates a button for `bookmark` command to use either in toolbar or in menu bar.
188
+ */
189
+ _createButton(ButtonClass) {
190
+ const editor = this.editor;
191
+ const locale = editor.locale;
192
+ const view = new ButtonClass(locale);
193
+ const insertCommand = editor.commands.get('insertBookmark');
194
+ const updateCommand = editor.commands.get('updateBookmark');
195
+ const t = locale.t;
196
+ view.set({
197
+ label: t('Bookmark'),
198
+ icon: icons.bookmark
199
+ });
200
+ // Execute the command.
201
+ this.listenTo(view, 'execute', () => this._showUI(true));
202
+ view.bind('isEnabled').toMany([insertCommand, updateCommand], 'isEnabled', (...areEnabled) => areEnabled.some(isEnabled => isEnabled));
203
+ view.bind('isOn').to(updateCommand, 'value', value => !!value);
204
+ return view;
205
+ }
206
+ /**
207
+ * Attaches actions that control whether the balloon panel containing the
208
+ * {@link #formView} should be displayed.
209
+ */
210
+ _enableBalloonActivators() {
211
+ const editor = this.editor;
212
+ const viewDocument = editor.editing.view.document;
213
+ // Handle click on view document and show panel when selection is placed inside the bookmark element.
214
+ // Keep panel open until selection will be inside the same bookmark element.
215
+ this.listenTo(viewDocument, 'click', () => {
216
+ const bookmark = this._getSelectedBookmarkElement();
217
+ if (bookmark) {
218
+ // Then show panel but keep focus inside editor editable.
219
+ this._showUI();
220
+ }
221
+ });
222
+ }
223
+ /**
224
+ * Attaches actions that control whether the balloon panel containing the
225
+ * {@link #formView} is visible or not.
226
+ */
227
+ _enableUserBalloonInteractions() {
228
+ // Focus the form if the balloon is visible and the Tab key has been pressed.
229
+ this.editor.keystrokes.set('Tab', (data, cancel) => {
230
+ if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {
231
+ this.actionsView.focus();
232
+ cancel();
233
+ }
234
+ }, {
235
+ // Use the high priority because the bookmark UI navigation is more important
236
+ // than other feature's actions, e.g. list indentation.
237
+ priority: 'high'
238
+ });
239
+ // Close the panel on the Esc key press when the editable has focus and the balloon is visible.
240
+ this.editor.keystrokes.set('Esc', (data, cancel) => {
241
+ if (this._isUIVisible) {
242
+ this._hideUI();
243
+ cancel();
244
+ }
245
+ });
246
+ // Close on click outside of balloon panel element.
247
+ clickOutsideHandler({
248
+ emitter: this.formView,
249
+ activator: () => this._isUIInPanel,
250
+ contextElements: () => [this._balloon.view.element],
251
+ callback: () => this._hideUI()
252
+ });
253
+ }
254
+ /**
255
+ * Updates the button label. If bookmark is selected label is set to 'Update' otherwise
256
+ * it is 'Insert'.
257
+ */
258
+ _updateFormButtonLabel(isBookmarkSelected) {
259
+ const t = this.editor.locale.t;
260
+ this.formView.buttonView.label = isBookmarkSelected ? t('Update') : t('Insert');
261
+ }
262
+ /**
263
+ * Adds the {@link #actionsView} to the {@link #_balloon}.
264
+ *
265
+ * @internal
266
+ */
267
+ _addActionsView() {
268
+ if (!this.actionsView) {
269
+ this._createViews();
270
+ }
271
+ if (this._areActionsInPanel) {
272
+ return;
273
+ }
274
+ this._balloon.add({
275
+ view: this.actionsView,
276
+ position: this._getBalloonPositionData()
277
+ });
278
+ }
279
+ /**
280
+ * Adds the {@link #formView} to the {@link #_balloon}.
281
+ */
282
+ _addFormView() {
283
+ if (!this.formView) {
284
+ this._createViews();
285
+ }
286
+ if (this._isFormInPanel) {
287
+ return;
288
+ }
289
+ const editor = this.editor;
290
+ const updateBookmarkCommand = editor.commands.get('updateBookmark');
291
+ this.formView.disableCssTransitions();
292
+ this.formView.resetFormStatus();
293
+ this._balloon.add({
294
+ view: this.formView,
295
+ position: this._getBalloonPositionData()
296
+ });
297
+ this.formView.idInputView.fieldView.value = updateBookmarkCommand.value || '';
298
+ // Select input when form view is currently visible.
299
+ if (this._balloon.visibleView === this.formView) {
300
+ this.formView.idInputView.fieldView.select();
301
+ }
302
+ this.formView.enableCssTransitions();
303
+ }
304
+ /**
305
+ * Closes the form view. Decides whether the balloon should be hidden completely.
306
+ */
307
+ _closeFormView() {
308
+ const updateBookmarkCommand = this.editor.commands.get('updateBookmark');
309
+ if (updateBookmarkCommand.value !== undefined) {
310
+ this._removeFormView();
311
+ }
312
+ else {
313
+ this._hideUI();
314
+ }
315
+ }
316
+ /**
317
+ * Removes the {@link #formView} from the {@link #_balloon}.
318
+ */
319
+ _removeFormView() {
320
+ if (this._isFormInPanel) {
321
+ // Blur the input element before removing it from DOM to prevent issues in some browsers.
322
+ // See https://github.com/ckeditor/ckeditor5/issues/1501.
323
+ this.formView.buttonView.focus();
324
+ // Reset the ID field to update the state of the submit button.
325
+ this.formView.idInputView.fieldView.reset();
326
+ this._balloon.remove(this.formView);
327
+ // Because the form has an input which has focus, the focus must be brought back
328
+ // to the editor. Otherwise, it would be lost.
329
+ this.editor.editing.view.focus();
330
+ this._hideFakeVisualSelection();
331
+ }
332
+ }
333
+ /**
334
+ * Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.
335
+ */
336
+ _showUI(forceVisible = false) {
337
+ if (!this.formView) {
338
+ this._createViews();
339
+ }
340
+ // When there's no bookmark under the selection, go straight to the editing UI.
341
+ if (!this._getSelectedBookmarkElement()) {
342
+ // Show visual selection on a text without a bookmark when the contextual balloon is displayed.
343
+ this._showFakeVisualSelection();
344
+ this._addActionsView();
345
+ // Be sure panel with bookmark is visible.
346
+ if (forceVisible) {
347
+ this._balloon.showStack('main');
348
+ }
349
+ this._addFormView();
350
+ }
351
+ // If there's a bookmark under the selection...
352
+ else {
353
+ // Go to the editing UI if actions are already visible.
354
+ if (this._areActionsVisible) {
355
+ this._addFormView();
356
+ }
357
+ // Otherwise display just the actions UI.
358
+ else {
359
+ this._addActionsView();
360
+ }
361
+ // Be sure panel with bookmark is visible.
362
+ if (forceVisible) {
363
+ this._balloon.showStack('main');
364
+ }
365
+ }
366
+ // Begin responding to ui#update once the UI is added.
367
+ this._startUpdatingUI();
368
+ }
369
+ /**
370
+ * Removes the {@link #formView} from the {@link #_balloon}.
371
+ *
372
+ * See {@link #_addFormView}, {@link #_addActionsView}.
373
+ */
374
+ _hideUI() {
375
+ if (!this._isUIInPanel) {
376
+ return;
377
+ }
378
+ const editor = this.editor;
379
+ this.stopListening(editor.ui, 'update');
380
+ this.stopListening(this._balloon, 'change:visibleView');
381
+ // Make sure the focus always gets back to the editable _before_ removing the focused form view.
382
+ // Doing otherwise causes issues in some browsers. See https://github.com/ckeditor/ckeditor5-link/issues/193.
383
+ editor.editing.view.focus();
384
+ // Remove form first because it's on top of the stack.
385
+ this._removeFormView();
386
+ // Then remove the actions view because it's beneath the form.
387
+ this._balloon.remove(this.actionsView);
388
+ this._hideFakeVisualSelection();
389
+ }
390
+ /**
391
+ * Makes the UI react to the {@link module:ui/editorui/editorui~EditorUI#event:update} event to
392
+ * reposition itself when the editor UI should be refreshed.
393
+ *
394
+ * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.
395
+ */
396
+ _startUpdatingUI() {
397
+ const editor = this.editor;
398
+ const viewDocument = editor.editing.view.document;
399
+ let prevSelectedBookmark = this._getSelectedBookmarkElement();
400
+ let prevSelectionParent = getSelectionParent();
401
+ this._updateFormButtonLabel(!!prevSelectedBookmark);
402
+ const update = () => {
403
+ const selectedBookmark = this._getSelectedBookmarkElement();
404
+ const selectionParent = getSelectionParent();
405
+ // Hide the panel if:
406
+ //
407
+ // * the selection went out of the EXISTING bookmark element. E.g. user moved the caret out
408
+ // of the bookmark,
409
+ // * the selection went to a different parent when creating a NEW bookmark. E.g. someone
410
+ // else modified the document.
411
+ // * the selection has expanded (e.g. displaying bookmark actions then pressing SHIFT+Right arrow).
412
+ //
413
+ if ((prevSelectedBookmark && !selectedBookmark) ||
414
+ (!prevSelectedBookmark && selectionParent !== prevSelectionParent)) {
415
+ this._hideUI();
416
+ }
417
+ // Update the position of the panel when:
418
+ // * bookmark panel is in the visible stack
419
+ // * the selection remains on the original bookmark element,
420
+ // * there was no bookmark element in the first place, i.e. creating a new bookmark
421
+ else if (this._isUIVisible) {
422
+ // If still in a bookmark element, simply update the position of the balloon.
423
+ // If there was no bookmark (e.g. inserting one), the balloon must be moved
424
+ // to the new position in the editing view (a new native DOM range).
425
+ this._balloon.updatePosition(this._getBalloonPositionData());
426
+ }
427
+ this._updateFormButtonLabel(!!prevSelectedBookmark);
428
+ prevSelectedBookmark = selectedBookmark;
429
+ prevSelectionParent = selectionParent;
430
+ };
431
+ function getSelectionParent() {
432
+ return viewDocument.selection.focus.getAncestors()
433
+ .reverse()
434
+ .find((node) => node.is('element'));
435
+ }
436
+ this.listenTo(editor.ui, 'update', update);
437
+ this.listenTo(this._balloon, 'change:visibleView', update);
438
+ }
439
+ /**
440
+ * Returns `true` when {@link #formView} is in the {@link #_balloon}.
441
+ */
442
+ get _isFormInPanel() {
443
+ return !!this.formView && this._balloon.hasView(this.formView);
444
+ }
445
+ /**
446
+ * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.
447
+ */
448
+ get _areActionsInPanel() {
449
+ return !!this.actionsView && this._balloon.hasView(this.actionsView);
450
+ }
451
+ /**
452
+ * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
453
+ * currently visible.
454
+ */
455
+ get _areActionsVisible() {
456
+ return !!this.actionsView && this._balloon.visibleView === this.actionsView;
457
+ }
458
+ /**
459
+ * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
460
+ */
461
+ get _isUIInPanel() {
462
+ return this._isFormInPanel || this._areActionsInPanel;
463
+ }
464
+ /**
465
+ * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
466
+ * currently visible.
467
+ */
468
+ get _isUIVisible() {
469
+ const visibleView = this._balloon.visibleView;
470
+ return !!this.formView && visibleView == this.formView || this._areActionsVisible;
471
+ }
472
+ /**
473
+ * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached
474
+ * to the target element or selection.
475
+ */
476
+ _getBalloonPositionData() {
477
+ const view = this.editor.editing.view;
478
+ const model = this.editor.model;
479
+ let target;
480
+ const bookmarkElement = this._getSelectedBookmarkElement();
481
+ if (model.markers.has(VISUAL_SELECTION_MARKER_NAME)) {
482
+ // There are cases when we highlight selection using a marker (#7705, #4721).
483
+ const markerViewElements = Array.from(this.editor.editing.mapper.markerNameToElements(VISUAL_SELECTION_MARKER_NAME));
484
+ const newRange = view.createRange(view.createPositionBefore(markerViewElements[0]), view.createPositionAfter(markerViewElements[markerViewElements.length - 1]));
485
+ target = view.domConverter.viewRangeToDom(newRange);
486
+ }
487
+ else if (bookmarkElement) {
488
+ target = () => {
489
+ const mapper = this.editor.editing.mapper;
490
+ const domConverter = view.domConverter;
491
+ const viewElement = mapper.toViewElement(bookmarkElement);
492
+ return domConverter.mapViewToDom(viewElement);
493
+ };
494
+ }
495
+ return target && { target };
496
+ }
497
+ /**
498
+ * Returns the bookmark {@link module:engine/view/attributeelement~AttributeElement} under
499
+ * the {@link module:engine/view/document~Document editing view's} selection or `null`
500
+ * if there is none.
501
+ */
502
+ _getSelectedBookmarkElement() {
503
+ const selection = this.editor.model.document.selection;
504
+ const element = selection.getSelectedElement();
505
+ if (element && element.is('element', 'bookmark')) {
506
+ return element;
507
+ }
508
+ return null;
509
+ }
510
+ /**
511
+ * Displays a fake visual selection when the contextual balloon is displayed.
512
+ *
513
+ * This adds a 'bookmark-ui' marker into the document that is rendered as a highlight on selected text fragment.
514
+ */
515
+ _showFakeVisualSelection() {
516
+ const model = this.editor.model;
517
+ model.change(writer => {
518
+ const range = model.document.selection.getFirstRange();
519
+ if (model.markers.has(VISUAL_SELECTION_MARKER_NAME)) {
520
+ writer.updateMarker(VISUAL_SELECTION_MARKER_NAME, { range });
521
+ }
522
+ else {
523
+ if (range.start.isAtEnd) {
524
+ const startPosition = range.start.getLastMatchingPosition(({ item }) => !model.schema.isContent(item), { boundaries: range });
525
+ writer.addMarker(VISUAL_SELECTION_MARKER_NAME, {
526
+ usingOperation: false,
527
+ affectsData: false,
528
+ range: writer.createRange(startPosition, range.end)
529
+ });
530
+ }
531
+ else {
532
+ writer.addMarker(VISUAL_SELECTION_MARKER_NAME, {
533
+ usingOperation: false,
534
+ affectsData: false,
535
+ range
536
+ });
537
+ }
538
+ }
539
+ });
540
+ }
541
+ /**
542
+ * Hides the fake visual selection created in {@link #_showFakeVisualSelection}.
543
+ */
544
+ _hideFakeVisualSelection() {
545
+ const model = this.editor.model;
546
+ if (model.markers.has(VISUAL_SELECTION_MARKER_NAME)) {
547
+ model.change(writer => {
548
+ writer.removeMarker(VISUAL_SELECTION_MARKER_NAME);
549
+ });
550
+ }
551
+ }
552
+ }
553
+ /**
554
+ * Returns bookmark form validation callbacks.
555
+ */
556
+ function getFormValidators(editor) {
557
+ const { t } = editor;
558
+ const bookmarkEditing = editor.plugins.get(BookmarkEditing);
559
+ return [
560
+ form => {
561
+ if (!form.id) {
562
+ return t('Bookmark must not be empty.');
563
+ }
564
+ },
565
+ form => {
566
+ if (form.id && /\s/.test(form.id)) {
567
+ return t('Bookmark name cannot contain space characters.');
568
+ }
569
+ },
570
+ form => {
571
+ const selectedElement = editor.model.document.selection.getSelectedElement();
572
+ const existingBookmarkForId = bookmarkEditing.getElementForBookmarkId(form.id);
573
+ // Accept change of bookmark ID if no real change is happening (edit -> submit, without changes).
574
+ if (selectedElement === existingBookmarkForId) {
575
+ return;
576
+ }
577
+ if (existingBookmarkForId) {
578
+ return t('Bookmark name already exists.');
579
+ }
580
+ }
581
+ ];
582
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module bookmark
7
+ */
8
+ export { default as Bookmark } from './bookmark.js';
9
+ export { default as BookmarkEditing } from './bookmarkediting.js';
10
+ export { default as BookmarkUI } from './bookmarkui.js';
11
+ export { default as InsertBookmarkCommand } from './insertbookmarkcommand.js';
12
+ export { default as UpdateBookmarkCommand } from './updatebookmarkcommand.js';
13
+ export type { BookmarkConfig } from './bookmarkconfig.js';
14
+ import './augmentation.js';
package/src/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module bookmark
7
+ */
8
+ export { default as Bookmark } from './bookmark.js';
9
+ export { default as BookmarkEditing } from './bookmarkediting.js';
10
+ export { default as BookmarkUI } from './bookmarkui.js';
11
+ export { default as InsertBookmarkCommand } from './insertbookmarkcommand.js';
12
+ export { default as UpdateBookmarkCommand } from './updatebookmarkcommand.js';
13
+ import './augmentation.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import { Command } from 'ckeditor5/src/core.js';
6
+ /**
7
+ * The insert bookmark command.
8
+ *
9
+ * The command is registered by {@link module:bookmark/bookmarkediting~BookmarkEditing} as `'insertBookmark'`.
10
+ *
11
+ * To insert a bookmark element at place where is the current collapsed selection or where is the beginning of document selection,
12
+ * execute the command passing the bookmark id as a parameter:
13
+ *
14
+ * ```ts
15
+ * editor.execute( 'insertBookmark', { bookmarkId: 'foo_bar' } );
16
+ * ```
17
+ */
18
+ export default class InsertBookmarkCommand extends Command {
19
+ /**
20
+ * @inheritDoc
21
+ */
22
+ refresh(): void;
23
+ /**
24
+ * Executes the command.
25
+ *
26
+ * @fires execute
27
+ * @param options Command options.
28
+ * @param options.bookmarkId The value of the `bookmarkId` attribute.
29
+ */
30
+ execute(options: {
31
+ bookmarkId: string;
32
+ }): void;
33
+ /**
34
+ * Returns the position where the bookmark can be inserted. And if it is not possible to insert a bookmark,
35
+ * check if it is possible to insert a paragraph.
36
+ */
37
+ private _getPositionToInsertBookmark;
38
+ }