react-cheminfo 0.23.0 → 0.25.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 (264) hide show
  1. package/README.md +39 -26
  2. package/lib/chrome/ui/HeaderToggle.d.ts +52 -0
  3. package/lib/chrome/ui/HeaderToggle.d.ts.map +1 -0
  4. package/lib/chrome/ui/HeaderToggle.js +31 -0
  5. package/lib/chrome/ui/HeaderToggle.js.map +1 -0
  6. package/lib/chrome/ui/index.d.ts +2 -0
  7. package/lib/chrome/ui/index.d.ts.map +1 -1
  8. package/lib/chrome/ui/index.js +1 -0
  9. package/lib/chrome/ui/index.js.map +1 -1
  10. package/lib/citation/core/gfn2Paper.d.ts +10 -0
  11. package/lib/citation/core/gfn2Paper.d.ts.map +1 -0
  12. package/lib/citation/core/gfn2Paper.js +28 -0
  13. package/lib/citation/core/gfn2Paper.js.map +1 -0
  14. package/lib/citation/core/index.d.ts +1 -0
  15. package/lib/citation/core/index.d.ts.map +1 -1
  16. package/lib/citation/core/index.js +1 -0
  17. package/lib/citation/core/index.js.map +1 -1
  18. package/lib/clipboard/ui/ClickToCopy.d.ts +8 -7
  19. package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
  20. package/lib/clipboard/ui/ClickToCopy.js +3 -3
  21. package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
  22. package/lib/conformers.d.ts +27 -0
  23. package/lib/conformers.d.ts.map +1 -0
  24. package/lib/conformers.js +19 -0
  25. package/lib/conformers.js.map +1 -0
  26. package/lib/core.d.ts +1 -0
  27. package/lib/core.d.ts.map +1 -1
  28. package/lib/core.js +1 -0
  29. package/lib/core.js.map +1 -1
  30. package/lib/credits/core/credits.d.ts +12 -0
  31. package/lib/credits/core/credits.d.ts.map +1 -1
  32. package/lib/credits/core/credits.js +14 -0
  33. package/lib/credits/core/credits.js.map +1 -1
  34. package/lib/ecosystem/core/index.d.ts +1 -1
  35. package/lib/ecosystem/core/index.d.ts.map +1 -1
  36. package/lib/ecosystem/core/index.js.map +1 -1
  37. package/lib/ecosystem/core/sites.d.ts +11 -1
  38. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  39. package/lib/ecosystem/core/sites.js +11 -4
  40. package/lib/ecosystem/core/sites.js.map +1 -1
  41. package/lib/ecosystem/ui/EcosystemLinks.d.ts.map +1 -1
  42. package/lib/ecosystem/ui/EcosystemLinks.js +3 -1
  43. package/lib/ecosystem/ui/EcosystemLinks.js.map +1 -1
  44. package/lib/ecosystem/ui/SiteTile.d.ts.map +1 -1
  45. package/lib/ecosystem/ui/SiteTile.js +3 -1
  46. package/lib/ecosystem/ui/SiteTile.js.map +1 -1
  47. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  48. package/lib/ecosystem/ui/glyphs.js +6 -5
  49. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  50. package/lib/format/core/index.d.ts +1 -1
  51. package/lib/format/core/index.d.ts.map +1 -1
  52. package/lib/format/core/index.js +1 -1
  53. package/lib/format/core/index.js.map +1 -1
  54. package/lib/format/core/words.d.ts +9 -0
  55. package/lib/format/core/words.d.ts.map +1 -1
  56. package/lib/format/core/words.js +16 -0
  57. package/lib/format/core/words.js.map +1 -1
  58. package/lib/language/core/index.d.ts +3 -0
  59. package/lib/language/core/index.d.ts.map +1 -0
  60. package/lib/language/core/index.js +3 -0
  61. package/lib/language/core/index.js.map +1 -0
  62. package/lib/language/core/languageName.d.ts +8 -0
  63. package/lib/language/core/languageName.d.ts.map +1 -0
  64. package/lib/language/core/languageName.js +16 -0
  65. package/lib/language/core/languageName.js.map +1 -0
  66. package/lib/language/core/languageParam.d.ts +35 -0
  67. package/lib/language/core/languageParam.d.ts.map +1 -0
  68. package/lib/language/core/languageParam.js +67 -0
  69. package/lib/language/core/languageParam.js.map +1 -0
  70. package/lib/language/ui/SiteLanguage.d.ts +20 -0
  71. package/lib/language/ui/SiteLanguage.d.ts.map +1 -0
  72. package/lib/language/ui/SiteLanguage.js +14 -0
  73. package/lib/language/ui/SiteLanguage.js.map +1 -0
  74. package/lib/language/ui/index.d.ts +4 -0
  75. package/lib/language/ui/index.d.ts.map +1 -0
  76. package/lib/language/ui/index.js +3 -0
  77. package/lib/language/ui/index.js.map +1 -0
  78. package/lib/language/ui/siteLanguageContext.d.ts +12 -0
  79. package/lib/language/ui/siteLanguageContext.d.ts.map +1 -0
  80. package/lib/language/ui/siteLanguageContext.js +19 -0
  81. package/lib/language/ui/siteLanguageContext.js.map +1 -0
  82. package/lib/orbital/core/atomicOrbitals.d.ts +9 -1
  83. package/lib/orbital/core/atomicOrbitals.d.ts.map +1 -1
  84. package/lib/orbital/core/atomicOrbitals.js +7 -0
  85. package/lib/orbital/core/atomicOrbitals.js.map +1 -1
  86. package/lib/orbital/core/hydrogenic.d.ts +2 -1
  87. package/lib/orbital/core/hydrogenic.d.ts.map +1 -1
  88. package/lib/orbital/core/hydrogenic.js +2 -1
  89. package/lib/orbital/core/hydrogenic.js.map +1 -1
  90. package/lib/orbital/core/index.d.ts +1 -0
  91. package/lib/orbital/core/index.d.ts.map +1 -1
  92. package/lib/orbital/core/index.js +1 -0
  93. package/lib/orbital/core/index.js.map +1 -1
  94. package/lib/orbital/core/slaterEnergy.d.ts +35 -0
  95. package/lib/orbital/core/slaterEnergy.d.ts.map +1 -0
  96. package/lib/orbital/core/slaterEnergy.js +66 -0
  97. package/lib/orbital/core/slaterEnergy.js.map +1 -0
  98. package/lib/shared/ui/MenuButton.d.ts +3 -2
  99. package/lib/shared/ui/MenuButton.d.ts.map +1 -1
  100. package/lib/shared/ui/MenuButton.js +1 -1
  101. package/lib/shared/ui/MenuButton.js.map +1 -1
  102. package/lib/structure/core/conformerMinimise.d.ts +36 -0
  103. package/lib/structure/core/conformerMinimise.d.ts.map +1 -0
  104. package/lib/structure/core/conformerMinimise.js +81 -0
  105. package/lib/structure/core/conformerMinimise.js.map +1 -0
  106. package/lib/structure/core/conformerMinimum.d.ts +62 -0
  107. package/lib/structure/core/conformerMinimum.d.ts.map +1 -0
  108. package/lib/structure/core/conformerMinimum.js +90 -0
  109. package/lib/structure/core/conformerMinimum.js.map +1 -0
  110. package/lib/structure/core/conformerOptions.d.ts +62 -0
  111. package/lib/structure/core/conformerOptions.d.ts.map +1 -0
  112. package/lib/structure/core/conformerOptions.js +83 -0
  113. package/lib/structure/core/conformerOptions.js.map +1 -0
  114. package/lib/structure/core/conformerRefine.d.ts +104 -0
  115. package/lib/structure/core/conformerRefine.d.ts.map +1 -0
  116. package/lib/structure/core/conformerRefine.js +130 -0
  117. package/lib/structure/core/conformerRefine.js.map +1 -0
  118. package/lib/structure/core/conformerRefineRank.d.ts +36 -0
  119. package/lib/structure/core/conformerRefineRank.d.ts.map +1 -0
  120. package/lib/structure/core/conformerRefineRank.js +69 -0
  121. package/lib/structure/core/conformerRefineRank.js.map +1 -0
  122. package/lib/structure/core/conformerSession.d.ts +50 -0
  123. package/lib/structure/core/conformerSession.d.ts.map +1 -0
  124. package/lib/structure/core/conformerSession.js +88 -0
  125. package/lib/structure/core/conformerSession.js.map +1 -0
  126. package/lib/structure/core/conformerShape.d.ts +36 -0
  127. package/lib/structure/core/conformerShape.d.ts.map +1 -0
  128. package/lib/structure/core/conformerShape.js +150 -0
  129. package/lib/structure/core/conformerShape.js.map +1 -0
  130. package/lib/structure/core/conformers.d.ts +107 -0
  131. package/lib/structure/core/conformers.d.ts.map +1 -0
  132. package/lib/structure/core/conformers.js +149 -0
  133. package/lib/structure/core/conformers.js.map +1 -0
  134. package/lib/structure/core/geometryRelaxer.d.ts +66 -0
  135. package/lib/structure/core/geometryRelaxer.d.ts.map +1 -0
  136. package/lib/structure/core/geometryRelaxer.js +2 -0
  137. package/lib/structure/core/geometryRelaxer.js.map +1 -0
  138. package/lib/structure/core/index.d.ts +4 -0
  139. package/lib/structure/core/index.d.ts.map +1 -1
  140. package/lib/structure/core/index.js +2 -0
  141. package/lib/structure/core/index.js.map +1 -1
  142. package/lib/structure/core/moleculeCoordinates.d.ts +31 -0
  143. package/lib/structure/core/moleculeCoordinates.d.ts.map +1 -0
  144. package/lib/structure/core/moleculeCoordinates.js +80 -0
  145. package/lib/structure/core/moleculeCoordinates.js.map +1 -0
  146. package/lib/structure/core/molfileExport.d.ts +42 -0
  147. package/lib/structure/core/molfileExport.d.ts.map +1 -0
  148. package/lib/structure/core/molfileExport.js +47 -0
  149. package/lib/structure/core/molfileExport.js.map +1 -0
  150. package/lib/structure/core/oclResources.d.ts +12 -0
  151. package/lib/structure/core/oclResources.d.ts.map +1 -0
  152. package/lib/structure/core/oclResources.js +35 -0
  153. package/lib/structure/core/oclResources.js.map +1 -0
  154. package/lib/translate/core/catalog.d.ts +61 -0
  155. package/lib/translate/core/catalog.d.ts.map +1 -0
  156. package/lib/translate/core/catalog.js +49 -0
  157. package/lib/translate/core/catalog.js.map +1 -0
  158. package/lib/translate/core/checkTranslation.d.ts +32 -0
  159. package/lib/translate/core/checkTranslation.d.ts.map +1 -0
  160. package/lib/translate/core/checkTranslation.js +98 -0
  161. package/lib/translate/core/checkTranslation.js.map +1 -0
  162. package/lib/translate/core/contribution.d.ts +88 -0
  163. package/lib/translate/core/contribution.d.ts.map +1 -0
  164. package/lib/translate/core/contribution.js +14 -0
  165. package/lib/translate/core/contribution.js.map +1 -0
  166. package/lib/translate/core/index.d.ts +19 -0
  167. package/lib/translate/core/index.d.ts.map +1 -0
  168. package/lib/translate/core/index.js +15 -0
  169. package/lib/translate/core/index.js.map +1 -0
  170. package/lib/translate/core/marker.d.ts +45 -0
  171. package/lib/translate/core/marker.d.ts.map +1 -0
  172. package/lib/translate/core/marker.js +79 -0
  173. package/lib/translate/core/marker.js.map +1 -0
  174. package/lib/translate/core/mergeMessages.d.ts +35 -0
  175. package/lib/translate/core/mergeMessages.d.ts.map +1 -0
  176. package/lib/translate/core/mergeMessages.js +69 -0
  177. package/lib/translate/core/mergeMessages.js.map +1 -0
  178. package/lib/translate/core/session.d.ts +102 -0
  179. package/lib/translate/core/session.d.ts.map +1 -0
  180. package/lib/translate/core/session.js +162 -0
  181. package/lib/translate/core/session.js.map +1 -0
  182. package/lib/translate/core/start.d.ts +103 -0
  183. package/lib/translate/core/start.d.ts.map +1 -0
  184. package/lib/translate/core/start.js +92 -0
  185. package/lib/translate/core/start.js.map +1 -0
  186. package/lib/translate/core/suggestions.d.ts +77 -0
  187. package/lib/translate/core/suggestions.d.ts.map +1 -0
  188. package/lib/translate/core/suggestions.js +143 -0
  189. package/lib/translate/core/suggestions.js.map +1 -0
  190. package/lib/translate/core/tables.d.ts +100 -0
  191. package/lib/translate/core/tables.d.ts.map +1 -0
  192. package/lib/translate/core/tables.js +51 -0
  193. package/lib/translate/core/tables.js.map +1 -0
  194. package/lib/translate.d.ts +2 -0
  195. package/lib/translate.d.ts.map +1 -0
  196. package/lib/translate.js +6 -0
  197. package/lib/translate.js.map +1 -0
  198. package/lib/ui.d.ts +1 -0
  199. package/lib/ui.d.ts.map +1 -1
  200. package/lib/ui.js +1 -0
  201. package/lib/ui.js.map +1 -1
  202. package/lib/xtb/core/xtbRelaxer.d.ts +61 -0
  203. package/lib/xtb/core/xtbRelaxer.d.ts.map +1 -0
  204. package/lib/xtb/core/xtbRelaxer.js +108 -0
  205. package/lib/xtb/core/xtbRelaxer.js.map +1 -0
  206. package/lib/xtb.d.ts +11 -0
  207. package/lib/xtb.d.ts.map +1 -0
  208. package/lib/xtb.js +10 -0
  209. package/lib/xtb.js.map +1 -0
  210. package/package.json +18 -11
  211. package/src/chrome/ui/HeaderToggle.tsx +100 -0
  212. package/src/chrome/ui/index.ts +2 -0
  213. package/src/citation/core/gfn2Paper.ts +32 -0
  214. package/src/citation/core/index.ts +1 -0
  215. package/src/clipboard/ui/ClickToCopy.tsx +8 -7
  216. package/src/conformers.ts +87 -0
  217. package/src/core.ts +1 -0
  218. package/src/credits/core/credits.ts +16 -0
  219. package/src/ecosystem/core/index.ts +1 -0
  220. package/src/ecosystem/core/sites.ts +24 -4
  221. package/src/ecosystem/ui/EcosystemLinks.tsx +3 -1
  222. package/src/ecosystem/ui/SiteTile.tsx +3 -1
  223. package/src/ecosystem/ui/glyphs.tsx +16 -22
  224. package/src/format/core/index.ts +1 -1
  225. package/src/format/core/words.ts +19 -0
  226. package/src/language/core/index.ts +7 -0
  227. package/src/language/core/languageName.ts +16 -0
  228. package/src/language/core/languageParam.ts +70 -0
  229. package/src/language/ui/SiteLanguage.tsx +26 -0
  230. package/src/language/ui/index.ts +3 -0
  231. package/src/language/ui/siteLanguageContext.ts +20 -0
  232. package/src/orbital/core/atomicOrbitals.ts +17 -1
  233. package/src/orbital/core/hydrogenic.ts +2 -1
  234. package/src/orbital/core/index.ts +1 -0
  235. package/src/orbital/core/slaterEnergy.ts +83 -0
  236. package/src/shared/ui/MenuButton.tsx +4 -3
  237. package/src/structure/core/conformerMinimise.ts +99 -0
  238. package/src/structure/core/conformerMinimum.ts +125 -0
  239. package/src/structure/core/conformerOptions.ts +125 -0
  240. package/src/structure/core/conformerRefine.ts +234 -0
  241. package/src/structure/core/conformerRefineRank.ts +89 -0
  242. package/src/structure/core/conformerSession.ts +123 -0
  243. package/src/structure/core/conformerShape.ts +181 -0
  244. package/src/structure/core/conformers.ts +282 -0
  245. package/src/structure/core/geometryRelaxer.ts +71 -0
  246. package/src/structure/core/index.ts +13 -0
  247. package/src/structure/core/moleculeCoordinates.ts +93 -0
  248. package/src/structure/core/molfileExport.ts +62 -0
  249. package/src/structure/core/oclResources.ts +41 -0
  250. package/src/translate/core/catalog.ts +83 -0
  251. package/src/translate/core/checkTranslation.ts +128 -0
  252. package/src/translate/core/contribution.ts +99 -0
  253. package/src/translate/core/index.ts +72 -0
  254. package/src/translate/core/marker.ts +85 -0
  255. package/src/translate/core/mergeMessages.ts +74 -0
  256. package/src/translate/core/session.ts +250 -0
  257. package/src/translate/core/start.ts +183 -0
  258. package/src/translate/core/suggestions.ts +211 -0
  259. package/src/translate/core/tables.ts +120 -0
  260. package/src/translate.ts +5 -0
  261. package/src/ui.ts +1 -0
  262. package/src/xtb/core/xtbRelaxer.ts +160 -0
  263. package/src/xtb.ts +16 -0
  264. package/styles/chrome.css +61 -30
