@massimo-cassandro/minimo 1.43.4 → 1.45.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.
- package/dev-tools/custom-media-builder/README.md +11 -0
- package/dev-tools/custom-media-builder/custom-media-builder.mjs +74 -0
- package/dev-tools/starter-kit/source_files/root/_sf/templates/_incl/minimo-form-layout.html.twig +10 -4
- package/dev-tools/starter-kit/source_files/root/package-tpl.json +1 -0
- package/dev-tools/starter-kit/starter-install.sh +1 -0
- package/package.json +3 -1
- package/src/css/forms/forms.css +1 -0
- package/src/custom-media.css +10 -33
- package/src/custom-media.js +72 -0
- package/src/utilities/better-text-with-places.js +41 -8
- package/src/utilities/better-text.js +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Custom media builder
|
|
2
|
+
|
|
3
|
+
Genera il file css delle @custom-media a partire da un modulo JS che esporta
|
|
4
|
+
(default) un oggetto { nome: media-query } e un un secondo oggetto breakpoint.js
|
|
5
|
+
per la condivisione dei breakpoiunt in js, vedi `src/custom-media.js`.
|
|
6
|
+
|
|
7
|
+
Uso da riga di comando (percorsi relativi alla directory corrente):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
node custom-media-builder.mjs [--src=./app/css/custom-media.js] [--dest=<src con estensione .css>]
|
|
11
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import process from 'process';
|
|
7
|
+
import { pathToFileURL } from 'url';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Genera il file css delle @custom-media.
|
|
11
|
+
* Il file viene riscritto solo se il contenuto è cambiato,
|
|
12
|
+
* per non attivare inutilmente il watcher di webpack.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} [options]
|
|
15
|
+
* @param {string} [options.src] modulo JS con l'export default delle custom media
|
|
16
|
+
* @param {string} [options.dest] file css da generare (default: file in `src` con estensione cambiata in `.css`)
|
|
17
|
+
* @returns {Promise<boolean>} `true` se il file è stato riscritto
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* await buildCustomMedia({
|
|
21
|
+
* src: './app/css/custom-media.js',
|
|
22
|
+
* dest: './app/css/custom-media.css',
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
export async function buildCustomMedia({
|
|
26
|
+
src = './app/css/custom-media.js',
|
|
27
|
+
dest = null,
|
|
28
|
+
} = {}) {
|
|
29
|
+
|
|
30
|
+
const srcPath = path.resolve(src),
|
|
31
|
+
destPath = path.resolve(dest ?? srcPath.replace(/\.m?js$/, '.css'));
|
|
32
|
+
|
|
33
|
+
const { default: customMedia } = await import(pathToFileURL(srcPath).href);
|
|
34
|
+
|
|
35
|
+
if (!customMedia || typeof customMedia !== 'object') {
|
|
36
|
+
throw new Error(`${src}: export default mancante o non valido`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const rows = Object.entries(customMedia).map(([name, query]) => {
|
|
40
|
+
if (typeof query !== 'string' || !query.trim()) {
|
|
41
|
+
throw new Error(`${src}: valore non valido per "${name}"`);
|
|
42
|
+
}
|
|
43
|
+
return `@custom-media --${name.replace(/^--/, '')} ${query.trim()};`;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const content = '/* File generato da custom-media-builder.mjs a partire da ' +
|
|
47
|
+
`${path.basename(srcPath)}. Eventuali modifich andranno perdute */\n\n` +
|
|
48
|
+
rows.join('\n') + '\n';
|
|
49
|
+
|
|
50
|
+
if (fs.existsSync(destPath) && fs.readFileSync(destPath, 'utf8') === content) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fs.writeFileSync(destPath, content);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// esecuzione da riga di comando
|
|
59
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
60
|
+
const args = Object.fromEntries(
|
|
61
|
+
process.argv.slice(2)
|
|
62
|
+
.map(arg => arg.match(/^--(src|dest)=(.+)$/))
|
|
63
|
+
.filter(Boolean)
|
|
64
|
+
.map(([, key, value]) => [key, value])
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const written = await buildCustomMedia(args);
|
|
69
|
+
console.log(written ? 'custom media: file aggiornato' : 'custom media: nessuna modifica');
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error(err.message);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
package/dev-tools/starter-kit/source_files/root/_sf/templates/_incl/minimo-form-layout.html.twig
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{#
|
|
2
|
-
|
|
2
|
+
minimo form layout (ex bs5)
|
|
3
3
|
=======================================
|
|
4
4
|
Massimo Cassandro
|
|
5
|
-
|
|
5
|
+
v. 2.1
|
|
6
6
|
#}
|
|
7
7
|
|
|
8
8
|
{#
|
|
@@ -112,11 +112,17 @@
|
|
|
112
112
|
{% set params = {} %}
|
|
113
113
|
{%- endif -%}
|
|
114
114
|
{%- if params.container_attr is not defined %}
|
|
115
|
-
{% set params = params|merge({container_attr: {}}) %}
|
|
115
|
+
{% set params = params|merge({container_attr: {} }) %}
|
|
116
116
|
{%- endif -%}
|
|
117
117
|
|
|
118
118
|
{% set params = params|merge({
|
|
119
|
-
container_attr: params.container_attr
|
|
119
|
+
container_attr: params.container_attr
|
|
120
|
+
|merge({
|
|
121
|
+
class: (
|
|
122
|
+
container_class|default('') ~ ' ' ~
|
|
123
|
+
params.container_attr.class|default('') ~
|
|
124
|
+
(compound|default()? ' form-collection-fset form-group' : ' form-group')
|
|
125
|
+
)|trim })
|
|
120
126
|
}) %}
|
|
121
127
|
|
|
122
128
|
{%- if disabled is defined and disabled %}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"create-favicons": "npx create-favicons --dir=./app/favicons",
|
|
32
32
|
"python server": "python3 -m http.server [[port8000]] # --directory __dirname__ # 8000 = default port",
|
|
33
33
|
"node server": "node serve # richiede ‘npm i serve’",
|
|
34
|
+
"build custom media": "npx custom-media-builder --src=./app/css/custom-media.js",
|
|
34
35
|
"build tokens": "npx buildTokens --config ./app/css/tokens-config.mjs",
|
|
35
36
|
"check unresolved props": "npx checkUnresolvedProps --config ./app/css/tokens-config.mjs",
|
|
36
37
|
"find orphan css classes": "npx findOrphanCssClasses --config ./app/css/orphan-css-classes.config.mjs",
|
|
@@ -458,6 +458,7 @@ done
|
|
|
458
458
|
MINIMO_PKG_DIR=./node_modules/@massimo-cassandro/minimo
|
|
459
459
|
|
|
460
460
|
force_cat "${MINIMO_PKG_DIR}/src/custom-properties.css" "${FRONTEND_INSTALL_PATH}/css/minimo-custom-properties.css"
|
|
461
|
+
force_cat "${MINIMO_PKG_DIR}/src/custom-media.js" "${FRONTEND_INSTALL_PATH}/css/custom-media.js"
|
|
461
462
|
force_cat "${MINIMO_PKG_DIR}/src/custom-media.css" "${FRONTEND_INSTALL_PATH}/css/custom-media.css"
|
|
462
463
|
|
|
463
464
|
# entry css principale del progetto: copia diretta di minimo.css
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massimo-cassandro/minimo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.0",
|
|
4
4
|
"description": "Light css framework & utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"upd@m": "dev-tools/upd@m/index.mjs",
|
|
35
35
|
"svgIconsTools": "dev-tools/svg-icons-tools/index.mjs",
|
|
36
36
|
"create-favicons": "dev-tools/create-favicons/index.mjs",
|
|
37
|
+
"custom-media-builder": "dev-tools/custom-media-builder/custom-media-builder.mjs",
|
|
37
38
|
"starter-kit": "dev-tools/starter-kit/starter-install.sh"
|
|
38
39
|
},
|
|
39
40
|
"repository": {
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
"build-margin-padding-css": "node ./scripts/build-margin-padding-css.mjs",
|
|
48
49
|
"generate:types": "node ./scripts/generate-class-types.mjs",
|
|
49
50
|
"prepublishOnly": "npm run generate:types",
|
|
51
|
+
"build custom media": "node ./dev-tools/custom-media-builder/custom-media-builder.mjs --src=./src/custom-media.js",
|
|
50
52
|
"check unresolved props": "node ./dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs --config ./design-tokens/tokens-config.mjs",
|
|
51
53
|
"test": "node --test \"test/**/*.test.mjs\"",
|
|
52
54
|
"test sideEffects tree-shaking": "node ./test/sideEffects-tree-shaking/run-test.mjs",
|
package/src/css/forms/forms.css
CHANGED
package/src/custom-media.css
CHANGED
|
@@ -1,40 +1,17 @@
|
|
|
1
|
-
/*
|
|
2
|
-
vedi scripts/build-margin-padding-css.mjs) per coerenza con la scala `sizes`,
|
|
3
|
-
che usa la stessa nomenclatura xs/sm/md/lg/xl e genera ambiguità nelle
|
|
4
|
-
utility responsive. Non banale: i tier attuali (xxlarge/xlarge/large/medium/
|
|
5
|
-
small, con varianti -only/-down) sono numerosi e in parte sovrapposti (es.
|
|
6
|
-
"large" = "small desktop") e non si riducono in modo pulito a poche
|
|
7
|
-
categorie semantiche; inoltre il nome è usato in molti file (grid.css,
|
|
8
|
-
display.css, visibility.css, text.css, sf-macro.css, json-table, oltre ai
|
|
9
|
-
file margin-padding-*-media.css) ed è parte di un template pensato per
|
|
10
|
-
essere personalizzato dall'utente: rinominarlo qui non aggiorna le copie
|
|
11
|
-
già in uso nei progetti che lo hanno importato. */
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
90rem : 1440px xxlarge (large desktop)
|
|
15
|
-
80rem : 1280px xlarge (desktop)
|
|
16
|
-
64rem : 1024px large (small desktop)
|
|
17
|
-
47.5rem : 760px medium (tablet)
|
|
18
|
-
25rem : 400px small (phone)
|
|
19
|
-
|
|
20
|
-
tablet alt:
|
|
21
|
-
53.75rem : 860px medium (tablet)
|
|
22
|
-
*/
|
|
1
|
+
/* File generato da custom-media-builder.mjs a partire da custom-media.js: NON MODIFICARE DIRETTAMENTE */
|
|
23
2
|
|
|
24
3
|
@custom-media --media-xxlarge-viewport-up (width >= 90rem);
|
|
25
4
|
@custom-media --media-xlarge-viewport-up (width >= 80rem);
|
|
26
5
|
@custom-media --media-large-viewport-up (width >= 64rem);
|
|
27
6
|
@custom-media --media-medium-viewport-up (width >= 47.5rem);
|
|
28
7
|
@custom-media --media-small-viewport-up (width >= 25rem);
|
|
29
|
-
|
|
30
8
|
@custom-media --media-xxlarge-viewport-only (width >= 90rem);
|
|
31
|
-
@custom-media --media-xlarge-viewport-only (
|
|
32
|
-
@custom-media --media-large-viewport-only (64rem
|
|
33
|
-
@custom-media --media-medium-viewport-only (47.5rem
|
|
34
|
-
@custom-media --media-small-viewport-only (width
|
|
35
|
-
|
|
36
|
-
@custom-media --media-
|
|
37
|
-
@custom-media --media-
|
|
38
|
-
@custom-media --media-
|
|
39
|
-
@custom-media --media-
|
|
40
|
-
@custom-media --media-small-viewport-down (max-width: 25rem);
|
|
9
|
+
@custom-media --media-xlarge-viewport-only (80rem <= width < 90rem);
|
|
10
|
+
@custom-media --media-large-viewport-only (64rem <= width < 80rem);
|
|
11
|
+
@custom-media --media-medium-viewport-only (47.5rem <= width < 64rem);
|
|
12
|
+
@custom-media --media-small-viewport-only (width < 47.5rem);
|
|
13
|
+
@custom-media --media-xxlarge-viewport-down (width < 90rem);
|
|
14
|
+
@custom-media --media-xlarge-viewport-down (width < 80rem);
|
|
15
|
+
@custom-media --media-large-viewport-down (width < 64rem);
|
|
16
|
+
@custom-media --media-medium-viewport-down (width < 47.5rem);
|
|
17
|
+
@custom-media --media-small-viewport-down (width < 25rem);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Definizioni delle custom media del progetto: unica fonte dei breakpoint,
|
|
3
|
+
usata sia per generare custom-media.css (vedi custom-media-builder.mjs,
|
|
4
|
+
`npm run "build custom media"`) sia direttamente in JS.
|
|
5
|
+
|
|
6
|
+
NB: dopo ogni modifica rigenerare custom-media.css (la generazione è
|
|
7
|
+
comunque eseguita all'avvio delle build webpack DEV e PROD).
|
|
8
|
+
|
|
9
|
+
I valori sono duplicati nei `media` scritti a mano dei template Twig
|
|
10
|
+
(home.html.twig e home_incl/hero.incl.html.twig): vanno aggiornati a mano.
|
|
11
|
+
|
|
12
|
+
90rem : 1440px xxlarge (large desktop)
|
|
13
|
+
80rem : 1280px xlarge (desktop)
|
|
14
|
+
64rem : 1024px large (small desktop)
|
|
15
|
+
47.5rem : 760px medium (tablet)
|
|
16
|
+
25rem : 400px small (phone)
|
|
17
|
+
|
|
18
|
+
tablet alt:
|
|
19
|
+
53.75rem : 860px medium (tablet)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/* TODO valutare rinomina dei breakpoint in nomi semantici (es. dsk/lap/tab/mob,
|
|
23
|
+
vedi scripts/build-margin-padding-css.mjs) per coerenza con la scala `sizes`,
|
|
24
|
+
che usa la stessa nomenclatura xs/sm/md/lg/xl e genera ambiguità nelle
|
|
25
|
+
utility responsive. Non banale: i tier attuali (xxlarge/xlarge/large/medium/
|
|
26
|
+
small, con varianti -only/-down) sono numerosi e in parte sovrapposti (es.
|
|
27
|
+
"large" = "small desktop") e non si riducono in modo pulito a poche
|
|
28
|
+
categorie semantiche; inoltre il nome è usato in molti file (grid.css,
|
|
29
|
+
display.css, visibility.css, text.css, sf-macro.css, json-table, oltre ai
|
|
30
|
+
file margin-padding-*-media.css) ed è parte di un template pensato per
|
|
31
|
+
essere personalizzato dall'utente: rinominarlo qui non aggiorna le copie
|
|
32
|
+
già in uso nei progetti che lo hanno importato. */
|
|
33
|
+
|
|
34
|
+
export const breakpoints = {
|
|
35
|
+
xxlarge: '90rem',
|
|
36
|
+
xlarge: '80rem',
|
|
37
|
+
large: '64rem',
|
|
38
|
+
medium: '47.5rem',
|
|
39
|
+
small: '25rem',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const bp = breakpoints;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Custom media del progetto: chiave = nome della custom media (senza `--`),
|
|
46
|
+
* valore = media query.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* import customMedia from './custom-media.js';
|
|
50
|
+
* const mql = matchMedia(customMedia['media-medium-viewport-up']); // '(width >= 47.5rem)'
|
|
51
|
+
*/
|
|
52
|
+
const customMedia = {
|
|
53
|
+
'media-xxlarge-viewport-up': `(width >= ${bp.xxlarge})`,
|
|
54
|
+
'media-xlarge-viewport-up': `(width >= ${bp.xlarge})`,
|
|
55
|
+
'media-large-viewport-up': `(width >= ${bp.large})`,
|
|
56
|
+
'media-medium-viewport-up': `(width >= ${bp.medium})`,
|
|
57
|
+
'media-small-viewport-up': `(width >= ${bp.small})`,
|
|
58
|
+
|
|
59
|
+
'media-xxlarge-viewport-only': `(width >= ${bp.xxlarge})`,
|
|
60
|
+
'media-xlarge-viewport-only': `(${bp.xlarge} <= width < ${bp.xxlarge})`,
|
|
61
|
+
'media-large-viewport-only': `(${bp.large} <= width < ${bp.xlarge})`,
|
|
62
|
+
'media-medium-viewport-only': `(${bp.medium} <= width < ${bp.large})`,
|
|
63
|
+
'media-small-viewport-only': `(width < ${bp.medium})`,
|
|
64
|
+
|
|
65
|
+
'media-xxlarge-viewport-down': `(width < ${bp.xxlarge})`,
|
|
66
|
+
'media-xlarge-viewport-down': `(width < ${bp.xlarge})`,
|
|
67
|
+
'media-large-viewport-down': `(width < ${bp.large})`,
|
|
68
|
+
'media-medium-viewport-down': `(width < ${bp.medium})`,
|
|
69
|
+
'media-small-viewport-down': `(width < ${bp.small})`,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default customMedia;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/*! minimo - Better Text with places */
|
|
3
3
|
|
|
4
|
-
import { betterText, NBSP_AFTER_PARTICLE_REGEX } from './better-text.js';
|
|
4
|
+
import { betterText, NBSP_AFTER_PARTICLE_REGEX, PARTICELLE } from './better-text.js';
|
|
5
5
|
|
|
6
6
|
const places = [
|
|
7
7
|
// EUROPA
|
|
@@ -467,6 +467,19 @@ function buildPlacesMatcher(list) {
|
|
|
467
467
|
|
|
468
468
|
const defaultMatcher = buildPlacesMatcher(places);
|
|
469
469
|
|
|
470
|
+
/*
|
|
471
|
+
Corrisponde agli spazi (normali o non separabili) NON seguiti da una particella:
|
|
472
|
+
usata con l'opzione `addNbsp` per unire le parole dei nomi composti, lasciando
|
|
473
|
+
separabile lo spazio prima di una particella (es. "Lago di Como" → spazio normale
|
|
474
|
+
tra "Lago" e "di", mentre quello tra "di" e "Como" è già gestito da betterText())
|
|
475
|
+
*/
|
|
476
|
+
const SPACE_BEFORE_NON_PARTICLE_REGEX = new RegExp(
|
|
477
|
+
'[ \\u00A0]+(?!(?:' +
|
|
478
|
+
PARTICELLE.map(p => p.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&')).join('|') +
|
|
479
|
+
')(?![\\p{L}\\p{N}]))',
|
|
480
|
+
'giu'
|
|
481
|
+
);
|
|
482
|
+
|
|
470
483
|
/**
|
|
471
484
|
* Versione di betterText() che normalizza anche le occorrenze di luoghi noti
|
|
472
485
|
* (paesi, città, fiumi, monti, località turistiche) presenti nel testo:
|
|
@@ -480,18 +493,33 @@ const defaultMatcher = buildPlacesMatcher(places);
|
|
|
480
493
|
* ovunque compaiano.
|
|
481
494
|
*
|
|
482
495
|
* @param {string} str - stringa da elaborare
|
|
483
|
-
* @param {
|
|
484
|
-
* @param {string[]} [
|
|
496
|
+
* @param {object} [options] - opzioni (default: {})
|
|
497
|
+
* @param {string[]} [options.custom_words] - elenco di parole di cui va mantenuta la capitalizzazione esatta (es. `['iPhone', 'macOS']`) (default: [])
|
|
498
|
+
* @param {string[]} [options.extra_places] - luoghi aggiuntivi, uniti all'elenco predefinito (default: [])
|
|
499
|
+
* @param {boolean} [options.addNbsp] - se `true`, nei nomi di luogo composti da più parole gli spazi vengono
|
|
500
|
+
* sostituiti da spazi non separabili, tranne quelli che precedono una particella
|
|
501
|
+
* (es. in "Monte Bianco" lo spazio diventa non separabile, in "Lago di Como" solo quello dopo "di") (default: false)
|
|
485
502
|
* @returns {string} stringa elaborata, oppure stringa vuota se l'input è falsy
|
|
486
503
|
*
|
|
487
504
|
* @example
|
|
488
505
|
* betterTextWithPlaces("vacanza a new york e nel lago di como ,l'avana");
|
|
489
506
|
* // → "vacanza a New York e nel Lago di Como, L’Avana"
|
|
490
507
|
*
|
|
491
|
-
* betterTextWithPlaces('gita a monte cervino', ['iPhone'], ['Monte Cervino']);
|
|
508
|
+
* betterTextWithPlaces('gita a monte cervino', { custom_words: ['iPhone'], extra_places: ['Monte Cervino'] });
|
|
492
509
|
* // → 'gita a Monte Cervino'
|
|
510
|
+
*
|
|
511
|
+
* // opzioni con i valori di default
|
|
512
|
+
* betterTextWithPlaces('monte bianco e lago di como', {
|
|
513
|
+
* custom_words: [],
|
|
514
|
+
* extra_places: [],
|
|
515
|
+
* addNbsp: false
|
|
516
|
+
* });
|
|
517
|
+
* // → 'Monte Bianco e Lago di Como' (spazio non separabile solo dopo "di")
|
|
518
|
+
*
|
|
519
|
+
* betterTextWithPlaces('monte bianco e lago di como', { addNbsp: true });
|
|
520
|
+
* // → 'Monte Bianco e Lago di Como' (spazi non separabili tra "Monte" e "Bianco" e dopo "di")
|
|
493
521
|
*/
|
|
494
|
-
export function betterTextWithPlaces(str, custom_words = [], extra_places = []) {
|
|
522
|
+
export function betterTextWithPlaces(str, { custom_words = [], extra_places = [], addNbsp = false } = {}) {
|
|
495
523
|
|
|
496
524
|
str = betterText(str, custom_words);
|
|
497
525
|
|
|
@@ -503,7 +531,12 @@ export function betterTextWithPlaces(str, custom_words = [], extra_places = [])
|
|
|
503
531
|
? buildPlacesMatcher([...places, ...extra_places])
|
|
504
532
|
: defaultMatcher;
|
|
505
533
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
534
|
+
if (!matcher) {
|
|
535
|
+
return str;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return str.replace(matcher.regex, match => {
|
|
539
|
+
const place = matcher.canonical.get(placeKey(match)) ?? match;
|
|
540
|
+
return addNbsp ? place.replace(SPACE_BEFORE_NON_PARTICLE_REGEX, '\u00A0') : place;
|
|
541
|
+
});
|
|
509
542
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
che nulla di tutto ciò dipende dagli argomenti della funzione e in precedenza veniva
|
|
10
10
|
ricostruito a ogni singola chiamata di betterText().
|
|
11
11
|
*/
|
|
12
|
-
const PARTICELLE = [
|
|
12
|
+
export const PARTICELLE = [
|
|
13
13
|
'e', 'ed',
|
|
14
14
|
'di', 'a', 'da', 'in', 'per', 'con', 'su', 'per', 'tra', 'fra',
|
|
15
15
|
'il', 'lo', 'la', 'i', 'gli', 'le',
|