@aglyn/plugins-ai 1.0.0-beta.262 → 1.0.0-beta.264
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/package.json +17 -17
- package/src/lib/insights/ai-figure-summaries.d.ts +1 -1
- package/src/lib/insights/ai-figure-summaries.js +55 -38
- package/src/lib/insights/ai-figure-summaries.js.map +1 -1
- package/src/lib/insights/ai-insight-digest.d.ts +2 -0
- package/src/lib/insights/ai-insight-digest.js +7 -4
- package/src/lib/insights/ai-insight-digest.js.map +1 -1
- package/src/lib/jobs/ai-job-insight-step.d.ts +1 -1
- package/src/lib/jobs/ai-job-insight-step.js +5 -3
- package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +2 -0
- package/src/lib/jobs/ai-job-page-language.js +23 -2
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.js +8 -2
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +14 -1
- package/src/lib/jobs/ai-job-plan-step.js +44 -9
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +11 -1
- package/src/lib/jobs/ai-job-site-datasets.js +32 -7
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-jobs-notify.d.ts +8 -1
- package/src/lib/jobs/ai-jobs-notify.js +44 -2
- package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +91 -11
- package/src/lib/jobs/ai-layout-stock-photos.js +1046 -48
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.js +163 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.js +53 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.d.ts +21 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.js +119 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.js +24 -11
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +7 -0
- package/src/lib/layout-language/ai-layout-listings.js +12 -0
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +27 -8
- package/src/lib/layout-language/ai-layout-pictures.js +85 -4
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/layout-language/ai-layout-promised-copy.d.ts +54 -0
- package/src/lib/layout-language/ai-layout-promised-copy.js +104 -0
- package/src/lib/layout-language/ai-layout-promised-copy.js.map +1 -0
- package/src/lib/model/ai-insight.d.ts +9 -0
- package/src/lib/model/ai-insight.js +12 -0
- package/src/lib/model/ai-insight.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +7 -1
- package/src/lib/model/ai-job-notice.js +10 -9
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-plan-said-sections.d.ts +81 -0
- package/src/lib/model/ai-plan-said-sections.js +168 -0
- package/src/lib/model/ai-plan-said-sections.js.map +1 -0
- package/src/lib/model/ai-site-job.d.ts +8 -2
- package/src/lib/model/ai-site-job.js +7 -1
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +15 -1
- package/src/lib/runtime/ai-doctrine-validators.js +80 -1
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +11 -3
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
|
@@ -132,6 +132,14 @@ import { aiStockBusinessNoun } from "./ai-stock-business-nouns.js";
|
|
|
132
132
|
* ("wedding" of "a wedding and portrait photographer") is not the craft;
|
|
133
133
|
* and a hero whose second tag names the world too leads one whose first
|
|
134
134
|
* alone does.
|
|
135
|
+
* 9. **A world from the name** (the beta.261 Synchronicity Gym start,
|
|
136
|
+
* AGL-3856: its business type "a local service business" named no world,
|
|
137
|
+
* so its hero searched nothing and was left a black scrim, and its
|
|
138
|
+
* closing band's "Ready to train" took a subway train). A business type
|
|
139
|
+
* that names no world takes the craft its name, else its audience, names
|
|
140
|
+
* where this module lists it ("gym" of "Synchronicity Gym"); and a
|
|
141
|
+
* training word's other senses (a railway's train, an elevator's lift, a
|
|
142
|
+
* newspaper's press, a boat's row) never fill a gym's picture.
|
|
135
143
|
*
|
|
136
144
|
* A slot the library could not fill because it never answered — down, or
|
|
137
145
|
* out of time before its first answer — or because the site's library
|
|
@@ -1208,7 +1216,8 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1208
1216
|
'boxer',
|
|
1209
1217
|
'beach',
|
|
1210
1218
|
'circus',
|
|
1211
|
-
// Another sport's ball, never "medicine ball": a basketball court covered a deadlift night (AGL-3864)
|
|
1219
|
+
// Another sport's ball, never "medicine ball": a basketball court covered a deadlift night (AGL-3864),
|
|
1220
|
+
// a cricket ball on a wooden court another (AGL-3856).
|
|
1212
1221
|
'basketball',
|
|
1213
1222
|
'football',
|
|
1214
1223
|
'soccer',
|
|
@@ -1217,7 +1226,58 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1217
1226
|
'tennis',
|
|
1218
1227
|
'golf',
|
|
1219
1228
|
'rugby',
|
|
1220
|
-
'hockey'
|
|
1229
|
+
'hockey',
|
|
1230
|
+
'cricket',
|
|
1231
|
+
'squash',
|
|
1232
|
+
'badminton',
|
|
1233
|
+
'shuttlecock',
|
|
1234
|
+
'bowling',
|
|
1235
|
+
'billiards',
|
|
1236
|
+
'snooker',
|
|
1237
|
+
'pool',
|
|
1238
|
+
'lacrosse',
|
|
1239
|
+
'softball',
|
|
1240
|
+
'handball',
|
|
1241
|
+
'pingpong',
|
|
1242
|
+
'pong'
|
|
1243
|
+
],
|
|
1244
|
+
// A training word's other senses (AGL-3856): "train" is a railway's, "lift"
|
|
1245
|
+
// an elevator's or a ski lift's, "press" a newspaper's, "row" a boat's. The
|
|
1246
|
+
// beta.261 Synchronicity Gym's closing band, "Ready to train", took a
|
|
1247
|
+
// subway train at a station.
|
|
1248
|
+
shun: [
|
|
1249
|
+
'railway',
|
|
1250
|
+
'railroad',
|
|
1251
|
+
'rail',
|
|
1252
|
+
'locomotive',
|
|
1253
|
+
'subway',
|
|
1254
|
+
'metro',
|
|
1255
|
+
'tram',
|
|
1256
|
+
'tramway',
|
|
1257
|
+
'commuter',
|
|
1258
|
+
'freight',
|
|
1259
|
+
'transport',
|
|
1260
|
+
'transportation',
|
|
1261
|
+
'traffic',
|
|
1262
|
+
'vehicle',
|
|
1263
|
+
'bus',
|
|
1264
|
+
'truck',
|
|
1265
|
+
'airplane',
|
|
1266
|
+
'aircraft',
|
|
1267
|
+
'elevator',
|
|
1268
|
+
'escalator',
|
|
1269
|
+
'chairlift',
|
|
1270
|
+
'forklift',
|
|
1271
|
+
'crane',
|
|
1272
|
+
'newspaper',
|
|
1273
|
+
'journalism',
|
|
1274
|
+
'journalist',
|
|
1275
|
+
'printing',
|
|
1276
|
+
'boat',
|
|
1277
|
+
'ship',
|
|
1278
|
+
'canoe',
|
|
1279
|
+
'kayak',
|
|
1280
|
+
'sailboat'
|
|
1221
1281
|
]
|
|
1222
1282
|
},
|
|
1223
1283
|
{
|
|
@@ -1230,6 +1290,7 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1230
1290
|
'photo',
|
|
1231
1291
|
'photograph'
|
|
1232
1292
|
],
|
|
1293
|
+
scenes: true,
|
|
1233
1294
|
kin: [
|
|
1234
1295
|
'photographer',
|
|
1235
1296
|
'photography',
|
|
@@ -1415,7 +1476,7 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1415
1476
|
});
|
|
1416
1477
|
}
|
|
1417
1478
|
if (!broad.length) broad.push(business, craft);
|
|
1418
|
-
return {
|
|
1479
|
+
return _extends({
|
|
1419
1480
|
business,
|
|
1420
1481
|
craft,
|
|
1421
1482
|
domain: [
|
|
@@ -1426,7 +1487,10 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1426
1487
|
],
|
|
1427
1488
|
making: [
|
|
1428
1489
|
...new Set(makingSearches)
|
|
1429
|
-
]
|
|
1490
|
+
]
|
|
1491
|
+
}, groups.some((group)=>group.scenes) ? {
|
|
1492
|
+
scenes: true
|
|
1493
|
+
} : {}, {
|
|
1430
1494
|
named: [
|
|
1431
1495
|
...new Set(stemList(businessType))
|
|
1432
1496
|
],
|
|
@@ -1440,7 +1504,7 @@ const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
|
1440
1504
|
shunLead: [
|
|
1441
1505
|
...shunLead
|
|
1442
1506
|
]
|
|
1443
|
-
};
|
|
1507
|
+
});
|
|
1444
1508
|
}
|
|
1445
1509
|
/** A phrase's content words without its filler; all filler, and nothing is left. */ function subjectOf(list) {
|
|
1446
1510
|
return list.filter((word)=>!FILLER.has(word));
|
|
@@ -1487,6 +1551,221 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1487
1551
|
if (aiStorefrontSays('story', sectionName) || saysMadeByHand(slot.alt) || saysMadeByHand(sectionName)) return 'story';
|
|
1488
1552
|
return undefined;
|
|
1489
1553
|
}
|
|
1554
|
+
/**
|
|
1555
|
+
* The people a picture of a moment shows (AGL-3856): what its words name, the
|
|
1556
|
+
* search that asks for them, the words a photo of them leads with, those of
|
|
1557
|
+
* which it must name one anywhere, and what it never carries unless the
|
|
1558
|
+
* words name it. A family session is never a bride.
|
|
1559
|
+
*/ const PEOPLE_SCENES = [
|
|
1560
|
+
{
|
|
1561
|
+
words: [
|
|
1562
|
+
'family',
|
|
1563
|
+
'families',
|
|
1564
|
+
'kid',
|
|
1565
|
+
'kids',
|
|
1566
|
+
'child',
|
|
1567
|
+
'children',
|
|
1568
|
+
'newborn',
|
|
1569
|
+
'baby',
|
|
1570
|
+
'parent',
|
|
1571
|
+
'parents',
|
|
1572
|
+
'mother',
|
|
1573
|
+
'father'
|
|
1574
|
+
],
|
|
1575
|
+
query: ()=>'family',
|
|
1576
|
+
subject: 'family',
|
|
1577
|
+
lead: [
|
|
1578
|
+
'family',
|
|
1579
|
+
'families',
|
|
1580
|
+
'child',
|
|
1581
|
+
'children',
|
|
1582
|
+
'kid',
|
|
1583
|
+
'kids',
|
|
1584
|
+
'mother',
|
|
1585
|
+
'father',
|
|
1586
|
+
'parents',
|
|
1587
|
+
'daughter',
|
|
1588
|
+
'son',
|
|
1589
|
+
'baby',
|
|
1590
|
+
'toddler'
|
|
1591
|
+
],
|
|
1592
|
+
people: [
|
|
1593
|
+
'family',
|
|
1594
|
+
'child',
|
|
1595
|
+
'children',
|
|
1596
|
+
'kid',
|
|
1597
|
+
'kids',
|
|
1598
|
+
'mother',
|
|
1599
|
+
'father',
|
|
1600
|
+
'parent',
|
|
1601
|
+
'parents',
|
|
1602
|
+
'daughter',
|
|
1603
|
+
'son',
|
|
1604
|
+
'baby',
|
|
1605
|
+
'toddler',
|
|
1606
|
+
'mom',
|
|
1607
|
+
'dad'
|
|
1608
|
+
],
|
|
1609
|
+
shun: [
|
|
1610
|
+
'bride',
|
|
1611
|
+
'groom',
|
|
1612
|
+
'bridal',
|
|
1613
|
+
'wedding',
|
|
1614
|
+
'newlywed',
|
|
1615
|
+
'newlyweds',
|
|
1616
|
+
'marriage'
|
|
1617
|
+
]
|
|
1618
|
+
},
|
|
1619
|
+
{
|
|
1620
|
+
words: [
|
|
1621
|
+
'wedding',
|
|
1622
|
+
'weddings',
|
|
1623
|
+
'elopement',
|
|
1624
|
+
'elopements',
|
|
1625
|
+
'elope',
|
|
1626
|
+
'eloping',
|
|
1627
|
+
'bride',
|
|
1628
|
+
'groom',
|
|
1629
|
+
'engagement',
|
|
1630
|
+
'engaged',
|
|
1631
|
+
'couple',
|
|
1632
|
+
'couples',
|
|
1633
|
+
'newlywed',
|
|
1634
|
+
'newlyweds',
|
|
1635
|
+
'honeymoon'
|
|
1636
|
+
],
|
|
1637
|
+
query: (named)=>[
|
|
1638
|
+
'wedding',
|
|
1639
|
+
'bride',
|
|
1640
|
+
'groom'
|
|
1641
|
+
].some((word)=>named.has(word)) ? 'wedding couple' : 'couple',
|
|
1642
|
+
subject: 'couple',
|
|
1643
|
+
lead: [
|
|
1644
|
+
'couple',
|
|
1645
|
+
'couples',
|
|
1646
|
+
'bride',
|
|
1647
|
+
'groom',
|
|
1648
|
+
'wedding',
|
|
1649
|
+
'newlyweds',
|
|
1650
|
+
'lovers',
|
|
1651
|
+
'elopement',
|
|
1652
|
+
'bride and groom'
|
|
1653
|
+
],
|
|
1654
|
+
people: [
|
|
1655
|
+
'couple',
|
|
1656
|
+
'bride',
|
|
1657
|
+
'groom',
|
|
1658
|
+
'newlywed',
|
|
1659
|
+
'newlyweds',
|
|
1660
|
+
'lovers',
|
|
1661
|
+
'husband',
|
|
1662
|
+
'wife',
|
|
1663
|
+
'man',
|
|
1664
|
+
'woman'
|
|
1665
|
+
],
|
|
1666
|
+
shun: []
|
|
1667
|
+
}
|
|
1668
|
+
];
|
|
1669
|
+
/** Where a picture of a moment is set, by the words that name it, and the word a search and a photo say it with. */ const SCENE_SETTINGS = [
|
|
1670
|
+
{
|
|
1671
|
+
words: [
|
|
1672
|
+
'mountain',
|
|
1673
|
+
'mountains',
|
|
1674
|
+
'ridgetop',
|
|
1675
|
+
'ridge',
|
|
1676
|
+
'summit',
|
|
1677
|
+
'peak',
|
|
1678
|
+
'alpine',
|
|
1679
|
+
'overlook',
|
|
1680
|
+
'parkway'
|
|
1681
|
+
],
|
|
1682
|
+
said: 'mountains'
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
words: [
|
|
1686
|
+
'fall',
|
|
1687
|
+
'autumn',
|
|
1688
|
+
'foliage'
|
|
1689
|
+
],
|
|
1690
|
+
said: 'autumn'
|
|
1691
|
+
},
|
|
1692
|
+
{
|
|
1693
|
+
words: [
|
|
1694
|
+
'winter',
|
|
1695
|
+
'snow',
|
|
1696
|
+
'snowy'
|
|
1697
|
+
],
|
|
1698
|
+
said: 'winter'
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
words: [
|
|
1702
|
+
'beach',
|
|
1703
|
+
'coast',
|
|
1704
|
+
'seaside',
|
|
1705
|
+
'shore',
|
|
1706
|
+
'ocean'
|
|
1707
|
+
],
|
|
1708
|
+
said: 'beach'
|
|
1709
|
+
},
|
|
1710
|
+
{
|
|
1711
|
+
words: [
|
|
1712
|
+
'forest',
|
|
1713
|
+
'woods',
|
|
1714
|
+
'woodland'
|
|
1715
|
+
],
|
|
1716
|
+
said: 'forest'
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
words: [
|
|
1720
|
+
'spring',
|
|
1721
|
+
'blossom',
|
|
1722
|
+
'blossoms'
|
|
1723
|
+
],
|
|
1724
|
+
said: 'spring'
|
|
1725
|
+
},
|
|
1726
|
+
{
|
|
1727
|
+
words: [
|
|
1728
|
+
'city',
|
|
1729
|
+
'urban',
|
|
1730
|
+
'downtown'
|
|
1731
|
+
],
|
|
1732
|
+
said: 'city'
|
|
1733
|
+
}
|
|
1734
|
+
];
|
|
1735
|
+
/**
|
|
1736
|
+
* The scene a picture's words name (AGL-3856): the people at a moment, and
|
|
1737
|
+
* where — "Ridgetop Elopement" a couple in the mountains, "Mountain Wedding
|
|
1738
|
+
* Day" a wedding couple in the mountains, "Family Session in the Fall" a
|
|
1739
|
+
* family in autumn — read from every word, never only the first clause.
|
|
1740
|
+
* `null` where it names no people.
|
|
1741
|
+
*/ export function aiStockScene(text) {
|
|
1742
|
+
var _ref;
|
|
1743
|
+
var _SCENE_SETTINGS_find;
|
|
1744
|
+
const named = new Set(text.toLowerCase().split(/[^a-zÀ-ɏ]+/).filter(Boolean));
|
|
1745
|
+
const scene = PEOPLE_SCENES.find((entry)=>entry.words.some((word)=>named.has(word)));
|
|
1746
|
+
if (!scene) return null;
|
|
1747
|
+
const setting = (_ref = (_SCENE_SETTINGS_find = SCENE_SETTINGS.find((entry)=>entry.words.some((word)=>named.has(word)))) == null ? void 0 : _SCENE_SETTINGS_find.said) != null ? _ref : '';
|
|
1748
|
+
const query = scene.query(named);
|
|
1749
|
+
return {
|
|
1750
|
+
queries: [
|
|
1751
|
+
...new Set([
|
|
1752
|
+
setting ? `${query} ${setting}` : '',
|
|
1753
|
+
query
|
|
1754
|
+
].filter(Boolean))
|
|
1755
|
+
],
|
|
1756
|
+
subject: [
|
|
1757
|
+
scene.subject,
|
|
1758
|
+
setting
|
|
1759
|
+
].filter(Boolean).join(' '),
|
|
1760
|
+
object: scene.subject,
|
|
1761
|
+
lead: scene.lead.map((phrase)=>stemList(phrase).join(' ')),
|
|
1762
|
+
people: scene.people.map(aiStockStem),
|
|
1763
|
+
shun: scene.shun.filter((word)=>!named.has(word)).map(aiStockStem),
|
|
1764
|
+
named: [
|
|
1765
|
+
...new Set(stemList(text))
|
|
1766
|
+
]
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1490
1769
|
/** An object's kin phrases as stems, or none. */ const kinStems = (entry)=>entry ? [
|
|
1491
1770
|
...new Set(entry.kin.map((phrase)=>stemList(phrase).join(' ')))
|
|
1492
1771
|
] : [];
|
|
@@ -1709,7 +1988,7 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1709
1988
|
return searches;
|
|
1710
1989
|
}
|
|
1711
1990
|
/** The searches a slot tries, in order, most specific first, each distinct. */ export function aiStockSearchesFor(slot, terms, subject, part) {
|
|
1712
|
-
var _terms_core, _terms_making;
|
|
1991
|
+
var _terms_core, _terms_making, _ref;
|
|
1713
1992
|
const orientation = aiStockOrientation(slot.aspect);
|
|
1714
1993
|
const size = slot.role === 'hero' ? {
|
|
1715
1994
|
minWidth: 1600
|
|
@@ -1750,6 +2029,8 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1750
2029
|
broad: true,
|
|
1751
2030
|
category: true
|
|
1752
2031
|
}));
|
|
2032
|
+
// A scene's people are read from every word of the picture's, never its first clause alone.
|
|
2033
|
+
const scene = terms.scenes && slot.role !== 'hero' && part !== 'collection' ? aiStockScene(slot.alt) : null;
|
|
1753
2034
|
const thing = subject ? [
|
|
1754
2035
|
{
|
|
1755
2036
|
query: qualify(subject),
|
|
@@ -1787,11 +2068,31 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1787
2068
|
...broad
|
|
1788
2069
|
] : [
|
|
1789
2070
|
...part === 'story' ? making : [],
|
|
1790
|
-
...thing,
|
|
2071
|
+
...scene ? [] : thing,
|
|
1791
2072
|
...broad
|
|
1792
2073
|
];
|
|
1793
2074
|
const seen = new Set();
|
|
1794
2075
|
const searches = [];
|
|
2076
|
+
// A picture of people at a moment asks for them, and where, before anything
|
|
2077
|
+
// else, and takes only a photo leading with them (AGL-3856): never the
|
|
2078
|
+
// roses of a "Mountain Wedding Day", nor a bride for a family session.
|
|
2079
|
+
for (const query of (_ref = scene == null ? void 0 : scene.queries) != null ? _ref : []){
|
|
2080
|
+
seen.add(`${query}|false`);
|
|
2081
|
+
searches.push(_extends({
|
|
2082
|
+
query,
|
|
2083
|
+
orientation
|
|
2084
|
+
}, size, {
|
|
2085
|
+
strict: true,
|
|
2086
|
+
subject: scene.subject,
|
|
2087
|
+
object: scene.object,
|
|
2088
|
+
kin: scene.lead,
|
|
2089
|
+
lead: true,
|
|
2090
|
+
needs: scene.people,
|
|
2091
|
+
allow: scene.named
|
|
2092
|
+
}, scene.shun.length ? {
|
|
2093
|
+
refuse: scene.shun
|
|
2094
|
+
} : {}));
|
|
2095
|
+
}
|
|
1795
2096
|
for (const raw of queries){
|
|
1796
2097
|
const query = clip(raw.query);
|
|
1797
2098
|
const key = `${query}|${raw.people === true}`;
|
|
@@ -1896,7 +2197,7 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1896
2197
|
* the subject's two-word phrase 3, each of its other words 1, and the
|
|
1897
2198
|
* site's world 1, plus a quarter when it is among the first tags.
|
|
1898
2199
|
*/ export function aiStockRelevance(photo, judgement) {
|
|
1899
|
-
var _judgement_rivals, _judgement_subject, _judgement_named, _judgement_shun, _judgement_shunLead, _judgement_leadAny, _judgement_kin, _judgement_requires, _judgement_category, _judgement_object, _judgement_domain;
|
|
2200
|
+
var _judgement_rivals, _judgement_subject, _judgement_named, _judgement_shun, _judgement_refuse, _judgement_needs, _judgement_shunLead, _judgement_leadAny, _judgement_kin, _judgement_requires, _judgement_category, _judgement_object, _judgement_domain;
|
|
1900
2201
|
const hit = hitWords(photo);
|
|
1901
2202
|
if (hit.rejected) return 0;
|
|
1902
2203
|
if (aiStockSensitive(photo, judgement.named)) return 0;
|
|
@@ -1910,6 +2211,11 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
1910
2211
|
]);
|
|
1911
2212
|
// A dispenser is not a soapmaker's, nor a pump a bar's (AGL-3660).
|
|
1912
2213
|
if (((_judgement_shun = judgement.shun) != null ? _judgement_shun : []).some((word)=>hit.all.has(word) && !owned.has(word))) return 0;
|
|
2214
|
+
// A family session is never a bride, however the photographer's brief names weddings.
|
|
2215
|
+
if (((_judgement_refuse = judgement.refuse) != null ? _judgement_refuse : []).some((word)=>hit.all.has(word))) return 0;
|
|
2216
|
+
// A wedding day shows its people: a close-up of roses tagged "wedding" never fills it.
|
|
2217
|
+
const needs = (_judgement_needs = judgement.needs) != null ? _judgement_needs : [];
|
|
2218
|
+
if (needs.length && !needs.some((word)=>hit.all.has(word))) return 0;
|
|
1913
2219
|
// What the photo is OF: a typewriter's terms of service are not a law firm's.
|
|
1914
2220
|
if (((_judgement_shunLead = judgement.shunLead) != null ? _judgement_shunLead : []).some((word)=>hit.lead.has(word) && !owned.has(word))) return 0;
|
|
1915
2221
|
if (judgement.product) {
|
|
@@ -2069,60 +2375,166 @@ function jobPhotos(key) {
|
|
|
2069
2375
|
/**
|
|
2070
2376
|
* Words a tag uses for how a photo looks or feels, never a thing it shows
|
|
2071
2377
|
* (AGL-3856): "extravagant" of "wedding dress, bride, extravagant".
|
|
2072
|
-
*/ const DESCRIBING = words('love romance romantic luxury luxurious fancy extravagant happiness happy beauty emotion emotions mood lifestyle ' + 'concept aesthetic wallpaper background retro vintage antique old young cute sexy fun funny sad positive healthy fit ' + 'strong powerful homemade tasty yummy sweet sweetness nice dark bw monochrome macro sporty active married bridal ' + 'female male');
|
|
2073
|
-
/**
|
|
2378
|
+
*/ const DESCRIBING = words('love romance romantic luxury luxurious fancy extravagant happiness happy beauty emotion emotions mood lifestyle ' + 'concept aesthetic wallpaper background retro vintage antique old young cute sexy fun funny sad positive negative healthy fit ' + 'strong powerful homemade tasty yummy sweet sweetness nice dark bw monochrome macro sporty active married bridal ' + 'female male adult good bad poc bipoc');
|
|
2379
|
+
/**
|
|
2380
|
+
* Words a tag uses for what a person or a thing is like, said before it
|
|
2381
|
+
* rather than as a thing of its own (AGL-3856): "a confident lawyer", never
|
|
2382
|
+
* "a lawyer, law and a confident".
|
|
2383
|
+
*/ const QUALITIES = words('confident professional successful serious smart busy creative proud skilled experienced determined focused ' + 'senior junior expert friendly cheerful smiling');
|
|
2384
|
+
/** What a tag names that takes no article: "chalk" of "board, chalk". */ const MASS_NOUNS = words('food coffee tea bread wood water fitness wax soap clay nature money fabric yarn wool furniture jewelry jewellery ' + 'pottery glass paper music art sport hair makeup chalk paint ink dust stone marble concrete steel metal ' + 'skincare equipment decor fashion wildlife scenery weather traffic wine beer chocolate rice sugar flour milk ' + 'cheese honey oil ice fire light sunlight dough sourdough pastry dessert crossfit people foliage greenery ' + 'autumn winter spring summer');
|
|
2385
|
+
/**
|
|
2386
|
+
* What a tag names that no photo shows as a thing of its own (AGL-3856): "law"
|
|
2387
|
+
* of "lawyer, law", "feedback" of "board, chalk, feedback". Left out, never
|
|
2388
|
+
* said with an article.
|
|
2389
|
+
*/ const ABSTRACT_NOUNS = words('law justice advocacy business feedback review news return communication communicate discussion dialog conversation ' + 'success career work job satisfaction quality concept idea strategy marketing education technology health support ' + 'confirmation opinion rating evaluation planning project presentation optimization information internet finance ' + 'management leadership teamwork motivation growth strength service services help advice consulting consultation ' + 'marriage photography architecture travel transport transportation industry company corporate social e-business');
|
|
2390
|
+
/** Stopwords a description still says, as the people a photo shows: "a family", "a person". */ const SAID_PEOPLE = words('people person family');
|
|
2074
2391
|
/** Words ending in "-ing" that are things, and take an article: "a wedding", "a ring". */ const COUNTED_ING = words('wedding ring earring building painting drawing ceiling string swing king sibling wing');
|
|
2392
|
+
/** People a photo shows; the generic ones give way to a role ("man" to "businessman"). */ const PEOPLE_NOUNS = words('man men woman women person people boy girl guy lady child children kid kids baby family couple bride groom ' + 'businessman businesswoman businessmen lawyer attorney doctor dentist nurse chef cook baker barista athlete ' + 'trainer coach student students teacher worker entrepreneur model photographer potter artist florist mother ' + 'father parent parents grandmother grandfather');
|
|
2393
|
+
const GENERIC_PEOPLE = words('man men woman women person people guy lady adult');
|
|
2394
|
+
/**
|
|
2395
|
+
* Places a photo is set in, each with how a phrase says it is there: "a
|
|
2396
|
+
* train at a station", "a lawyer in court".
|
|
2397
|
+
*/ const PLACES = {
|
|
2398
|
+
station: 'at',
|
|
2399
|
+
market: 'at',
|
|
2400
|
+
desk: 'at',
|
|
2401
|
+
table: 'at',
|
|
2402
|
+
counter: 'at',
|
|
2403
|
+
beach: 'on',
|
|
2404
|
+
court: 'in',
|
|
2405
|
+
courtroom: 'in',
|
|
2406
|
+
office: 'in',
|
|
2407
|
+
kitchen: 'in',
|
|
2408
|
+
gym: 'in',
|
|
2409
|
+
studio: 'in',
|
|
2410
|
+
classroom: 'in',
|
|
2411
|
+
room: 'in',
|
|
2412
|
+
garden: 'in',
|
|
2413
|
+
park: 'in',
|
|
2414
|
+
shop: 'in',
|
|
2415
|
+
store: 'in',
|
|
2416
|
+
bakery: 'in',
|
|
2417
|
+
cafe: 'in',
|
|
2418
|
+
restaurant: 'in',
|
|
2419
|
+
workshop: 'in',
|
|
2420
|
+
library: 'in',
|
|
2421
|
+
salon: 'in',
|
|
2422
|
+
clinic: 'in',
|
|
2423
|
+
forest: 'in',
|
|
2424
|
+
city: 'in',
|
|
2425
|
+
church: 'in',
|
|
2426
|
+
field: 'in'
|
|
2427
|
+
};
|
|
2428
|
+
/** Places said without an article: "in court". */ const BARE_PLACES = words('court');
|
|
2075
2429
|
/**
|
|
2076
2430
|
* A tag as a phrase of an English description (AGL-3856): "a wedding dress",
|
|
2077
|
-
* "an attorney", "books", "
|
|
2078
|
-
* thing ("extravagant", "beautiful") or is too long to be one.
|
|
2431
|
+
* "an attorney", "books", "chalk", "Columbus"; `null` for a tag that names no
|
|
2432
|
+
* thing ("extravagant", "beautiful", "feedback") or is too long to be one.
|
|
2079
2433
|
*/ function describedTag(tag, proper) {
|
|
2080
|
-
const describing = (word)=>FILLER.has(word) || DESCRIBING.has(word) || /(?:ous|ful)$/.test(word) || word.length > 4 && /[^e]ed$/.test(word);
|
|
2434
|
+
const describing = (word)=>FILLER.has(word) || DESCRIBING.has(word) || QUALITIES.has(word) || /(?:ous|ful)$/.test(word) || word.length > 4 && /[^e]ed$/.test(word);
|
|
2081
2435
|
const all = tag.toLowerCase().replace(/[^a-zÀ-ɏ\s'-]/g, ' ').split(/\s+/).filter(Boolean);
|
|
2082
2436
|
// "Beautiful flowers" shows flowers; "roasted" shows nothing.
|
|
2083
2437
|
const list = all.filter((word)=>!describing(word));
|
|
2084
2438
|
if (!list.length || all.length > 3) return null;
|
|
2085
2439
|
// A phrase of no thing ("up close") or a doing ("take pictures", "to lift", "work out") is not what it shows.
|
|
2086
|
-
if (list.every((word)=>STOPWORDS.has(word) && word
|
|
2440
|
+
if (list.every((word)=>STOPWORDS.has(word) && !SAID_PEOPLE.has(word))) return null;
|
|
2087
2441
|
if (/^(?:to|take|taking|make|making|get|do|go|lie)$/.test(list[0])) return null;
|
|
2088
2442
|
if (/^(?:out|up|off|down|away|on|in)$/.test(list[list.length - 1])) return null;
|
|
2089
2443
|
if (list.every((word)=>proper.has(word))) return list.map((word)=>`${word.charAt(0).toUpperCase()}${word.slice(1)}`).join(' ');
|
|
2090
|
-
const phrase = list.join(' ');
|
|
2091
2444
|
const last = list[list.length - 1];
|
|
2445
|
+
// An idea, never a thing: "law", "feedback", "customer satisfaction".
|
|
2446
|
+
if (ABSTRACT_NOUNS.has(last)) return null;
|
|
2447
|
+
const phrase = list.join(' ');
|
|
2092
2448
|
const plural = aiStockStem(last) !== last && !/^(?:lens|canvas|atlas|gas|bus)$/.test(last);
|
|
2093
2449
|
const uncounted = MASS_NOUNS.has(last) || last.endsWith('ing') && !COUNTED_ING.has(last);
|
|
2094
|
-
if (plural || uncounted || STOPWORDS.has(list[0]) && list[0]
|
|
2095
|
-
return `${
|
|
2450
|
+
if (plural || uncounted || STOPWORDS.has(list[0]) && !SAID_PEOPLE.has(list[0])) return phrase;
|
|
2451
|
+
return `${articleFor(phrase)} ${phrase}`;
|
|
2452
|
+
}
|
|
2453
|
+
/** "a" or "an" before a phrase. */ const articleFor = (phrase)=>/^(?:[aeio]|u(?!ni|s[eu]))/.test(phrase) ? 'an' : 'a';
|
|
2454
|
+
/** Whether two words name one thing, one inside the other: "law" and "lawyer", "man" and "businessman". */ function nearSynonyms(a, b) {
|
|
2455
|
+
const [short, long] = a.length <= b.length ? [
|
|
2456
|
+
a,
|
|
2457
|
+
b
|
|
2458
|
+
] : [
|
|
2459
|
+
b,
|
|
2460
|
+
a
|
|
2461
|
+
];
|
|
2462
|
+
return short.length >= 3 && short !== long && (long.startsWith(short) || long.endsWith(short));
|
|
2096
2463
|
}
|
|
2097
2464
|
/**
|
|
2098
|
-
* A photo described from its own tags (AGL-3856):
|
|
2099
|
-
*
|
|
2100
|
-
*
|
|
2101
|
-
*
|
|
2102
|
-
*
|
|
2465
|
+
* A photo described from its own tags (AGL-3856): a short English phrase of
|
|
2466
|
+
* what its first tags show — one or two things, or a thing and where it is,
|
|
2467
|
+
* one person at most — never the library's comma-separated list: "A train at
|
|
2468
|
+
* a station", "A confident lawyer in court", "A portrait of a businessman",
|
|
2469
|
+
* "A board and chalk". A tag of how it looks is said before the thing it
|
|
2470
|
+
* qualifies; an idea ("law", "feedback") is left out; a word inside another
|
|
2471
|
+
* ("law" of "lawyer", "man" of "businessman") gives way to it; a mass noun
|
|
2472
|
+
* takes no article. `null` where no tag names a thing.
|
|
2103
2473
|
*/ export function aiStockTagsAlt(tags, proper = new Set()) {
|
|
2104
|
-
|
|
2474
|
+
var _people_find;
|
|
2475
|
+
const parts = [];
|
|
2476
|
+
let quality = '';
|
|
2477
|
+
let portrait = false;
|
|
2105
2478
|
for (const tag of tags.slice(0, 6)){
|
|
2106
|
-
|
|
2479
|
+
var _ref;
|
|
2480
|
+
var _bare_split_pop;
|
|
2481
|
+
const lower = tag.toLowerCase().trim();
|
|
2482
|
+
if (lower === 'portrait' || lower === 'portraits') {
|
|
2483
|
+
portrait = true;
|
|
2484
|
+
continue;
|
|
2485
|
+
}
|
|
2486
|
+
if (QUALITIES.has(lower)) {
|
|
2487
|
+
quality || (quality = lower);
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2107
2490
|
const said = describedTag(tag, proper);
|
|
2108
2491
|
if (!said) continue;
|
|
2109
|
-
const
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2492
|
+
const bare = said.replace(/^an?\s+/, '');
|
|
2493
|
+
const stems = stemList(bare);
|
|
2494
|
+
const head = (_ref = (_bare_split_pop = bare.split(/\s+/).pop()) == null ? void 0 : _bare_split_pop.toLowerCase()) != null ? _ref : '';
|
|
2495
|
+
if (!head) continue;
|
|
2496
|
+
const kind = PEOPLE_NOUNS.has(head) ? 'person' : PLACES[head] ? 'place' : 'thing';
|
|
2497
|
+
if (parts.some((part)=>stems.every((stem)=>part.stems.includes(stem)))) continue;
|
|
2498
|
+
// A longer phrase, or a word holding another, takes its place: "wedding dress" for "wedding", "lawyer" for "law".
|
|
2499
|
+
const within = parts.findIndex((part)=>part.stems.every((stem)=>stems.includes(stem)) || nearSynonyms(part.head, head));
|
|
2500
|
+
const part = {
|
|
2501
|
+
said,
|
|
2114
2502
|
stems,
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2503
|
+
head,
|
|
2504
|
+
kind
|
|
2505
|
+
};
|
|
2506
|
+
if (within >= 0) {
|
|
2507
|
+
const held = parts[within];
|
|
2508
|
+
const fuller = nearSynonyms(held.head, head) ? head.length > held.head.length : stems.length > held.stems.length;
|
|
2509
|
+
if (fuller) parts.splice(within, 1, part);
|
|
2510
|
+
continue;
|
|
2511
|
+
}
|
|
2512
|
+
parts.push(part);
|
|
2513
|
+
}
|
|
2514
|
+
// One person: a role over a man or a woman ("businessman" over "man"), else the first.
|
|
2515
|
+
const people = parts.filter((part)=>part.kind === 'person');
|
|
2516
|
+
const person = (_people_find = people.find((part)=>!GENERIC_PEOPLE.has(part.head))) != null ? _people_find : people[0];
|
|
2517
|
+
const place = parts.find((part)=>part.kind === 'place');
|
|
2518
|
+
const things = parts.filter((part)=>part.kind === 'thing');
|
|
2519
|
+
const shown = (person ? [
|
|
2520
|
+
person
|
|
2521
|
+
] : []).concat(things);
|
|
2522
|
+
if (!shown.length && !place) return null;
|
|
2523
|
+
let phrase;
|
|
2524
|
+
if (portrait && person) phrase = `a portrait of ${person.said}`;
|
|
2525
|
+
else {
|
|
2526
|
+
const chosen = shown.sort((a, b)=>parts.indexOf(a) - parts.indexOf(b)).slice(0, place ? 1 : 2).map((part)=>part.said);
|
|
2527
|
+
// A quality is said before a single counted thing: "a confident lawyer".
|
|
2528
|
+
if (quality && chosen[0] && /^an? \S+$/.test(chosen[0])) chosen[0] = `${articleFor(quality)} ${quality} ${chosen[0].replace(/^an?\s+/, '')}`;
|
|
2529
|
+
phrase = chosen.join(' and ');
|
|
2530
|
+
}
|
|
2531
|
+
if (place) {
|
|
2532
|
+
var _PLACES_place_head;
|
|
2533
|
+
const preposition = (_PLACES_place_head = PLACES[place.head]) != null ? _PLACES_place_head : 'in';
|
|
2534
|
+
const where = BARE_PLACES.has(place.head) && /^an? \S+$/.test(place.said) ? place.head : place.said;
|
|
2535
|
+
phrase = phrase ? `${phrase} ${preposition} ${where}` : where;
|
|
2121
2536
|
}
|
|
2122
|
-
|
|
2123
|
-
const said = kept.map((entry)=>entry.said);
|
|
2124
|
-
const joined = said.length > 1 ? `${said.slice(0, -1).join(', ')} and ${said[said.length - 1]}` : said[0];
|
|
2125
|
-
const out = `${joined.charAt(0).toUpperCase()}${joined.slice(1)}`;
|
|
2537
|
+
const out = `${phrase.charAt(0).toUpperCase()}${phrase.slice(1)}`;
|
|
2126
2538
|
return out.length > AI_STOCK_ALT_MAX ? out.slice(0, AI_STOCK_ALT_MAX).replace(/[\s,]+\S*$/, '') : out;
|
|
2127
2539
|
}
|
|
2128
2540
|
/** The thing a description names: its subject's object, a trailing "speaking calmly" or "dusted" dropped. */ function describedObject(text, sectionName) {
|
|
@@ -2155,12 +2567,13 @@ function jobPhotos(key) {
|
|
|
2155
2567
|
* description, and are never kept. Otherwise the photo is described by the
|
|
2156
2568
|
* library's own words: its description where it writes one (a Pexels hit's
|
|
2157
2569
|
* `alt`), else its first tags as an English phrase ({@link aiStockTagsAlt}),
|
|
2158
|
-
* never the library's tag list
|
|
2570
|
+
* never the library's tag list, and where no tag names a thing, the slot's
|
|
2571
|
+
* own subject: its words, else its section's name. The libraries write in English, and no model
|
|
2159
2572
|
* translates them, so a site in another language takes the platform's own
|
|
2160
2573
|
* words for an illustrative photo in its language (`aiLayoutLabel`), true of
|
|
2161
2574
|
* any photo, as does a hit whose words name no thing.
|
|
2162
2575
|
*/ export function aiStockPhotoAlt(photo, slot, input = {}) {
|
|
2163
|
-
var _photo_alt, _aiStockTagsAlt, _photo_tags;
|
|
2576
|
+
var _photo_alt, _input_sectionName, _aiStockTagsAlt, _photo_tags;
|
|
2164
2577
|
if (aiLayoutSpeaksOtherThanEnglish(input.language)) return aiLayoutLabel('illustrativePhoto', input.language);
|
|
2165
2578
|
if (!slot.standIn) {
|
|
2166
2579
|
var _photo_tags1, _ref;
|
|
@@ -2177,7 +2590,13 @@ function jobPhotos(key) {
|
|
|
2177
2590
|
}
|
|
2178
2591
|
const own = ((_photo_alt = photo.alt) != null ? _photo_alt : '').replace(/\s+/g, ' ').trim();
|
|
2179
2592
|
if (own) return own.length > AI_STOCK_ALT_MAX ? `${own.slice(0, AI_STOCK_ALT_MAX).replace(/\s+\S*$/, '')}…` : own;
|
|
2180
|
-
|
|
2593
|
+
// No tag names a thing: the slot's own subject, as its words or its section's name say it, never a tag list.
|
|
2594
|
+
const subject = [
|
|
2595
|
+
slot.alt,
|
|
2596
|
+
(_input_sectionName = input.sectionName) != null ? _input_sectionName : ''
|
|
2597
|
+
].map((text)=>text.replace(/\s+/g, ' ').trim()).find((text)=>/[A-Za-zÀ-ɏ]/.test(text));
|
|
2598
|
+
const fallback = subject ? `${subject.charAt(0).toUpperCase()}${subject.slice(1)}`.slice(0, AI_STOCK_ALT_MAX) : '';
|
|
2599
|
+
return (_aiStockTagsAlt = aiStockTagsAlt((_photo_tags = photo.tags) != null ? _photo_tags : [], input.proper)) != null ? _aiStockTagsAlt : fallback || aiLayoutLabel('illustrativePhoto', input.language);
|
|
2181
2600
|
}
|
|
2182
2601
|
/** The names a business type writes with a capital, lowercased: "columbus", "ohio" (AGL-3856). */ export function aiStockProperWords(businessType) {
|
|
2183
2602
|
const found = new Set();
|
|
@@ -2190,19 +2609,33 @@ const EXTENSIONS = {
|
|
|
2190
2609
|
'image/webp': 'webp'
|
|
2191
2610
|
};
|
|
2192
2611
|
/**
|
|
2193
|
-
* A job's language and English photo words (AGL-3760),
|
|
2194
|
-
*
|
|
2612
|
+
* A job's language and English photo words (AGL-3760), the English name of
|
|
2613
|
+
* its kind of site (AGL-3771), and the business's name and audience as the
|
|
2614
|
+
* person typed them (AGL-3856), as a stock photo source takes them.
|
|
2195
2615
|
*/ export function aiStockPhotoWordsOf(job) {
|
|
2196
2616
|
const plan = job.plan;
|
|
2197
2617
|
const kind = job.inputs ? aiSiteKindOfInputs(job.inputs) : null;
|
|
2198
2618
|
// "Restaurant & café" searches as "restaurant cafe".
|
|
2199
2619
|
const kindWords = kind ? kind.label.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/&/g, ' ').replace(/\s+/g, ' ').trim().toLowerCase() : '';
|
|
2620
|
+
const said = (key)=>{
|
|
2621
|
+
var _job_inputs;
|
|
2622
|
+
const value = (_job_inputs = job.inputs) == null ? void 0 : _job_inputs[key];
|
|
2623
|
+
return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
|
|
2624
|
+
};
|
|
2625
|
+
const name = said('businessName');
|
|
2626
|
+
const audience = said('audience');
|
|
2200
2627
|
return _extends({}, (plan == null ? void 0 : plan.language) ? {
|
|
2201
2628
|
language: plan.language
|
|
2202
2629
|
} : {}, (plan == null ? void 0 : plan.photoWords) ? {
|
|
2203
2630
|
photoWords: plan.photoWords
|
|
2204
2631
|
} : {}, kindWords ? {
|
|
2205
2632
|
kindWords
|
|
2633
|
+
} : {}, kind ? {
|
|
2634
|
+
kind: kind.id
|
|
2635
|
+
} : {}, name ? {
|
|
2636
|
+
name
|
|
2637
|
+
} : {}, audience ? {
|
|
2638
|
+
audience
|
|
2206
2639
|
} : {});
|
|
2207
2640
|
}
|
|
2208
2641
|
/**
|
|
@@ -2231,7 +2664,559 @@ const EXTENSIONS = {
|
|
|
2231
2664
|
* every slot of every source — hero, background, gallery, card, product,
|
|
2232
2665
|
* post — so no slot searches by words another slot is held against.
|
|
2233
2666
|
*/ export function aiStockSourceTerms(input) {
|
|
2234
|
-
|
|
2667
|
+
var _input_name, _input_audience, _input_name1, _input_audience1, _input_kind;
|
|
2668
|
+
const english = aiStockSourceSubject(input);
|
|
2669
|
+
const terms = aiStockSiteTerms(english || input.business);
|
|
2670
|
+
if (english || terms.domain.length && !aiStockIsAbbreviation(input.business)) return terms;
|
|
2671
|
+
// A business type that names no world ("a local service business"), or
|
|
2672
|
+
// one the libraries do not know ("LMS"), is searched by the craft its
|
|
2673
|
+
// name, else its audience, names (AGL-3856): the beta.261 Synchronicity Gym
|
|
2674
|
+
// hero searched nothing at all and was left a black scrim, and its closing
|
|
2675
|
+
// band, held to no world, took a subway train for "Ready to train". Then by
|
|
2676
|
+
// the kind of site its name says ("Adult Hybrid Learning Center"), and
|
|
2677
|
+
// last by the kind of site the person picked: the beta.262 Adult Hybrid
|
|
2678
|
+
// Learning Center searched "lms" and shipped no photo at all.
|
|
2679
|
+
const craft = aiStockListedCraft((_input_name = input.name) != null ? _input_name : '') || aiStockListedCraft((_input_audience = input.audience) != null ? _input_audience : '');
|
|
2680
|
+
const kind = craft ? '' : aiStockNamedKind((_input_name1 = input.name) != null ? _input_name1 : '') || aiStockNamedKind((_input_audience1 = input.audience) != null ? _input_audience1 : '') || ((_input_kind = input.kind) != null ? _input_kind : '');
|
|
2681
|
+
const found = craft ? aiStockSiteTerms(craft) : aiStockKindTerms(kind);
|
|
2682
|
+
if (!found) return terms;
|
|
2683
|
+
return _extends({}, found, {
|
|
2684
|
+
named: [
|
|
2685
|
+
...new Set([
|
|
2686
|
+
...terms.named,
|
|
2687
|
+
...found.named
|
|
2688
|
+
])
|
|
2689
|
+
]
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
/**
|
|
2693
|
+
* Whether a business type is only an abbreviation the libraries do not know
|
|
2694
|
+
* (AGL-3856): "LMS", "CRM", "B2B". Its letters are no world to search.
|
|
2695
|
+
*/ export function aiStockIsAbbreviation(businessType) {
|
|
2696
|
+
const list = businessType.trim().split(/\s+/).filter(Boolean);
|
|
2697
|
+
return list.length > 0 && list.length <= 2 && list.every((word)=>/^[A-Z0-9&/.-]{2,6}s?$/.test(word) && /[A-Z]/.test(word));
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* What a picture of each kind of site the guided start offers shows, where
|
|
2701
|
+
* nothing else says (AGL-3856): the words it is searched by, the words a
|
|
2702
|
+
* photo of it is tagged with, and its broad searches. A kind whose subject
|
|
2703
|
+
* is a craft {@link CRAFT_KIN} lists takes that craft's own.
|
|
2704
|
+
*/ const KIND_SUBJECTS = {
|
|
2705
|
+
business: {
|
|
2706
|
+
subject: 'small business',
|
|
2707
|
+
kin: [
|
|
2708
|
+
'business',
|
|
2709
|
+
'office',
|
|
2710
|
+
'team',
|
|
2711
|
+
'meeting',
|
|
2712
|
+
'workplace',
|
|
2713
|
+
'coworkers',
|
|
2714
|
+
'entrepreneur',
|
|
2715
|
+
'shop',
|
|
2716
|
+
'service',
|
|
2717
|
+
'customer'
|
|
2718
|
+
],
|
|
2719
|
+
broad: [
|
|
2720
|
+
'small business owner',
|
|
2721
|
+
'team meeting office'
|
|
2722
|
+
]
|
|
2723
|
+
},
|
|
2724
|
+
trades: {
|
|
2725
|
+
subject: 'contractor',
|
|
2726
|
+
kin: [
|
|
2727
|
+
'contractor',
|
|
2728
|
+
'construction',
|
|
2729
|
+
'repair',
|
|
2730
|
+
'renovation',
|
|
2731
|
+
'tools',
|
|
2732
|
+
'worker',
|
|
2733
|
+
'handyman',
|
|
2734
|
+
'plumber',
|
|
2735
|
+
'electrician',
|
|
2736
|
+
'house',
|
|
2737
|
+
'roof'
|
|
2738
|
+
],
|
|
2739
|
+
broad: [
|
|
2740
|
+
'home repair contractor',
|
|
2741
|
+
'construction worker tools'
|
|
2742
|
+
]
|
|
2743
|
+
},
|
|
2744
|
+
professional: {
|
|
2745
|
+
subject: 'consultant',
|
|
2746
|
+
kin: [
|
|
2747
|
+
'consultant',
|
|
2748
|
+
'consulting',
|
|
2749
|
+
'office',
|
|
2750
|
+
'meeting',
|
|
2751
|
+
'client',
|
|
2752
|
+
'advisor',
|
|
2753
|
+
'finance',
|
|
2754
|
+
'accountant',
|
|
2755
|
+
'lawyer',
|
|
2756
|
+
'desk',
|
|
2757
|
+
'business'
|
|
2758
|
+
],
|
|
2759
|
+
broad: [
|
|
2760
|
+
'consultant client meeting',
|
|
2761
|
+
'professional office'
|
|
2762
|
+
]
|
|
2763
|
+
},
|
|
2764
|
+
wellness: {
|
|
2765
|
+
subject: 'wellness',
|
|
2766
|
+
kin: [
|
|
2767
|
+
'wellness',
|
|
2768
|
+
'health',
|
|
2769
|
+
'therapy',
|
|
2770
|
+
'therapist',
|
|
2771
|
+
'massage',
|
|
2772
|
+
'spa',
|
|
2773
|
+
'relaxation',
|
|
2774
|
+
'clinic',
|
|
2775
|
+
'healthcare'
|
|
2776
|
+
],
|
|
2777
|
+
broad: [
|
|
2778
|
+
'wellness therapy',
|
|
2779
|
+
'massage therapy'
|
|
2780
|
+
]
|
|
2781
|
+
},
|
|
2782
|
+
restaurant: {
|
|
2783
|
+
subject: 'restaurant',
|
|
2784
|
+
kin: [
|
|
2785
|
+
'restaurant',
|
|
2786
|
+
'dining',
|
|
2787
|
+
'food',
|
|
2788
|
+
'dish',
|
|
2789
|
+
'chef',
|
|
2790
|
+
'meal',
|
|
2791
|
+
'cafe',
|
|
2792
|
+
'cuisine',
|
|
2793
|
+
'dinner',
|
|
2794
|
+
'lunch'
|
|
2795
|
+
],
|
|
2796
|
+
broad: [
|
|
2797
|
+
'restaurant dining',
|
|
2798
|
+
'restaurant food'
|
|
2799
|
+
]
|
|
2800
|
+
},
|
|
2801
|
+
store: {
|
|
2802
|
+
subject: 'boutique',
|
|
2803
|
+
kin: [
|
|
2804
|
+
'boutique',
|
|
2805
|
+
'shop',
|
|
2806
|
+
'store',
|
|
2807
|
+
'shopping',
|
|
2808
|
+
'retail',
|
|
2809
|
+
'products',
|
|
2810
|
+
'display',
|
|
2811
|
+
'shelf'
|
|
2812
|
+
],
|
|
2813
|
+
broad: [
|
|
2814
|
+
'boutique shop',
|
|
2815
|
+
'retail store display'
|
|
2816
|
+
]
|
|
2817
|
+
},
|
|
2818
|
+
portfolio: {
|
|
2819
|
+
subject: 'artist',
|
|
2820
|
+
kin: [
|
|
2821
|
+
'art',
|
|
2822
|
+
'artist',
|
|
2823
|
+
'design',
|
|
2824
|
+
'creative',
|
|
2825
|
+
'studio',
|
|
2826
|
+
'workspace',
|
|
2827
|
+
'painting',
|
|
2828
|
+
'drawing'
|
|
2829
|
+
],
|
|
2830
|
+
broad: [
|
|
2831
|
+
'artist studio',
|
|
2832
|
+
'creative workspace'
|
|
2833
|
+
]
|
|
2834
|
+
},
|
|
2835
|
+
studio: {
|
|
2836
|
+
subject: 'design studio',
|
|
2837
|
+
kin: [
|
|
2838
|
+
'design',
|
|
2839
|
+
'designer',
|
|
2840
|
+
'studio',
|
|
2841
|
+
'creative',
|
|
2842
|
+
'agency',
|
|
2843
|
+
'team',
|
|
2844
|
+
'workspace',
|
|
2845
|
+
'office'
|
|
2846
|
+
],
|
|
2847
|
+
broad: [
|
|
2848
|
+
'design studio team',
|
|
2849
|
+
'creative agency office'
|
|
2850
|
+
]
|
|
2851
|
+
},
|
|
2852
|
+
photography: {
|
|
2853
|
+
subject: 'photographer'
|
|
2854
|
+
},
|
|
2855
|
+
blog: {
|
|
2856
|
+
subject: 'writer',
|
|
2857
|
+
kin: [
|
|
2858
|
+
'writer',
|
|
2859
|
+
'writing',
|
|
2860
|
+
'notebook',
|
|
2861
|
+
'laptop',
|
|
2862
|
+
'desk',
|
|
2863
|
+
'journal',
|
|
2864
|
+
'reading',
|
|
2865
|
+
'book'
|
|
2866
|
+
],
|
|
2867
|
+
broad: [
|
|
2868
|
+
'writer desk laptop',
|
|
2869
|
+
'writing notebook'
|
|
2870
|
+
]
|
|
2871
|
+
},
|
|
2872
|
+
events: {
|
|
2873
|
+
subject: 'event',
|
|
2874
|
+
kin: [
|
|
2875
|
+
'event',
|
|
2876
|
+
'celebration',
|
|
2877
|
+
'party',
|
|
2878
|
+
'wedding',
|
|
2879
|
+
'venue',
|
|
2880
|
+
'reception',
|
|
2881
|
+
'gathering',
|
|
2882
|
+
'decoration',
|
|
2883
|
+
'banquet'
|
|
2884
|
+
],
|
|
2885
|
+
broad: [
|
|
2886
|
+
'event celebration',
|
|
2887
|
+
'event venue decoration'
|
|
2888
|
+
]
|
|
2889
|
+
},
|
|
2890
|
+
fitness: {
|
|
2891
|
+
subject: 'gym'
|
|
2892
|
+
},
|
|
2893
|
+
yoga: {
|
|
2894
|
+
subject: 'yoga',
|
|
2895
|
+
kin: [
|
|
2896
|
+
'yoga',
|
|
2897
|
+
'meditation',
|
|
2898
|
+
'mindfulness',
|
|
2899
|
+
'pose',
|
|
2900
|
+
'mat',
|
|
2901
|
+
'relaxation',
|
|
2902
|
+
'stretching'
|
|
2903
|
+
],
|
|
2904
|
+
broad: [
|
|
2905
|
+
'yoga class',
|
|
2906
|
+
'meditation'
|
|
2907
|
+
]
|
|
2908
|
+
},
|
|
2909
|
+
beauty: {
|
|
2910
|
+
subject: 'salon',
|
|
2911
|
+
kin: [
|
|
2912
|
+
'salon',
|
|
2913
|
+
'beauty',
|
|
2914
|
+
'hair',
|
|
2915
|
+
'hairdresser',
|
|
2916
|
+
'makeup',
|
|
2917
|
+
'nails',
|
|
2918
|
+
'manicure',
|
|
2919
|
+
'stylist',
|
|
2920
|
+
'spa',
|
|
2921
|
+
'cosmetics'
|
|
2922
|
+
],
|
|
2923
|
+
broad: [
|
|
2924
|
+
'beauty salon',
|
|
2925
|
+
'hair salon'
|
|
2926
|
+
]
|
|
2927
|
+
},
|
|
2928
|
+
realestate: {
|
|
2929
|
+
subject: 'real estate',
|
|
2930
|
+
kin: [
|
|
2931
|
+
'house',
|
|
2932
|
+
'home',
|
|
2933
|
+
'estate',
|
|
2934
|
+
'property',
|
|
2935
|
+
'interior',
|
|
2936
|
+
'apartment',
|
|
2937
|
+
'realtor',
|
|
2938
|
+
'architecture',
|
|
2939
|
+
'living'
|
|
2940
|
+
],
|
|
2941
|
+
broad: [
|
|
2942
|
+
'house exterior',
|
|
2943
|
+
'home interior'
|
|
2944
|
+
]
|
|
2945
|
+
},
|
|
2946
|
+
education: {
|
|
2947
|
+
subject: 'classroom',
|
|
2948
|
+
kin: [
|
|
2949
|
+
'classroom',
|
|
2950
|
+
'student',
|
|
2951
|
+
'students',
|
|
2952
|
+
'education',
|
|
2953
|
+
'learning',
|
|
2954
|
+
'e-learning',
|
|
2955
|
+
'teacher',
|
|
2956
|
+
'teaching',
|
|
2957
|
+
'class',
|
|
2958
|
+
'lecture',
|
|
2959
|
+
'study',
|
|
2960
|
+
'studying',
|
|
2961
|
+
'course',
|
|
2962
|
+
'school',
|
|
2963
|
+
'seminar',
|
|
2964
|
+
'training',
|
|
2965
|
+
'book',
|
|
2966
|
+
'books',
|
|
2967
|
+
'laptop'
|
|
2968
|
+
],
|
|
2969
|
+
broad: [
|
|
2970
|
+
'adult students classroom',
|
|
2971
|
+
'online learning',
|
|
2972
|
+
'adult education'
|
|
2973
|
+
]
|
|
2974
|
+
},
|
|
2975
|
+
nonprofit: {
|
|
2976
|
+
subject: 'volunteers',
|
|
2977
|
+
kin: [
|
|
2978
|
+
'volunteer',
|
|
2979
|
+
'volunteers',
|
|
2980
|
+
'charity',
|
|
2981
|
+
'helping',
|
|
2982
|
+
'donation',
|
|
2983
|
+
'nonprofit',
|
|
2984
|
+
'team',
|
|
2985
|
+
'people'
|
|
2986
|
+
],
|
|
2987
|
+
broad: [
|
|
2988
|
+
'charity volunteers',
|
|
2989
|
+
'volunteers helping'
|
|
2990
|
+
]
|
|
2991
|
+
},
|
|
2992
|
+
music: {
|
|
2993
|
+
subject: 'musician',
|
|
2994
|
+
kin: [
|
|
2995
|
+
'music',
|
|
2996
|
+
'musician',
|
|
2997
|
+
'band',
|
|
2998
|
+
'concert',
|
|
2999
|
+
'guitar',
|
|
3000
|
+
'stage',
|
|
3001
|
+
'singer',
|
|
3002
|
+
'instrument',
|
|
3003
|
+
'piano',
|
|
3004
|
+
'drums'
|
|
3005
|
+
],
|
|
3006
|
+
broad: [
|
|
3007
|
+
'live music band',
|
|
3008
|
+
'musician guitar'
|
|
3009
|
+
]
|
|
3010
|
+
},
|
|
3011
|
+
personal: {
|
|
3012
|
+
subject: 'workspace',
|
|
3013
|
+
kin: [
|
|
3014
|
+
'workspace',
|
|
3015
|
+
'desk',
|
|
3016
|
+
'laptop',
|
|
3017
|
+
'office',
|
|
3018
|
+
'professional',
|
|
3019
|
+
'notebook',
|
|
3020
|
+
'coffee'
|
|
3021
|
+
],
|
|
3022
|
+
broad: [
|
|
3023
|
+
'workspace desk laptop',
|
|
3024
|
+
'professional workspace'
|
|
3025
|
+
]
|
|
3026
|
+
},
|
|
3027
|
+
landing: {
|
|
3028
|
+
subject: 'startup team',
|
|
3029
|
+
kin: [
|
|
3030
|
+
'startup',
|
|
3031
|
+
'team',
|
|
3032
|
+
'technology',
|
|
3033
|
+
'laptop',
|
|
3034
|
+
'office',
|
|
3035
|
+
'workspace',
|
|
3036
|
+
'business',
|
|
3037
|
+
'meeting'
|
|
3038
|
+
],
|
|
3039
|
+
broad: [
|
|
3040
|
+
'startup team office',
|
|
3041
|
+
'modern workspace'
|
|
3042
|
+
]
|
|
3043
|
+
},
|
|
3044
|
+
'coming-soon': {
|
|
3045
|
+
subject: 'workspace',
|
|
3046
|
+
kin: [
|
|
3047
|
+
'workspace',
|
|
3048
|
+
'desk',
|
|
3049
|
+
'laptop',
|
|
3050
|
+
'office',
|
|
3051
|
+
'notebook',
|
|
3052
|
+
'coffee'
|
|
3053
|
+
],
|
|
3054
|
+
broad: [
|
|
3055
|
+
'modern workspace',
|
|
3056
|
+
'workspace desk laptop'
|
|
3057
|
+
]
|
|
3058
|
+
}
|
|
3059
|
+
};
|
|
3060
|
+
/** Words a business's name or audience uses for a kind of site (AGL-3856): "Learning Center" is a school's. */ const NAMED_KINDS = [
|
|
3061
|
+
{
|
|
3062
|
+
kind: 'education',
|
|
3063
|
+
words: [
|
|
3064
|
+
'learning',
|
|
3065
|
+
'academy',
|
|
3066
|
+
'school',
|
|
3067
|
+
'tutoring',
|
|
3068
|
+
'tutor',
|
|
3069
|
+
'tutors',
|
|
3070
|
+
'college',
|
|
3071
|
+
'institute',
|
|
3072
|
+
'university',
|
|
3073
|
+
'courses',
|
|
3074
|
+
'classes',
|
|
3075
|
+
'lessons',
|
|
3076
|
+
'education',
|
|
3077
|
+
'students',
|
|
3078
|
+
'learners'
|
|
3079
|
+
]
|
|
3080
|
+
},
|
|
3081
|
+
{
|
|
3082
|
+
kind: 'beauty',
|
|
3083
|
+
words: [
|
|
3084
|
+
'salon',
|
|
3085
|
+
'barber',
|
|
3086
|
+
'barbershop',
|
|
3087
|
+
'nails',
|
|
3088
|
+
'spa',
|
|
3089
|
+
'lashes',
|
|
3090
|
+
'brows'
|
|
3091
|
+
]
|
|
3092
|
+
},
|
|
3093
|
+
{
|
|
3094
|
+
kind: 'realestate',
|
|
3095
|
+
words: [
|
|
3096
|
+
'realty',
|
|
3097
|
+
'realtor',
|
|
3098
|
+
'realtors',
|
|
3099
|
+
'properties',
|
|
3100
|
+
'homes',
|
|
3101
|
+
'estate'
|
|
3102
|
+
]
|
|
3103
|
+
},
|
|
3104
|
+
{
|
|
3105
|
+
kind: 'restaurant',
|
|
3106
|
+
words: [
|
|
3107
|
+
'restaurant',
|
|
3108
|
+
'bistro',
|
|
3109
|
+
'kitchen',
|
|
3110
|
+
'grill',
|
|
3111
|
+
'diner',
|
|
3112
|
+
'eatery',
|
|
3113
|
+
'cafe',
|
|
3114
|
+
'café',
|
|
3115
|
+
'tavern',
|
|
3116
|
+
'pizzeria'
|
|
3117
|
+
]
|
|
3118
|
+
},
|
|
3119
|
+
{
|
|
3120
|
+
kind: 'trades',
|
|
3121
|
+
words: [
|
|
3122
|
+
'plumbing',
|
|
3123
|
+
'roofing',
|
|
3124
|
+
'hvac',
|
|
3125
|
+
'electric',
|
|
3126
|
+
'electrical',
|
|
3127
|
+
'landscaping',
|
|
3128
|
+
'construction',
|
|
3129
|
+
'contracting',
|
|
3130
|
+
'remodeling',
|
|
3131
|
+
'painting',
|
|
3132
|
+
'handyman'
|
|
3133
|
+
]
|
|
3134
|
+
},
|
|
3135
|
+
{
|
|
3136
|
+
kind: 'nonprofit',
|
|
3137
|
+
words: [
|
|
3138
|
+
'foundation',
|
|
3139
|
+
'charity',
|
|
3140
|
+
'church',
|
|
3141
|
+
'ministry',
|
|
3142
|
+
'nonprofit',
|
|
3143
|
+
'volunteers'
|
|
3144
|
+
]
|
|
3145
|
+
},
|
|
3146
|
+
{
|
|
3147
|
+
kind: 'yoga',
|
|
3148
|
+
words: [
|
|
3149
|
+
'yoga',
|
|
3150
|
+
'meditation',
|
|
3151
|
+
'mindfulness'
|
|
3152
|
+
]
|
|
3153
|
+
},
|
|
3154
|
+
{
|
|
3155
|
+
kind: 'music',
|
|
3156
|
+
words: [
|
|
3157
|
+
'band',
|
|
3158
|
+
'music',
|
|
3159
|
+
'orchestra',
|
|
3160
|
+
'choir',
|
|
3161
|
+
'records'
|
|
3162
|
+
]
|
|
3163
|
+
},
|
|
3164
|
+
{
|
|
3165
|
+
kind: 'wellness',
|
|
3166
|
+
words: [
|
|
3167
|
+
'wellness',
|
|
3168
|
+
'therapy',
|
|
3169
|
+
'massage',
|
|
3170
|
+
'clinic',
|
|
3171
|
+
'chiropractic',
|
|
3172
|
+
'counseling'
|
|
3173
|
+
]
|
|
3174
|
+
}
|
|
3175
|
+
];
|
|
3176
|
+
/** The kind of site a business's name or audience names ({@link NAMED_KINDS}), or empty. */ export function aiStockNamedKind(text) {
|
|
3177
|
+
var _ref;
|
|
3178
|
+
var _NAMED_KINDS_find;
|
|
3179
|
+
const named = new Set(text.toLowerCase().split(/[^a-zÀ-ɏ]+/).filter(Boolean));
|
|
3180
|
+
return (_ref = (_NAMED_KINDS_find = NAMED_KINDS.find((entry)=>entry.words.some((word)=>named.has(word)))) == null ? void 0 : _NAMED_KINDS_find.kind) != null ? _ref : '';
|
|
3181
|
+
}
|
|
3182
|
+
/** What a kind of site's pictures are searched and judged by ({@link KIND_SUBJECTS}); `null` for a kind not listed. */ export function aiStockKindTerms(kind) {
|
|
3183
|
+
var _entry_broad;
|
|
3184
|
+
var _entry_kin;
|
|
3185
|
+
const entry = KIND_SUBJECTS[kind];
|
|
3186
|
+
if (!entry) return null;
|
|
3187
|
+
const base = aiStockSiteTerms(entry.subject);
|
|
3188
|
+
if (!((_entry_kin = entry.kin) == null ? void 0 : _entry_kin.length)) return base;
|
|
3189
|
+
const kin = entry.kin.map(aiStockStem);
|
|
3190
|
+
return _extends({}, base, {
|
|
3191
|
+
domain: [
|
|
3192
|
+
...new Set([
|
|
3193
|
+
...base.domain,
|
|
3194
|
+
...kin
|
|
3195
|
+
])
|
|
3196
|
+
],
|
|
3197
|
+
broad: [
|
|
3198
|
+
...(_entry_broad = entry.broad) != null ? _entry_broad : base.broad
|
|
3199
|
+
],
|
|
3200
|
+
// A hero names one of the kind's own words, never only the subject's.
|
|
3201
|
+
core: [
|
|
3202
|
+
...new Set([
|
|
3203
|
+
...base.core,
|
|
3204
|
+
...kin
|
|
3205
|
+
])
|
|
3206
|
+
]
|
|
3207
|
+
});
|
|
3208
|
+
}
|
|
3209
|
+
/**
|
|
3210
|
+
* The first word of a text that names a craft {@link CRAFT_KIN} lists, as
|
|
3211
|
+
* its table writes it: "gym" of "Synchronicity Gym", "law" of "Hartwell
|
|
3212
|
+
* Reyes Family Law". Empty where it names none, so a name that is only a
|
|
3213
|
+
* name ("Hillside") never becomes a world.
|
|
3214
|
+
*/ export function aiStockListedCraft(text) {
|
|
3215
|
+
for (const stem of stemList(text))for (const group of CRAFT_KIN){
|
|
3216
|
+
const word = group.match.find((match)=>aiStockStem(match) === stem);
|
|
3217
|
+
if (word) return word;
|
|
3218
|
+
}
|
|
3219
|
+
return '';
|
|
2235
3220
|
}
|
|
2236
3221
|
/**
|
|
2237
3222
|
* What a site in another language is searched by ({@link aiStockSourceTerms}),
|
|
@@ -2308,6 +3293,10 @@ const EXTENSIONS = {
|
|
|
2308
3293
|
delete request.leadWorld;
|
|
2309
3294
|
delete request.first;
|
|
2310
3295
|
delete request.category;
|
|
3296
|
+
delete request.strict;
|
|
3297
|
+
delete request.refuse;
|
|
3298
|
+
delete request.needs;
|
|
3299
|
+
delete request.allow;
|
|
2311
3300
|
const key = JSON.stringify([
|
|
2312
3301
|
request.query,
|
|
2313
3302
|
request.orientation,
|
|
@@ -2416,12 +3405,17 @@ const EXTENSIONS = {
|
|
|
2416
3405
|
};
|
|
2417
3406
|
/** How a search's hits are judged for a slot. */ const judgementFor = (slot, request, subject)=>{
|
|
2418
3407
|
var _request_subject, _request_shun;
|
|
2419
|
-
var _request_shun1, _request_leadAny;
|
|
3408
|
+
var _request_allow, _request_shun1, _request_leadAny, _request_refuse, _request_needs;
|
|
2420
3409
|
return _extends({
|
|
2421
3410
|
subject: (_request_subject = request.subject) != null ? _request_subject : request.broad ? '' : subject,
|
|
2422
3411
|
domain: terms.domain,
|
|
2423
|
-
strict: slot.role === 'gallery' && !request.broad || !!request.requires,
|
|
2424
|
-
named:
|
|
3412
|
+
strict: slot.role === 'gallery' && !request.broad || !!request.requires || !!request.strict,
|
|
3413
|
+
named: ((_request_allow = request.allow) == null ? void 0 : _request_allow.length) ? [
|
|
3414
|
+
...new Set([
|
|
3415
|
+
...terms.named,
|
|
3416
|
+
...request.allow
|
|
3417
|
+
])
|
|
3418
|
+
] : terms.named,
|
|
2425
3419
|
rivals: terms.rivals
|
|
2426
3420
|
}, terms.shun.length || ((_request_shun1 = request.shun) == null ? void 0 : _request_shun1.length) ? {
|
|
2427
3421
|
shun: [
|
|
@@ -2450,6 +3444,10 @@ const EXTENSIONS = {
|
|
|
2450
3444
|
leadWorld: true
|
|
2451
3445
|
} : {}, request.first ? {
|
|
2452
3446
|
first: true
|
|
3447
|
+
} : {}, ((_request_refuse = request.refuse) == null ? void 0 : _request_refuse.length) ? {
|
|
3448
|
+
refuse: request.refuse
|
|
3449
|
+
} : {}, ((_request_needs = request.needs) == null ? void 0 : _request_needs.length) ? {
|
|
3450
|
+
needs: request.needs
|
|
2453
3451
|
} : {});
|
|
2454
3452
|
};
|
|
2455
3453
|
/**
|