PluginProbe
ElasticPress / 5.3.5
ElasticPress v5.3.5
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / assets / js / synonyms / utils.js

utils.js in ElasticPress 5.3.5, at assets/js/synonyms/utils.js

272 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * External dependencies.
3 */
4 import { v4 as uuidv4 } from 'uuid';
5
6 /**
7 * WordPress dependencies.
8 */
9 import { __ } from '@wordpress/i18n';
10
11 /**
12 * @typedef Synonym
13 * @property {string} value The synonym value.
14 * @property {boolean} primary Whether the synonym is a primary term.
15 *
16 * @typedef Rule
17 * @property {string} id Rule ID.
18 * @property {Synonym[]} synonyms Rule synonyms.
19 * @property {boolean} valid Whether the rule is valid.
20 */
21
22 /**
23 * Determine whether a synonym is a primary term.
24 *
25 * @param {Synonym} synonym Synonym.
26 * @returns {boolean}
27 */
28 const isPrimary = (synonym) => {
29 return synonym.primary;
30 };
31
32 /**
33 * Determine whether a synonym is not a primary term.
34 *
35 * @param {Synonym} synonym Synonym.
36 * @returns {boolean}
37 */
38 const isNotPrimary = (synonym) => {
39 return !synonym.primary;
40 };
41
42 /**
43 * Get a rule object for a list of synonyms,
44 *
45 * @param {Synonym[]} synonyms Array of synonyms.
46 * @param {string} id Rule ID.
47 * @returns {Rule} Map entry
48 */
49 const getRule = (synonyms = [], id = '') => {
50 return {
51 id: id.length ? id : uuidv4(),
52 synonyms,
53 valid: true,
54 };
55 };
56
57 /**
58 * Get a rule in Solr format.
59 *
60 * @param {Rule} rule Rule set.
61 * @param {Synonym[]} rule.synonyms Rule synonyms.
62 * @returns {string}
63 */
64 const getSolr = ({ synonyms }) => {
65 const terms = synonyms.filter(isPrimary);
66 const replacements = synonyms.filter(isNotPrimary);
67
68 const sides = [terms, replacements]
69 .map((side) =>
70 side
71 .map((synonym) => synonym.value.trim())
72 .filter((synonym) => !!synonym)
73 .join(', '),
74 )
75 .filter((side) => side);
76
77 return sides.join(' => ');
78 };
79
80 /**
81 * Get synonyms from a Solr line.
82 *
83 * @param {string} line Solr line.
84 * @returns {Synonym[]}
85 */
86 const getSynonyms = (line) => {
87 const parts = line.split('=>').map((p, i, a) => {
88 const part = p
89 .split(',')
90 .map((v) => v.trim())
91 .filter((v) => v);
92
93 return part
94 .filter((v, i) => part.indexOf(v) === i)
95 .filter((v) => v)
96 .map((v) => ({
97 label: v,
98 value: v,
99 primary: a.length === 2 && i === 0,
100 }));
101 });
102
103 return parts.flat();
104 };
105
106 /**
107 * Determine whether a rule describes hyponyms.
108 *
109 * Hyponyms are rules where there is a single primary term and where the
110 * primary term is also included as a replacement.
111 *
112 * @param {Rule} rule Rule set.
113 * @param {Synonym[]} rule.synonyms Rule synonyms.
114 * @returns {boolean}
115 */
116 const isHyponyms = (rule) => {
117 const hypernyms = rule.synonyms.filter(isPrimary);
118
119 return (
120 hypernyms.length === 1 &&
121 rule.synonyms.filter(isNotPrimary).some((s) => hypernyms.some((h) => h.value === s.value))
122 );
123 };
124
125 /**
126 * Validate a new set of hyponyms.
127 *
128 * Hyponyms are valid if there is only one primary term and at least one
129 * replacement that is not also the primary term.
130 *
131 * This function is used before the hypernym is automatically injected as a
132 * hypernym, so make sure to use `isHyponyms` first to verify that the hypernym
133 * is included as a hyponym.
134 *
135 * @param {Array} synonyms Synonyms.
136 * @returns {boolean}
137 */
138 const isHyponymsValid = (synonyms) => {
139 const hypernyms = synonyms.filter(isPrimary);
140 const hyponyms = synonyms
141 .filter(isNotPrimary)
142 .filter((s) => !hypernyms.some((h) => h.value === s.value));
143
144 return hypernyms.length === 1 && hyponyms.length > 0;
145 };
146
147 /**
148 * Determine whether a rule describes replacements.
149 *
150 * Replacements are rules where there are terms and replacements that do not
151 * otherwise describe hyponyms.
152 *
153 * @param {Rule} rule Rule set.
154 * @param {Synonym[]} rule.synonyms Rule synonyms.
155 * @returns {boolean}
156 */
157 const isReplacements = ({ synonyms }) => {
158 return !isHyponyms({ synonyms }) && synonyms.some(isPrimary);
159 };
160
161 /**
162 * Validate a new set of replacements.
163 *
164 * Replacements are valid if there is at least one term and one replacement.
165 *
166 * @param {Array} synonyms Synonyms.
167 * @returns {boolean}
168 */
169 const isReplacementsValid = (synonyms) => {
170 return !isHyponyms({ synonyms }) && synonyms.some(isPrimary) && synonyms.some(isNotPrimary);
171 };
172
173 /**
174 * Is a list of synonyms a synonyms rule set.
175 *
176 *
177 * @param {Rule} rule Rule set.
178 * @param {Synonym[]} rule.synonyms Rule synonyms.
179 * @returns {boolean}
180 */
181 const isSynonyms = ({ synonyms }) => {
182 return synonyms.every(isNotPrimary);
183 };
184
185 /**
186 * Is a synonyms rule set valid.
187 *
188 * @param {Array} synonyms Rule synonyms.
189 * @returns {boolean}
190 */
191 const isSynonymsValid = (synonyms) => {
192 return synonyms.length > 1 && synonyms.every(isNotPrimary);
193 };
194
195 /**
196 * Reduce state to Solr spec.
197 *
198 * @param {Rule[]} rules Array of rule sets.
199 * @returns {string} new state
200 */
201 const getSolrFromRules = (rules) => {
202 const synonyms = rules.filter(isSynonyms).map(getSolr);
203 const hyponyms = rules.filter(isHyponyms).map(getSolr);
204 const replacements = rules.filter(isReplacements).map(getSolr);
205
206 const lines = [
207 __('# Defined synonyms.', 'elasticpress'),
208 '',
209 ...synonyms,
210 '',
211 __('# Defined hyponyms.', 'elasticpress'),
212 '',
213 ...hyponyms,
214 '',
215 __('# Defined replacements.', 'elasticpress'),
216 '',
217 ...replacements,
218 '',
219 ];
220
221 return lines.join('\n');
222 };
223
224 /**
225 * Reduce Solr text file to State.
226 *
227 * @param {string} solr A string in the Solr parseable synonym format.
228 * @returns {Rule[]} State
229 */
230 const getRulesFromSolr = (solr) => {
231 const rules = solr.split(/\r?\n/).reduce((rules, line) => {
232 if (line.indexOf('#') === 0) {
233 return rules;
234 }
235
236 if (line.trim().length === 0) {
237 return rules;
238 }
239
240 const synonyms = getSynonyms(line);
241 const rule = getRule(synonyms);
242
243 rules.push(rule);
244
245 return rules;
246 }, []);
247
248 return rules;
249 };
250
251 /**
252 * Generate universally unique identifier.
253 *
254 * @returns {string} A universally unique identifier
255 */
256 const uuid = () => {
257 return uuidv4();
258 };
259
260 export {
261 isHyponyms,
262 isHyponymsValid,
263 isReplacements,
264 isReplacementsValid,
265 isSynonyms,
266 isSynonymsValid,
267 getRule,
268 getRulesFromSolr,
269 getSolrFromRules,
270 uuid,
271 };
272