@@ -0,0 +1,162 @@
1
+ import { IntlMessageFormat } from 'intl-messageformat';
2
+ import { SOURCE_LOCALE, ownMessage } from "./catalog.js";
3
+ import { checkTranslation } from "./checkTranslation.js";
4
+ import { markText } from "./marker.js";
5
+ /** The version of the page ↔ overlay protocol this session speaks. */
6
+ export const BRIDGE_PROTOCOL = 2;
7
+ /** Where a page in translate mode exposes its session to the overlay. */
8
+ export const BRIDGE_GLOBAL = '__cheminfoTranslate';
9
+ /**
10
+ * Formats the messages of a page, and in translate mode lets the overlay edit
11
+ * them live: a draft replaces the published message as soon as it can be
12
+ * formatted, and a draft that cannot is ignored rather than breaking the page.
13
+ */
14
+ export class TranslateSession {
15
+ protocol = BRIDGE_PROTOCOL;
16
+ locale;
17
+ #marked;
18
+ #catalogs = new Map();
19
+ #ids = new Map();
20
+ #refs = [];
21
+ #listeners = new Set();
22
+ #formatters = new Map();
23
+ #checked = new Map();
24
+ #tables;
25
+ #version = 0;
26
+ constructor(options) {
27
+ const { locale, catalogs, translations = {}, marked = false, tables = [], } = options;
28
+ this.locale = locale;
29
+ this.#marked = marked;
30
+ this.#tables = tables;
31
+ for (const source of catalogs) {
32
+ this.#catalogs.set(source.id, {
33
+ source,
34
+ translation: translations[source.id] ?? {},
35
+ drafts: new Map(),
36
+ });
37
+ }
38
+ }
39
+ /**
40
+ * Increases on every draft change, for a view that re-renders on it.
41
+ * @returns The current version.
42
+ */
43
+ get version() {
44
+ return this.#version;
45
+ }
46
+ /**
47
+ * Format one message: the draft, else the published translation, else the
48
+ * English message — the first that passes its check against the English
49
+ * one and formats. A draft that drops a placeholder formats without error,
50
+ * so the check, not the formatting, is what keeps it off the page.
51
+ * @param catalogId - The catalog the message belongs to.
52
+ * @param key - The key of the message.
53
+ * @param values - What the placeholders are filled with.
54
+ * @returns The text to show; the key itself when no catalog has it.
55
+ */
56
+ format(catalogId, key, values) {
57
+ const catalog = this.#catalogs.get(catalogId);
58
+ if (catalog === undefined)
59
+ return key;
60
+ const source = ownMessage(catalog.source.messages, key);
61
+ if (source === undefined)
62
+ return key;
63
+ const draft = this.#usable(source, catalog.drafts.get(key));
64
+ const translation = this.#usable(source, ownMessage(catalog.translation, key));
65
+ const text = this.#tryFormat(draft, this.locale, values) ??
66
+ this.#tryFormat(translation, this.locale, values) ??
67
+ this.#tryFormat(source, SOURCE_LOCALE, values) ??
68
+ source;
69
+ return this.#marked ? markText(text, this.#idOf(catalogId, key)) : text;
70
+ }
71
+ catalogs() {
72
+ const snapshots = [];
73
+ for (const { source, translation, drafts } of this.#catalogs.values()) {
74
+ snapshots.push({
75
+ ...source,
76
+ translation,
77
+ drafts: Object.fromEntries(drafts),
78
+ });
79
+ }
80
+ return snapshots;
81
+ }
82
+ /**
83
+ * The tables whose rows a translator may write.
84
+ * @returns One entry per table the page declared.
85
+ */
86
+ tables() {
87
+ return [...this.#tables];
88
+ }
89
+ resolveMarker(id) {
90
+ return this.#refs[id];
91
+ }
92
+ setDraft(ref, message) {
93
+ const catalog = this.#catalogs.get(ref.catalogId);
94
+ if (catalog === undefined)
95
+ return;
96
+ if (ownMessage(catalog.source.messages, ref.key) === undefined)
97
+ return;
98
+ if (catalog.drafts.get(ref.key) === message)
99
+ return;
100
+ if (message === undefined) {
101
+ catalog.drafts.delete(ref.key);
102
+ }
103
+ else {
104
+ catalog.drafts.set(ref.key, message);
105
+ }
106
+ this.#version++;
107
+ for (const listener of this.#listeners)
108
+ listener();
109
+ }
110
+ subscribe(listener) {
111
+ this.#listeners.add(listener);
112
+ return () => {
113
+ this.#listeners.delete(listener);
114
+ };
115
+ }
116
+ #idOf(catalogId, key) {
117
+ const name = `${catalogId}\n${key}`;
118
+ let id = this.#ids.get(name);
119
+ if (id === undefined) {
120
+ id = this.#refs.length;
121
+ this.#refs.push({ catalogId, key });
122
+ this.#ids.set(name, id);
123
+ }
124
+ return id;
125
+ }
126
+ #usable(source, message) {
127
+ if (message === undefined)
128
+ return undefined;
129
+ const name = JSON.stringify([source, message]);
130
+ let usable = this.#checked.get(name);
131
+ if (usable === undefined) {
132
+ usable = checkTranslation(source, message).length === 0;
133
+ this.#checked.set(name, usable);
134
+ }
135
+ return usable ? message : undefined;
136
+ }
137
+ #tryFormat(message, locale, values) {
138
+ if (message === undefined)
139
+ return undefined;
140
+ const name = `${locale}\n${message}`;
141
+ let formatter = this.#formatters.get(name);
142
+ if (formatter === undefined) {
143
+ try {
144
+ formatter = new IntlMessageFormat(message, locale);
145
+ }
146
+ catch {
147
+ formatter = null;
148
+ }
149
+ this.#formatters.set(name, formatter);
150
+ }
151
+ if (formatter === null)
152
+ return undefined;
153
+ try {
154
+ const output = formatter.format(values);
155
+ return Array.isArray(output) ? output.join('') : String(output);
156
+ }
157
+ catch {
158
+ return undefined;
159
+ }
160
+ }
161
+ }
162
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/translate/core/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Turning a page into a translatable one.
3
+ *
4
+ * A site opened with `?translate=<locale>` formats every message with its
5
+ * invisible marker, hands its session to the overlay as
6
+ * `window.__cheminfoTranslate`, and loads that overlay from
7
+ * translate.cheminfo.org. Nothing of this is paid for by an ordinary visit:
8
+ * the site imports this module only once it has seen the parameter.
9
+ */
10
+ import type { CatalogSource, Messages } from './catalog.ts';
11
+ import { TranslateSession } from './session.ts';
12
+ import type { TranslatableTable } from './tables.ts';
13
+ /** The query parameter that opens a page in translate mode. */
14
+ export declare const TRANSLATE_PARAM = "translate";
15
+ /** Where the overlay is served from unless a site says otherwise. */
16
+ export declare const TRANSLATE_ORIGIN = "https://translate.cheminfo.org";
17
+ /**
18
+ * The locale a page is being translated into, from its address:
19
+ * `?translate=fr` opens the overlay for French.
20
+ * @param search - The query string, e.g. `location.search`.
21
+ * @returns The locale, or `undefined` when the page is not in translate mode,
22
+ * or names English, or names something that is not a language at all.
23
+ */
24
+ export declare function readTranslateLocale(search: string): string | undefined;
25
+ /** How a page enters translate mode. */
26
+ export interface StartTranslatingOptions {
27
+ /** The locale being translated into, from {@link readTranslateLocale}. */
28
+ locale: string;
29
+ /** Every catalog the page renders messages from. */
30
+ catalogs: readonly CatalogSource[];
31
+ /**
32
+ * The published messages of the locale, by catalog id, so the overlay opens
33
+ * on what the site already ships rather than on English.
34
+ * @default {}
35
+ */
36
+ translations?: Readonly<Record<string, Messages>>;
37
+ /**
38
+ * The tables whose rows a translator may write.
39
+ * @default []
40
+ */
41
+ tables?: readonly TranslatableTable[];
42
+ /**
43
+ * Where the overlay is loaded from.
44
+ * @default 'https://translate.cheminfo.org'
45
+ */
46
+ origin?: string;
47
+ /**
48
+ * The document the overlay script is added to.
49
+ * @default globalThis.document
50
+ */
51
+ document?: Document;
52
+ /**
53
+ * Told when the overlay cannot be fetched — translate.cheminfo.org down, a
54
+ * network that blocks it, an address typed wrong. The site is expected to
55
+ * stop formatting through the session, so a page nobody can edit goes back
56
+ * to being an ordinary page rather than staying marked with no editor.
57
+ * @default undefined
58
+ */
59
+ onUnavailable?: () => void;
60
+ /**
61
+ * How long to wait for the overlay before giving up on it, in ms. A server
62
+ * that accepts the connection and then says nothing never fails the script,
63
+ * so waiting for `error` alone would wait for ever.
64
+ * @default 10000
65
+ */
66
+ timeout?: number;
67
+ }
68
+ /**
69
+ * Put a page into translate mode.
70
+ *
71
+ * The session is exposed before the overlay is loaded, so the overlay finds a
72
+ * page already formatting marked messages. The site is handed the session back
73
+ * and must format through it from then on — that is what makes an edit show up
74
+ * as it is typed.
75
+ * @param options - See {@link StartTranslatingOptions}.
76
+ * @returns The session the page formats through.
77
+ */
78
+ export declare function startTranslating(options: StartTranslatingOptions): TranslateSession;
79
+ /** How the overlay script is added, and what happens when it does not come. */
80
+ export interface LoadOverlayOptions {
81
+ /**
82
+ * The document to add it to.
83
+ * @default globalThis.document
84
+ */
85
+ document?: Document;
86
+ /**
87
+ * Told when it cannot be fetched, or does not arrive in time.
88
+ * @default undefined
89
+ */
90
+ onUnavailable?: () => void;
91
+ /**
92
+ * How long to wait, in ms.
93
+ * @default 10000
94
+ */
95
+ timeout?: number;
96
+ }
97
+ /**
98
+ * Add the overlay script to the page, once.
99
+ * @param origin - Where the overlay is served from.
100
+ * @param options - See {@link LoadOverlayOptions}.
101
+ */
102
+ export declare function loadOverlay(origin: string, options?: LoadOverlayOptions): void;
103
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/translate/core/start.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAiB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,+DAA+D;AAC/D,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,mCAAmC,CAAC;AAEjE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMtE;AAED,wCAAwC;AACxC,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB,CAsBlB;AAKD,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,IAAI,CAkCN"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Turning a page into a translatable one.
3
+ *
4
+ * A site opened with `?translate=<locale>` formats every message with its
5
+ * invisible marker, hands its session to the overlay as
6
+ * `window.__cheminfoTranslate`, and loads that overlay from
7
+ * translate.cheminfo.org. Nothing of this is paid for by an ordinary visit:
8
+ * the site imports this module only once it has seen the parameter.
9
+ */
10
+ import { isLanguageTag } from "../../language/core/languageParam.js";
11
+ import { SOURCE_LOCALE } from "./catalog.js";
12
+ import { BRIDGE_GLOBAL, TranslateSession } from "./session.js";
13
+ /** The query parameter that opens a page in translate mode. */
14
+ export const TRANSLATE_PARAM = 'translate';
15
+ /** Where the overlay is served from unless a site says otherwise. */
16
+ export const TRANSLATE_ORIGIN = 'https://translate.cheminfo.org';
17
+ /**
18
+ * The locale a page is being translated into, from its address:
19
+ * `?translate=fr` opens the overlay for French.
20
+ * @param search - The query string, e.g. `location.search`.
21
+ * @returns The locale, or `undefined` when the page is not in translate mode,
22
+ * or names English, or names something that is not a language at all.
23
+ */
24
+ export function readTranslateLocale(search) {
25
+ const value = new URLSearchParams(search).get(TRANSLATE_PARAM);
26
+ if (value === null || value === SOURCE_LOCALE || !isLanguageTag(value)) {
27
+ return undefined;
28
+ }
29
+ return value;
30
+ }
31
+ /**
32
+ * Put a page into translate mode.
33
+ *
34
+ * The session is exposed before the overlay is loaded, so the overlay finds a
35
+ * page already formatting marked messages. The site is handed the session back
36
+ * and must format through it from then on — that is what makes an edit show up
37
+ * as it is typed.
38
+ * @param options - See {@link StartTranslatingOptions}.
39
+ * @returns The session the page formats through.
40
+ */
41
+ export function startTranslating(options) {
42
+ const { locale, catalogs, translations = {}, tables = [], origin = TRANSLATE_ORIGIN, document: target = globalThis.document, onUnavailable, timeout = OVERLAY_TIMEOUT, } = options;
43
+ const session = new TranslateSession({
44
+ locale,
45
+ catalogs,
46
+ translations,
47
+ tables,
48
+ marked: true,
49
+ });
50
+ Object.assign(globalThis, { [BRIDGE_GLOBAL]: session });
51
+ loadOverlay(origin, { document: target, onUnavailable, timeout });
52
+ return session;
53
+ }
54
+ /** How long the overlay has to arrive before the page gives up on it. */
55
+ const OVERLAY_TIMEOUT = 10_000;
56
+ /**
57
+ * Add the overlay script to the page, once.
58
+ * @param origin - Where the overlay is served from.
59
+ * @param options - See {@link LoadOverlayOptions}.
60
+ */
61
+ export function loadOverlay(origin, options = {}) {
62
+ const { document: target = globalThis.document, onUnavailable, timeout = OVERLAY_TIMEOUT, } = options;
63
+ if (target === undefined)
64
+ return;
65
+ const src = `${origin.replace(/\/$/, '')}/overlay.js`;
66
+ for (const loaded of target.querySelectorAll('script')) {
67
+ if (loaded.src === src)
68
+ return;
69
+ }
70
+ const script = target.createElement('script');
71
+ script.type = 'module';
72
+ script.src = src;
73
+ script.async = true;
74
+ // The page is only worth marking while there is an editor to use the marks,
75
+ // so a script that never arrives takes translate mode down with it.
76
+ let settled = false;
77
+ const giveUp = () => {
78
+ if (settled)
79
+ return;
80
+ settled = true;
81
+ script.remove();
82
+ onUnavailable?.();
83
+ };
84
+ const timer = globalThis.setTimeout(giveUp, timeout);
85
+ script.addEventListener('error', giveUp);
86
+ script.addEventListener('load', () => {
87
+ settled = true;
88
+ globalThis.clearTimeout(timer);
89
+ });
90
+ target.head.append(script);
91
+ }
92
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/translate/core/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * What a translator is offered before typing: the translations already made
3
+ * for the same English, for English that differs only where the text is not
4
+ * language, and for English that merely looks like it.
5
+ *
6
+ * A table is where this earns its place. Half of 118 element names are the
7
+ * same word in two languages and the other half differ by an ending; a column
8
+ * of quantities is a handful of phrases repeated with one word changed. A
9
+ * translator who is shown what was done three rows above confirms instead of
10
+ * typing, and the column stays consistent with itself — which is the thing a
11
+ * long table loses first.
12
+ *
13
+ * Nothing here invents a translation. Every suggestion is a translation
14
+ * somebody already wrote, either as it stands or with the part that is not
15
+ * language put back.
16
+ */
17
+ /** One message already translated, which a suggestion is drawn from. */
18
+ export interface TranslatedPair {
19
+ /** The key it is kept under, so the translator can see where it came from. */
20
+ key: string;
21
+ /** The English message. */
22
+ source: string;
23
+ /** Its translation. */
24
+ target: string;
25
+ }
26
+ /**
27
+ * How a suggestion was arrived at.
28
+ *
29
+ * - `exact` — the same English message, translated elsewhere.
30
+ * - `pattern` — English that differs only in a part that is not language (a
31
+ * number, a symbol, a formula), with that part put back into the
32
+ * translation.
33
+ * - `similar` — English that looks like this one; the translation is offered
34
+ * to be adapted, not to be taken as it is.
35
+ */
36
+ export type SuggestionKind = 'exact' | 'pattern' | 'similar';
37
+ /** One translation offered for a message. */
38
+ export interface MessageSuggestion {
39
+ /** What goes in the box if the translator takes it. */
40
+ message: string;
41
+ /** How it was arrived at. */
42
+ kind: SuggestionKind;
43
+ /** Between 0 and 1; 1 is the same English message. */
44
+ score: number;
45
+ /** The already-translated message it was drawn from. */
46
+ from: TranslatedPair;
47
+ }
48
+ /** How suggestions are chosen. */
49
+ export interface SuggestionOptions {
50
+ /**
51
+ * The most suggestions to return.
52
+ * @default 5
53
+ */
54
+ limit?: number;
55
+ /**
56
+ * How alike two English messages must be before one is offered for the
57
+ * other, between 0 and 1.
58
+ * @default 0.55
59
+ */
60
+ minimumScore?: number;
61
+ }
62
+ /**
63
+ * The translations worth offering for one English message.
64
+ * @param source - The English message being translated.
65
+ * @param pairs - Every message already translated in this language.
66
+ * @param options - See {@link SuggestionOptions}.
67
+ * @returns The suggestions, best first; empty when nothing is close enough.
68
+ */
69
+ export declare function messageSuggestions(source: string, pairs: readonly TranslatedPair[], options?: SuggestionOptions): MessageSuggestion[];
70
+ /**
71
+ * How alike two messages are, as the suggestions rank them.
72
+ * @param first - One message.
73
+ * @param second - The other.
74
+ * @returns 1 when they are the same, 0 when they share nothing.
75
+ */
76
+ export declare function messageSimilarity(first: string, second: string): number;
77
+ //# sourceMappingURL=suggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestions.d.ts","sourceRoot":"","sources":["../../../src/translate/core/suggestions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE7D,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,kCAAkC;AAClC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAUD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,GAAE,iBAAsB,GAC9B,iBAAiB,EAAE,CAqBrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAIvE"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * What a translator is offered before typing: the translations already made
3
+ * for the same English, for English that differs only where the text is not
4
+ * language, and for English that merely looks like it.
5
+ *
6
+ * A table is where this earns its place. Half of 118 element names are the
7
+ * same word in two languages and the other half differ by an ending; a column
8
+ * of quantities is a handful of phrases repeated with one word changed. A
9
+ * translator who is shown what was done three rows above confirms instead of
10
+ * typing, and the column stays consistent with itself — which is the thing a
11
+ * long table loses first.
12
+ *
13
+ * Nothing here invents a translation. Every suggestion is a translation
14
+ * somebody already wrote, either as it stands or with the part that is not
15
+ * language put back.
16
+ */
17
+ import leven from 'leven';
18
+ const DEFAULT_LIMIT = 5;
19
+ const DEFAULT_MINIMUM = 0.55;
20
+ const KIND_ORDER = {
21
+ exact: 0,
22
+ pattern: 1,
23
+ similar: 2,
24
+ };
25
+ /**
26
+ * The translations worth offering for one English message.
27
+ * @param source - The English message being translated.
28
+ * @param pairs - Every message already translated in this language.
29
+ * @param options - See {@link SuggestionOptions}.
30
+ * @returns The suggestions, best first; empty when nothing is close enough.
31
+ */
32
+ export function messageSuggestions(source, pairs, options = {}) {
33
+ const { limit = DEFAULT_LIMIT, minimumScore = DEFAULT_MINIMUM } = options;
34
+ if (source === '' || limit <= 0)
35
+ return [];
36
+ const found = [];
37
+ for (const pair of pairs) {
38
+ if (pair.target === '' || pair.source === '')
39
+ continue;
40
+ const suggestion = suggestFrom(source, pair, minimumScore);
41
+ if (suggestion !== undefined)
42
+ found.push(suggestion);
43
+ }
44
+ found.sort(compareSuggestions);
45
+ const best = [];
46
+ const taken = new Set();
47
+ for (const suggestion of found) {
48
+ if (taken.has(suggestion.message))
49
+ continue;
50
+ taken.add(suggestion.message);
51
+ best.push(suggestion);
52
+ if (best.length === limit)
53
+ break;
54
+ }
55
+ return best;
56
+ }
57
+ /**
58
+ * How alike two messages are, as the suggestions rank them.
59
+ * @param first - One message.
60
+ * @param second - The other.
61
+ * @returns 1 when they are the same, 0 when they share nothing.
62
+ */
63
+ export function messageSimilarity(first, second) {
64
+ const longest = Math.max(first.length, second.length);
65
+ if (longest === 0)
66
+ return 1;
67
+ return 1 - leven(first, second) / longest;
68
+ }
69
+ /**
70
+ * The best offer one already-translated message can make for another.
71
+ * @param source - The English being translated.
72
+ * @param pair - The already-translated message to draw from.
73
+ * @param minimumScore - How alike the two must be to be worth offering.
74
+ * @returns The suggestion, or `undefined` when the pair is too far away.
75
+ */
76
+ function suggestFrom(source, pair, minimumScore) {
77
+ if (pair.source === source) {
78
+ return { message: pair.target, kind: 'exact', score: 1, from: pair };
79
+ }
80
+ // An edit can never be smaller than the difference in length, so a pair that
81
+ // cannot reach the threshold is dropped before the distance is computed.
82
+ const longest = Math.max(source.length, pair.source.length);
83
+ const shortest = Math.min(source.length, pair.source.length);
84
+ if (longest === 0 || shortest / longest < minimumScore)
85
+ return undefined;
86
+ const pattern = patternSuggestion(source, pair);
87
+ if (pattern !== undefined && pattern.score >= minimumScore)
88
+ return pattern;
89
+ const score = messageSimilarity(source, pair.source);
90
+ if (score < minimumScore)
91
+ return undefined;
92
+ return { message: pair.target, kind: 'similar', score, from: pair };
93
+ }
94
+ /**
95
+ * A translation whose English differs from this one only in a run of text
96
+ * that survives into the translation unchanged — a number, a symbol, a
97
+ * formula. That run is the only thing put back, so nothing is invented.
98
+ * @param source - The English being translated.
99
+ * @param pair - The already-translated message to draw from.
100
+ * @returns The suggestion, or `undefined` when the run cannot be put back.
101
+ */
102
+ function patternSuggestion(source, pair) {
103
+ const prefix = commonPrefix(source, pair.source);
104
+ const suffix = commonSuffix(source.slice(prefix), pair.source.slice(prefix));
105
+ const own = source.slice(prefix, source.length - suffix);
106
+ const theirs = pair.source.slice(prefix, pair.source.length - suffix);
107
+ if (theirs === '')
108
+ return undefined;
109
+ // The varying run must appear once and only once, or putting it back would
110
+ // be a guess about which occurrence was meant.
111
+ const at = pair.target.indexOf(theirs);
112
+ if (at === -1 || pair.target.includes(theirs, at + 1))
113
+ return undefined;
114
+ const message = pair.target.slice(0, at) + own + pair.target.slice(at + theirs.length);
115
+ const kept = prefix + suffix;
116
+ const score = kept / Math.max(source.length, pair.source.length);
117
+ return { message, kind: 'pattern', score, from: pair };
118
+ }
119
+ function commonPrefix(first, second) {
120
+ const limit = Math.min(first.length, second.length);
121
+ let length = 0;
122
+ while (length < limit && first[length] === second[length])
123
+ length++;
124
+ return length;
125
+ }
126
+ function commonSuffix(first, second) {
127
+ const limit = Math.min(first.length, second.length);
128
+ let length = 0;
129
+ while (length < limit &&
130
+ first[first.length - 1 - length] === second[second.length - 1 - length]) {
131
+ length++;
132
+ }
133
+ return length;
134
+ }
135
+ function compareSuggestions(first, second) {
136
+ if (first.kind !== second.kind) {
137
+ return KIND_ORDER[first.kind] - KIND_ORDER[second.kind];
138
+ }
139
+ if (first.score !== second.score)
140
+ return second.score - first.score;
141
+ return first.from.key < second.from.key ? -1 : 1;
142
+ }
143
+ //# sourceMappingURL=suggestions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestions.js","sourceRoot":"","sources":["../../../src/translate/core/suggestions.ts"],"names":[],"mappings":"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"}