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
← All changes | assets/js/synonyms/utils.js +236 -95 4.2.1 → 5.3.5 View file →
@@ -1,23 +1,53 @@
1 +/**
2 + * External dependencies.
3 + */
1 4 import { v4 as uuidv4 } from 'uuid';
2 5
3 6 /**
4 - * Generate universally unique identifier.
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.
5 15 *
6 - * @returns {string} A universally unique identifier
16 + * @typedef Rule
17 + * @property {string} id Rule ID.
18 + * @property {Synonym[]} synonyms Rule synonyms.
19 + * @property {boolean} valid Whether the rule is valid.
7 20 */
8 -const uuid = () => {
9 - return uuidv4();
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;
10 30 };
11 31
12 32 /**
13 - * Map entry
33 + * Determine whether a synonym is not a primary term.
14 34 *
15 - * @param {Array} synonyms Array of synonyms.
16 - * @param {string} id The id, default generated by the application.
17 - * @returns {object} Map entry
35 + * @param {Synonym} synonym Synonym.
36 + * @returns {boolean}
18 37 */
19 -const mapEntry = (synonyms = [], id = '') => {
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 = '') => {
20 50 return {
21 51 id: id.length ? id : uuidv4(),
22 52 synonyms,
23 53 valid: true,
@@ -24,107 +54,218 @@
24 54 };
25 55 };
26 56
27 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 +/**
28 196 * Reduce state to Solr spec.
29 197 *
30 - * @param {object} state Current state.
31 - * @param {object[]} state.sets Array of synonym sets.
32 - * @param {object[]} state.alternatives Array of alternative sets.
198 + * @param {Rule[]} rules Array of rule sets.
33 199 * @returns {string} new state
34 200 */
35 -const reduceStateToSolr = ({ sets, alternatives }) => {
36 - const synonymsList = [];
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);
37 205
38 - // Handle sets.
39 - synonymsList.push('# Defined sets ( equivalent synonyms).');
40 - synonymsList.push(...sets.map(({ synonyms }) => synonyms.map(({ value }) => value).join(', ')));
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 + ];
41 220
42 - // Handle alternatives.
43 - synonymsList.push('\r');
44 - synonymsList.push('# Defined alternatives (explicit mappings).');
45 - synonymsList.push(
46 - ...alternatives.map((alternative) =>
47 - alternative.synonyms.find((item) => item.primary && item.value.length)
48 - ? alternative.synonyms
49 - .find((item) => item.primary)
50 - .value.concat(' => ')
51 - .concat(
52 - alternative.synonyms
53 - .filter((i) => !i.primary)
54 - .map(({ value }) => value)
55 - .join(', '),
56 - )
57 - : false,
58 - ),
59 - );
60 -
61 - return synonymsList.filter(Boolean).join('\n');
221 + return lines.join('\n');
62 222 };
63 223
64 224 /**
65 225 * Reduce Solr text file to State.
66 226 *
67 - * @param {string} solr A string in the Solr parseable synonym format.
68 - * @param {object} currentState The current sate.
69 - * @returns {object} State
227 + * @param {string} solr A string in the Solr parseable synonym format.
228 + * @returns {Rule[]} State
70 229 */
71 -const reduceSolrToState = (solr, currentState) => {
72 - /**
73 - * Format token.
74 - *
75 - * @param {string} value The value.
76 - * @param {boolean} primary Whether it's a primary.
77 - * @returns {object} Formated token
78 - */
79 - const formatToken = (value, primary = false) => {
80 - return {
81 - label: value,
82 - value,
83 - primary,
84 - };
85 - };
230 +const getRulesFromSolr = (solr) => {
231 + const rules = solr.split(/\r?\n/).reduce((rules, line) => {
232 + if (line.indexOf('#') === 0) {
233 + return rules;
234 + }
86 235
87 - return {
88 - ...currentState,
89 - ...solr.split(/\r?\n/).reduce(
90 - (newState, line) => {
91 - if (line.indexOf('#') === 0 || !line.trim().length) {
92 - return newState;
93 - }
236 + if (line.trim().length === 0) {
237 + return rules;
238 + }
94 239
95 - if (line.indexOf('=>') !== -1) {
96 - const parts = line.split('=>');
97 - return {
98 - ...newState,
99 - alternatives: [
100 - ...newState.alternatives,
101 - mapEntry([
102 - formatToken(parts[0].trim(), true),
103 - ...parts[1]
104 - .split(',')
105 - .filter((v) => v.trim())
106 - .map((token) => formatToken(token.trim())),
107 - ]),
108 - ],
109 - };
110 - }
240 + const synonyms = getSynonyms(line);
241 + const rule = getRule(synonyms);
111 242
112 - return {
113 - ...newState,
114 - sets: [
115 - ...newState.sets,
116 - mapEntry([
117 - ...line
118 - .split(',')
119 - .filter((v) => v.trim())
120 - .map((token) => formatToken(token.trim())),
121 - ]),
122 - ],
123 - };
124 - },
125 - { alternatives: [], sets: [] },
126 - ),
127 - };
243 + rules.push(rule);
244 +
245 + return rules;
246 + }, []);
247 +
248 + return rules;
128 249 };
129 250
130 -export { reduceStateToSolr, reduceSolrToState, uuid, mapEntry };
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 +};