@aglyn/plugins-ai 1.0.0-beta.270 → 1.0.0-beta.271
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/activity/ai-activity-actions.d.ts +1 -1
- package/src/lib/activity/ai-activity-actions.js +1 -0
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/components/ai-credits-card.component.d.ts +4 -3
- package/src/lib/components/ai-credits-card.component.js +15 -15
- package/src/lib/components/ai-credits-card.component.js.map +1 -1
- package/src/lib/components/ai-job-input-form.component.d.ts +36 -0
- package/src/lib/components/ai-job-input-form.component.js +100 -0
- package/src/lib/components/ai-job-input-form.component.js.map +1 -0
- package/src/lib/components/ai-job-requests.d.ts +4 -0
- package/src/lib/components/ai-job-requests.js +4 -0
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
- package/src/lib/components/ai-site-start-card.component.js +99 -31
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +43 -2
- package/src/lib/components/ai-site-start-steps.component.js +651 -15
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
- package/src/lib/components/ai-site-start-tracking.d.ts +10 -0
- package/src/lib/components/ai-site-start-tracking.js +14 -0
- package/src/lib/components/ai-site-start-tracking.js.map +1 -1
- package/src/lib/components/ai-site-style-previews.js +26 -22
- package/src/lib/components/ai-site-style-previews.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.d.ts +7 -5
- package/src/lib/components/ai-upsell-dialog.component.js +8 -6
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.js +11 -1
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +9 -1
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +8 -4
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-card.component.js +4 -7
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
- package/src/lib/declarations.d.ts +2 -2
- package/src/lib/declarations.js +9 -5
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.js +3 -1
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
- package/src/lib/jobs/ai-business-profile-prefill.d.ts +1 -1
- package/src/lib/jobs/ai-business-profile-prefill.js +14 -3
- package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.js +5 -3
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.d.ts +15 -1
- package/src/lib/jobs/ai-job-form-step.js +75 -8
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +13 -0
- package/src/lib/jobs/ai-job-page-language.js +37 -1
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +17 -0
- package/src/lib/jobs/ai-job-page-step.js +37 -16
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +25 -2
- package/src/lib/jobs/ai-job-plan-step.js +103 -29
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-settings-step.js +4 -3
- package/src/lib/jobs/ai-job-settings-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +27 -0
- package/src/lib/jobs/ai-job-site-datasets.js +140 -14
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-site-look.js +18 -5
- package/src/lib/jobs/ai-job-site-look.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +16 -1
- package/src/lib/jobs/ai-job-site-step.js +95 -22
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +8 -1
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-job-tracking-step.d.ts +14 -3
- package/src/lib/jobs/ai-job-tracking-step.js +28 -5
- package/src/lib/jobs/ai-job-tracking-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +8 -1
- package/src/lib/jobs/ai-jobs.js +63 -8
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +27 -2
- package/src/lib/jobs/ai-layout-stock-photos.js +190 -19
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-inspiration-signals.d.ts +98 -0
- package/src/lib/jobs/ai-site-inspiration-signals.js +585 -0
- package/src/lib/jobs/ai-site-inspiration-signals.js.map +1 -0
- package/src/lib/jobs/ai-site-inspiration.d.ts +157 -0
- package/src/lib/jobs/ai-site-inspiration.js +346 -0
- package/src/lib/jobs/ai-site-inspiration.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +26 -1
- package/src/lib/jobs/ai-site-publish.js +162 -13
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/ai-theme-brand-inputs.d.ts +16 -0
- package/src/lib/jobs/ai-theme-brand-inputs.js +18 -4
- package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.d.ts +97 -0
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.js +137 -0
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.d.ts +38 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.js +103 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.d.ts +25 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.js +174 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +1 -1
- package/src/lib/layout-language/ai-layout-compiler.js +438 -25
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-contact.d.ts +57 -0
- package/src/lib/layout-language/ai-layout-contact.js +137 -0
- package/src/lib/layout-language/ai-layout-contact.js.map +1 -0
- package/src/lib/layout-language/ai-layout-copy.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-copy.js +34 -2
- package/src/lib/layout-language/ai-layout-copy.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +65 -8
- package/src/lib/layout-language/ai-layout-design.js +411 -97
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.js +23 -0
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-labels.d.ts +2 -0
- package/src/lib/layout-language/ai-layout-labels.js +12 -6
- package/src/lib/layout-language/ai-layout-labels.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +3 -2
- package/src/lib/layout-language/ai-layout-language.js +4 -3
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-links.d.ts +13 -0
- package/src/lib/layout-language/ai-layout-links.js +30 -0
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +49 -6
- package/src/lib/layout-language/ai-layout-pictures.js +145 -22
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +16 -1
- package/src/lib/model/ai-build-job.js +40 -0
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-job-input.d.ts +33 -0
- package/src/lib/model/ai-job-input.js +59 -0
- package/src/lib/model/ai-job-input.js.map +1 -0
- package/src/lib/model/ai-job-notice.d.ts +4 -0
- package/src/lib/model/ai-job-notice.js +11 -1
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +40 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-details.d.ts +122 -0
- package/src/lib/model/ai-site-details.js +300 -0
- package/src/lib/model/ai-site-details.js.map +1 -0
- package/src/lib/model/ai-site-entity.d.ts +181 -0
- package/src/lib/model/ai-site-entity.js +390 -0
- package/src/lib/model/ai-site-entity.js.map +1 -0
- package/src/lib/model/ai-site-inspiration.d.ts +72 -0
- package/src/lib/model/ai-site-inspiration.js +109 -0
- package/src/lib/model/ai-site-inspiration.js.map +1 -0
- package/src/lib/model/ai-site-job.d.ts +13 -1
- package/src/lib/model/ai-site-job.js +15 -2
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.js +109 -21
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-look.d.ts +10 -0
- package/src/lib/model/ai-site-look.js +24 -0
- package/src/lib/model/ai-site-look.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +19 -5
- package/src/lib/model/ai-site-start-seo.js +25 -7
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start-steps.d.ts +9 -3
- package/src/lib/model/ai-site-start-steps.js +67 -5
- package/src/lib/model/ai-site-start-steps.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +68 -4
- package/src/lib/model/ai-site-start.js +166 -13
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/ai-upsell-copy.js +4 -1
- package/src/lib/model/ai-upsell-copy.js.map +1 -1
- package/src/lib/plan-entitlements.d.ts +4 -3
- package/src/lib/plan-entitlements.js +3 -8
- package/src/lib/plan-entitlements.js.map +1 -1
- package/src/lib/runtime/ai-dataset-generation.d.ts +8 -1
- package/src/lib/runtime/ai-dataset-generation.js +12 -2
- package/src/lib/runtime/ai-dataset-generation.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +26 -33
- package/src/lib/runtime/ai-doctrine-validators.js +54 -44
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +1 -1
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +7 -0
- package/src/lib/runtime/ai-node-tree.js +9 -1
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/server/ai-create-route.d.ts +1 -1
- package/src/lib/server/ai-create-route.js +3 -4
- package/src/lib/server/ai-create-route.js.map +1 -1
- package/src/lib/server/ai-jobs-resume.js +27 -3
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +7 -0
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/usage/assist-credits.d.ts +4 -4
- package/src/lib/usage/assist-credits.js +4 -4
- package/src/lib/usage/assist-credits.js.map +1 -1
- package/src/lib/usage/staff-org-ai-view.js +6 -3
- package/src/lib/usage/staff-org-ai-view.js.map +1 -1
- package/src/lib/usage/staff-org-ai.d.ts +4 -2
- package/src/lib/usage/staff-org-ai.js +7 -7
- package/src/lib/usage/staff-org-ai.js.map +1 -1
- package/src/lib/usage/staff-org-usage-ai.js +2 -2
- package/src/lib/usage/staff-org-usage-ai.js.map +1 -1
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { type PluginMediaIngest } from '@aglyn/aglyn/plugin-manager/plugin-media-ingest';
|
|
18
18
|
import { type StockPhoto, type StockPhotoOrientation, type StockPhotoProvider, type StockPhotoSearchRequest } from '@aglyn/aglyn/plugin-manager/stock-photo-provider';
|
|
19
19
|
import type { NodesMap } from '@aglyn/aglyn/types/nodes';
|
|
20
|
-
import { type AiLayoutPictureSlot, type AiLayoutPictureSource } from '../layout-language/ai-layout-pictures';
|
|
20
|
+
import { type AiLayoutPicturePhoto, type AiLayoutPictureSlot, type AiLayoutPictureSource } from '../layout-language/ai-layout-pictures';
|
|
21
21
|
import type { AiBuildPlan } from '../model/ai-build-plan';
|
|
22
22
|
/**
|
|
23
23
|
* STOCK PHOTOS FOR A LANGUAGE PAGE'S PICTURE SLOTS (AGL-3660).
|
|
@@ -178,6 +178,14 @@ export declare const AI_STOCK_PHOTO_PAGES_INPUT = "stockPhotoPages";
|
|
|
178
178
|
* (AGL-3616) — which a page does not place again.
|
|
179
179
|
*/
|
|
180
180
|
export declare const AI_STOCK_PHOTO_AVOID_INPUT = "stockPhotoAvoid";
|
|
181
|
+
/**
|
|
182
|
+
* The unit job input holding the photos another part of the job placed
|
|
183
|
+
* outside its pages — a dataset's records — with their size and words
|
|
184
|
+
* (AGL-3988): what a picture the library failed takes before any starter.
|
|
185
|
+
*/
|
|
186
|
+
export declare const AI_STOCK_PHOTO_JOB_PHOTOS_INPUT = "stockPhotoJobPhotos";
|
|
187
|
+
/** The job photos a unit input holds ({@link AI_STOCK_PHOTO_JOB_PHOTOS_INPUT}): library photos with a size; anything else is dropped. */
|
|
188
|
+
export declare function aiStockJobPhotosOf(value: unknown): AiLayoutPicturePhoto[];
|
|
181
189
|
/**
|
|
182
190
|
* A word's singular, for matching only: "bowls" and "bowl", "vases" and
|
|
183
191
|
* "vase", "berries" and "berry", "dishes" and "dish" meet. Both sides of a
|
|
@@ -591,6 +599,13 @@ export declare function aiStockPick(photos: readonly StockPhoto[], used: Readonl
|
|
|
591
599
|
* not the job's, and are not listed.
|
|
592
600
|
*/
|
|
593
601
|
export declare function aiStockPlacedSrcs(nodes: NodesMap | null | undefined): string[];
|
|
602
|
+
/**
|
|
603
|
+
* The library photos a stored page shows, each as a slot takes it (AGL-3988):
|
|
604
|
+
* its source, its size and what it shows. A photo the job placed on another
|
|
605
|
+
* page is what a slot the library failed takes before any starter
|
|
606
|
+
* (`aiLayoutJobPhotoPicks`). Each photo once; one without a size is left out.
|
|
607
|
+
*/
|
|
608
|
+
export declare function aiStockPlacedPhotos(nodes: NodesMap | null | undefined): AiLayoutPicturePhoto[];
|
|
594
609
|
/** Forgets every job's placed photos; for specs. */
|
|
595
610
|
export declare function aiStockForgetJobPhotos(): void;
|
|
596
611
|
/**
|
|
@@ -612,7 +627,17 @@ export declare function aiStockForgetJobPhotos(): void;
|
|
|
612
627
|
* - a second thing comes only from the first two tags and where no place is
|
|
613
628
|
* said, what a person holds only from the first three, where it is set
|
|
614
629
|
* from the first ten;
|
|
615
|
-
* - no word is said twice: never "an elderly couple and an elderly"
|
|
630
|
+
* - no word is said twice: never "an elderly couple and an elderly";
|
|
631
|
+
* - the sky, the clouds and the light are no thing anyone holds, and the
|
|
632
|
+
* weather is said as where it is: "a couple in the fog at a wedding",
|
|
633
|
+
* "a couple in the snow in the mountains", never "a couple with a sky at
|
|
634
|
+
* sunset" or "a snow in the mountains"; a feeling ("care", "worry") is no
|
|
635
|
+
* thing either; whoever else is about ("tourists") is never said beside a
|
|
636
|
+
* family; a parent beside a child is said with them ("a father with a
|
|
637
|
+
* girl"); a tag that is a phrase of its own ("couple on bench") is read as
|
|
638
|
+
* its parts; a time of day comes after where ("in the mountains at
|
|
639
|
+
* sunset"), and a bench out of doors says where it stands ("on a bench by
|
|
640
|
+
* the lake") (AGL-3988).
|
|
616
641
|
*
|
|
617
642
|
* `null` where no tag names a thing.
|
|
618
643
|
*/
|
|
@@ -178,6 +178,31 @@ import { aiStockBusinessNoun } from "./ai-stock-business-nouns.js";
|
|
|
178
178
|
* part of the job already shows outside its pages — a dataset's records
|
|
179
179
|
* (AGL-3616) — which a page does not place again.
|
|
180
180
|
*/ export const AI_STOCK_PHOTO_AVOID_INPUT = 'stockPhotoAvoid';
|
|
181
|
+
/**
|
|
182
|
+
* The unit job input holding the photos another part of the job placed
|
|
183
|
+
* outside its pages — a dataset's records — with their size and words
|
|
184
|
+
* (AGL-3988): what a picture the library failed takes before any starter.
|
|
185
|
+
*/ export const AI_STOCK_PHOTO_JOB_PHOTOS_INPUT = 'stockPhotoJobPhotos';
|
|
186
|
+
/** The job photos a unit input holds ({@link AI_STOCK_PHOTO_JOB_PHOTOS_INPUT}): library photos with a size; anything else is dropped. */ export function aiStockJobPhotosOf(value) {
|
|
187
|
+
if (!Array.isArray(value)) return [];
|
|
188
|
+
return value.flatMap((entry)=>{
|
|
189
|
+
const photo = entry;
|
|
190
|
+
const src = typeof (photo == null ? void 0 : photo.src) === 'string' ? photo.src : '';
|
|
191
|
+
const width = Number(photo == null ? void 0 : photo.width);
|
|
192
|
+
const height = Number(photo == null ? void 0 : photo.height);
|
|
193
|
+
if (!src.startsWith('media:') || !(width > 0) || !(height > 0)) return [];
|
|
194
|
+
const alt = typeof (photo == null ? void 0 : photo.alt) === 'string' ? photo.alt.trim() : '';
|
|
195
|
+
return [
|
|
196
|
+
_extends({
|
|
197
|
+
src,
|
|
198
|
+
width,
|
|
199
|
+
height
|
|
200
|
+
}, alt ? {
|
|
201
|
+
alt
|
|
202
|
+
} : {})
|
|
203
|
+
];
|
|
204
|
+
});
|
|
205
|
+
}
|
|
181
206
|
const words = (list)=>new Set(list.trim().split(/\s+/));
|
|
182
207
|
/** Words that carry no subject. */ const STOPWORDS = words('a an the and or of in on at to for with from by into onto over under near our your their my his her its ' + 'this that these those is are be being was were who whom which where while as about than then very just ' + 'small local best new top quality premium family-owned family owned independent professional ' + 'business company services service page photo picture image showing shows show ' + 'someone people person one two three some many several');
|
|
183
208
|
/**
|
|
@@ -3078,6 +3103,35 @@ const clip = (query)=>query.replace(/\s+/g, ' ').trim().slice(0, STOCK_PHOTO_QUE
|
|
|
3078
3103
|
}
|
|
3079
3104
|
return out;
|
|
3080
3105
|
}
|
|
3106
|
+
/**
|
|
3107
|
+
* The library photos a stored page shows, each as a slot takes it (AGL-3988):
|
|
3108
|
+
* its source, its size and what it shows. A photo the job placed on another
|
|
3109
|
+
* page is what a slot the library failed takes before any starter
|
|
3110
|
+
* (`aiLayoutJobPhotoPicks`). Each photo once; one without a size is left out.
|
|
3111
|
+
*/ export function aiStockPlacedPhotos(nodes) {
|
|
3112
|
+
const map = nodes != null ? nodes : {};
|
|
3113
|
+
const out = new Map();
|
|
3114
|
+
for (const node of Object.values(map)){
|
|
3115
|
+
var _node_props, _node_props1, _node_props2, _node_props3;
|
|
3116
|
+
if ((node == null ? void 0 : node.componentId) !== 'image') continue;
|
|
3117
|
+
const src = (_node_props = node.props) == null ? void 0 : _node_props['src'];
|
|
3118
|
+
const width = Number((_node_props1 = node.props) == null ? void 0 : _node_props1['intrinsicWidth']);
|
|
3119
|
+
const height = Number((_node_props2 = node.props) == null ? void 0 : _node_props2['intrinsicHeight']);
|
|
3120
|
+
if (typeof src !== 'string' || !src.startsWith('media:') || out.has(src)) continue;
|
|
3121
|
+
if (!(width > 0) || !(height > 0)) continue;
|
|
3122
|
+
const alt = typeof ((_node_props3 = node.props) == null ? void 0 : _node_props3['alt']) === 'string' ? node.props['alt'].trim() : '';
|
|
3123
|
+
out.set(src, _extends({
|
|
3124
|
+
src,
|
|
3125
|
+
width,
|
|
3126
|
+
height
|
|
3127
|
+
}, alt ? {
|
|
3128
|
+
alt
|
|
3129
|
+
} : {}));
|
|
3130
|
+
}
|
|
3131
|
+
return [
|
|
3132
|
+
...out.values()
|
|
3133
|
+
];
|
|
3134
|
+
}
|
|
3081
3135
|
/**
|
|
3082
3136
|
* What this process has placed for each job, by source key and asset src,
|
|
3083
3137
|
* with the scope (the page's seed) that placed it (AGL-3660). It spans the
|
|
@@ -3114,13 +3168,34 @@ function jobPhotos(key) {
|
|
|
3114
3168
|
'together alone apart away abroad ahead nearby outside inside upstairs downstairs ' + // Adjectives a tag gives alone, never a thing: "students, multicultural" (AGL-3856).
|
|
3115
3169
|
'multicultural multiethnic multiracial diverse international cultural traditional modern classic classical ' + 'domestic wild tropical rural urban ' + // How the photo was made, never what it shows: "cutout, perspective", "men, silhouettes".
|
|
3116
3170
|
'silhouette silhouettes cutout perspective bokeh closeup ' + // A holiday names when, never a thing: "tet market" is a market.
|
|
3117
|
-
'tet christmas easter halloween diwali ramadan hanukkah thanksgiving ' + 'indian asian african american european caucasian vietnamese japanese chinese korean thai latino latina hispanic ' + 'japan vietnam viet nam thailand india china korea germany france italy spain england britain uk usa america ' + 'canada mexico brazil australia africa europe asia')
|
|
3171
|
+
'tet christmas easter halloween diwali ramadan hanukkah thanksgiving ' + 'indian asian african american european caucasian vietnamese japanese chinese korean thai latino latina hispanic ' + 'japan vietnam viet nam thailand india china korea germany france italy spain england britain uk usa america ' + 'canada mexico brazil australia africa europe asia ' + // How a scene feels or looks, never a thing in it (AGL-3988): "mountain,
|
|
3172
|
+
// snow, winter, cold, couple, color, landscape" is a couple in the snow.
|
|
3173
|
+
'cold warm hot chilly freezing frozen icy color colors colour colours landscape landscapes ' + 'panorama panoramic vista scene scenes');
|
|
3174
|
+
/**
|
|
3175
|
+
* The sky and the light over a scene, never a thing in it (AGL-3988): "A
|
|
3176
|
+
* couple with a sky at sunset" and "A child with clouds by a lake" were a
|
|
3177
|
+
* couple at sunset and a child by a lake.
|
|
3178
|
+
*/ const SCENERY = words('sky skies cloud clouds sun sunshine sunlight daylight light shadow shadows horizon');
|
|
3179
|
+
/**
|
|
3180
|
+
* The weather a scene is in, said as where (AGL-3988): "A couple with a fog
|
|
3181
|
+
* at a wedding" was a couple in the fog, "A snow in the mountains" a couple
|
|
3182
|
+
* in the snow.
|
|
3183
|
+
*/ const WEATHER = {
|
|
3184
|
+
fog: 'in the fog',
|
|
3185
|
+
mist: 'in the mist',
|
|
3186
|
+
haze: 'in the haze',
|
|
3187
|
+
rain: 'in the rain',
|
|
3188
|
+
snow: 'in the snow',
|
|
3189
|
+
snowfall: 'in the snow',
|
|
3190
|
+
snowflakes: 'in the snow',
|
|
3191
|
+
wind: 'in the wind'
|
|
3192
|
+
};
|
|
3118
3193
|
/**
|
|
3119
3194
|
* Words a tag uses for what a person or a thing is like, said before it
|
|
3120
3195
|
* rather than as a thing of its own (AGL-3856): "a confident lawyer", "an
|
|
3121
3196
|
* elderly couple", "an analog camera", never "a lawyer, law and a confident".
|
|
3122
3197
|
*/ const QUALITIES = words('confident professional successful serious smart busy creative proud skilled experienced determined focused ' + 'senior junior expert friendly cheerful smiling elderly analog analogue digital mirrorless');
|
|
3123
|
-
/** What a tag names that takes no article: "chalk" of "board, chalk". */ const MASS_NOUNS = words('food coffee tea bread wood water wax soap clay money fabric yarn wool furniture jewelry jewellery ' + 'pottery glass paper music art hair makeup chalk paint ink dust stone marble concrete steel metal ' + 'skincare equipment decor
|
|
3198
|
+
/** What a tag names that takes no article: "chalk" of "board, chalk". */ const MASS_NOUNS = words('food coffee tea bread wood water wax soap clay money fabric yarn wool furniture jewelry jewellery ' + 'pottery glass paper music art hair makeup chalk paint ink dust stone marble concrete steel metal ' + 'skincare equipment decor wildlife weather traffic wine beer chocolate rice sugar flour milk ' + 'cheese honey oil ice fire light sunlight dough sourdough pastry dessert people foliage greenery faculty staff ' + 'clothing bedding frosting icing flooring');
|
|
3124
3199
|
/** Nouns plural without an "-s": said without an article, "women in a classroom". */ const PLURAL_NOUNS = words('men women people children feet teeth mice geese sheep fish');
|
|
3125
3200
|
/**
|
|
3126
3201
|
* What a tag names that no photo shows as a thing of its own (AGL-3856): an
|
|
@@ -3128,7 +3203,8 @@ function jobPhotos(key) {
|
|
|
3128
3203
|
* doing ("read", "lift", "fitness", "a workout"), a word for the photo itself
|
|
3129
3204
|
* ("photo", "spot"). Left out, never said with an article: "A bookwork and a
|
|
3130
3205
|
* read", "A kettlebell and fitness", "A board and training" said nothing.
|
|
3131
|
-
*/ 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 ' + 'fitness workout workouts exercise exercises crossfit sport sports skill skills knowledge exam exams lecture ' + 'session lesson course hobby leisure power energy wellness talent formation participation ' + 'press show day days night year years time holiday month months week weeks morning evening afternoon season seasons ' + 'kiss hug embrace ' +
|
|
3206
|
+
*/ 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 ' + 'fitness workout workouts exercise exercises crossfit sport sports skill skills knowledge exam exams lecture ' + 'session lesson course hobby leisure power energy wellness talent formation participation ' + 'press show day days night year years time holiday month months week weeks morning evening afternoon season seasons ' + 'kiss hug embrace ' + // A feeling, never a thing anyone holds (AGL-3988): "A father with a care".
|
|
3207
|
+
'care worry trust hope joy peace fear faith grief pride comfort safety bliss delight passion desire feeling feelings ' + 'moment moments memory memories fashion style ' + 'photo photos picture pictures image images shot shots shoot shoots spot spots ' + 'read write learn study lift move remove focus relax think sit smile laugh eat swim teach enjoy celebrate explore ' + 'hike can');
|
|
3132
3208
|
/** Words ending as an idea does that are things: "a station", "a city", "a ship". */ const CONCRETE_ABSTRACT_ENDINGS = words('station mansion lotion potion ornament instrument apartment monument pavement basement garment compartment ' + 'equipment cement city university facility ship warship spaceship airship');
|
|
3133
3209
|
/** Whether a word is an idea or a doing by how it ends: "participation", "unity", "empowerment". */ const saysAnIdea = (word)=>/(?:tion|sion|ment|ness|ity|ship|ism)s?$/.test(word) && !CONCRETE_ABSTRACT_ENDINGS.has(aiStockStem(word));
|
|
3134
3210
|
/**
|
|
@@ -3138,8 +3214,20 @@ function jobPhotos(key) {
|
|
|
3138
3214
|
/** Stopwords a description still says, as the people a photo shows: "a family", "a person". */ const SAID_PEOPLE = words('people person family');
|
|
3139
3215
|
/** 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 dumpling pudding sapling');
|
|
3140
3216
|
/** "-ing" words that are things, and take no article: "clothing". */ const UNCOUNTED_ING = words('clothing bedding frosting icing flooring stuffing seasoning filling');
|
|
3141
|
-
/** 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 human humans boy boys girl girls guy guys lady ladies child children kid kids ' + 'baby family couple bride groom schoolgirl schoolboy teen teenager student students graduate athlete athletes ' + 'businessman businesswoman businessmen lawyer attorney doctor dentist nurse chef cook baker barista ' + 'trainer coach teacher teachers instructor lecturer professor tutor worker workers entrepreneur model ' + 'photographer potter artist florist mother father parent parents grandmother grandfather grandparents ' + 'faculty staff team participants volunteer volunteers musician dancer leader manager owner founder ' + 'journalist journalists reporter reporters master masters lovers newlywed newlyweds husband wife fiance fiancee spouse')
|
|
3142
|
-
|
|
3217
|
+
/** 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 human humans boy boys girl girls guy guys lady ladies child children kid kids ' + 'baby family couple bride groom schoolgirl schoolboy teen teenager student students graduate athlete athletes ' + 'businessman businesswoman businessmen lawyer attorney doctor dentist nurse chef cook baker barista ' + 'trainer coach teacher teachers instructor lecturer professor tutor worker workers entrepreneur model ' + 'photographer potter artist florist mother father parent parents grandmother grandfather grandparents ' + 'faculty staff team participants volunteer volunteers musician dancer leader manager owner founder ' + 'journalist journalists reporter reporters master masters lovers newlywed newlyweds husband wife fiance fiancee spouse ' + // Whoever else is about (AGL-3988): "A family with tourists" was a family.
|
|
3218
|
+
'tourist tourists traveler travelers traveller travellers hiker hikers visitor visitors friend friends crowd ' + // A family's people, said as a parent with a child (AGL-3988).
|
|
3219
|
+
'dad dads mom moms mum mums son sons daughter daughters toddler toddlers');
|
|
3220
|
+
/** People said by no role: a model is whoever posed (AGL-3856), "a woman" of "woman, model, show, teacher". */ const GENERIC_PEOPLE = words('man men woman women person people human humans guy guys lady ladies adult boy boys girl girls model models ' + 'tourist tourists traveler travelers traveller travellers hiker hikers visitor visitors friend friends crowd');
|
|
3221
|
+
/** A parent a photo shows, said with the child beside them: "A father with a girl" (AGL-3988). */ const PARENTS = words('father mother dad mom mum parent parents grandfather grandmother grandparent grandparents');
|
|
3222
|
+
/** A child a photo shows beside a parent (AGL-3988). */ const CHILDREN = words('child children kid kids baby babies toddler toddlers girl girls boy boys son sons daughter daughters');
|
|
3223
|
+
/** How a family's word is said: "a dad" is a father (AGL-3988). */ const SAID_AS = {
|
|
3224
|
+
dad: 'father',
|
|
3225
|
+
dads: 'fathers',
|
|
3226
|
+
mom: 'mother',
|
|
3227
|
+
moms: 'mothers',
|
|
3228
|
+
mum: 'mother',
|
|
3229
|
+
mums: 'mothers'
|
|
3230
|
+
};
|
|
3143
3231
|
/**
|
|
3144
3232
|
* A body's parts, never a thing a photo is described by (AGL-3856): "A girl
|
|
3145
3233
|
* with a hand" said nothing, and "A body in a gym" is a gym.
|
|
@@ -3209,13 +3297,46 @@ function jobPhotos(key) {
|
|
|
3209
3297
|
cliff: 'on',
|
|
3210
3298
|
river: 'by',
|
|
3211
3299
|
lake: 'by',
|
|
3300
|
+
lakeside: 'by',
|
|
3301
|
+
lakeshore: 'by',
|
|
3302
|
+
sea: 'by',
|
|
3303
|
+
ocean: 'by',
|
|
3304
|
+
seaside: 'by',
|
|
3305
|
+
coast: 'on',
|
|
3306
|
+
shore: 'on',
|
|
3307
|
+
sundown: 'at',
|
|
3212
3308
|
waterfall: 'at'
|
|
3213
3309
|
};
|
|
3214
3310
|
/** Places that are things too, a photo's subject where nothing else is: "a desk in a classroom". */ const OBJECT_PLACES = words('desk table counter bridge bed sofa couch bench');
|
|
3215
|
-
/** Places said without an article: "in court", "at sunset". */ const BARE_PLACES = words('court sunset sunrise dusk dawn');
|
|
3311
|
+
/** Places said without an article: "in court", "at sunset". */ const BARE_PLACES = words('court sunset sunrise sundown dusk dawn');
|
|
3216
3312
|
/** Places said in words of their own: a mountain tag is "in the mountains". */ const PLACES_SAID = {
|
|
3217
|
-
mountain: 'the mountains'
|
|
3313
|
+
mountain: 'the mountains',
|
|
3314
|
+
lakeside: 'the lake',
|
|
3315
|
+
lakeshore: 'the lake',
|
|
3316
|
+
sea: 'the sea',
|
|
3317
|
+
ocean: 'the ocean',
|
|
3318
|
+
seaside: 'the sea',
|
|
3319
|
+
coast: 'the coast',
|
|
3320
|
+
shore: 'the shore'
|
|
3218
3321
|
};
|
|
3322
|
+
/** Places that say when, said after where: "a couple in the mountains at sunset" (AGL-3988). */ const TIME_PLACES = words('sunset sunrise sundown dusk dawn');
|
|
3323
|
+
/** Places out of doors, said after a thing to sit on: "a couple on a bench by the lake" (AGL-3988). */ const OUTDOORS = words('forest field meadow valley mountain hill cliff river lake lakeside lakeshore waterfall beach park garden trail sea ocean seaside coast shore');
|
|
3324
|
+
/** Words inside a tag that say one thing is where another is: "couple on bench" (AGL-3988). */ const TAG_PREPOSITIONS = words('on in at by with under near beside');
|
|
3325
|
+
/**
|
|
3326
|
+
* A tag that is a phrase of its own, read as its parts (AGL-3988): "couple
|
|
3327
|
+
* on bench" is a couple, and a bench they are on. The beta.270 Sugar Hollow
|
|
3328
|
+
* About page read it whole, as a place, and said "A lakeside on a couple on
|
|
3329
|
+
* bench".
|
|
3330
|
+
*/ function tagParts(tag) {
|
|
3331
|
+
const list = tag.toLowerCase().trim().split(/\s+/);
|
|
3332
|
+
const at = list.findIndex((word, index)=>index > 0 && index < list.length - 1 && TAG_PREPOSITIONS.has(word));
|
|
3333
|
+
return at > 0 ? [
|
|
3334
|
+
list.slice(0, at).join(' '),
|
|
3335
|
+
list.slice(at + 1).join(' ')
|
|
3336
|
+
] : [
|
|
3337
|
+
tag
|
|
3338
|
+
];
|
|
3339
|
+
}
|
|
3219
3340
|
/** How many of a photo's first tags its description reads: the things and people it is OF. */ const ALT_TAGS_READ = 8;
|
|
3220
3341
|
/** How far a photo's tags are read for where it is set, said last: "in a gym" of a kettlebell's seventh tag. */ const ALT_PLACE_TAGS_READ = 10;
|
|
3221
3342
|
/** A tag's words, a word for the photo itself taken off a compound: "photo-camera" is a camera. */ function tagWords(tag) {
|
|
@@ -3290,15 +3411,31 @@ function jobPhotos(key) {
|
|
|
3290
3411
|
* - a second thing comes only from the first two tags and where no place is
|
|
3291
3412
|
* said, what a person holds only from the first three, where it is set
|
|
3292
3413
|
* from the first ten;
|
|
3293
|
-
* - no word is said twice: never "an elderly couple and an elderly"
|
|
3414
|
+
* - no word is said twice: never "an elderly couple and an elderly";
|
|
3415
|
+
* - the sky, the clouds and the light are no thing anyone holds, and the
|
|
3416
|
+
* weather is said as where it is: "a couple in the fog at a wedding",
|
|
3417
|
+
* "a couple in the snow in the mountains", never "a couple with a sky at
|
|
3418
|
+
* sunset" or "a snow in the mountains"; a feeling ("care", "worry") is no
|
|
3419
|
+
* thing either; whoever else is about ("tourists") is never said beside a
|
|
3420
|
+
* family; a parent beside a child is said with them ("a father with a
|
|
3421
|
+
* girl"); a tag that is a phrase of its own ("couple on bench") is read as
|
|
3422
|
+
* its parts; a time of day comes after where ("in the mountains at
|
|
3423
|
+
* sunset"), and a bench out of doors says where it stands ("on a bench by
|
|
3424
|
+
* the lake") (AGL-3988).
|
|
3294
3425
|
*
|
|
3295
3426
|
* `null` where no tag names a thing.
|
|
3296
3427
|
*/ export function aiStockTagsAlt(tags, proper = new Set()) {
|
|
3428
|
+
var _ref;
|
|
3297
3429
|
const parts = [];
|
|
3298
3430
|
let quality = '';
|
|
3299
3431
|
let portrait = false;
|
|
3300
|
-
|
|
3301
|
-
|
|
3432
|
+
/** The weather it is in, said as where ({@link WEATHER}). */ let weather = '';
|
|
3433
|
+
const read = tags.slice(0, ALT_PLACE_TAGS_READ).flatMap((tag, index)=>tagParts(tag).map((part)=>({
|
|
3434
|
+
tag: part,
|
|
3435
|
+
index
|
|
3436
|
+
})));
|
|
3437
|
+
for (const { tag, index } of read){
|
|
3438
|
+
var _ref1;
|
|
3302
3439
|
var _bare_split_pop;
|
|
3303
3440
|
const lower = tag.toLowerCase().trim();
|
|
3304
3441
|
const reading = index < ALT_TAGS_READ;
|
|
@@ -3310,11 +3447,18 @@ function jobPhotos(key) {
|
|
|
3310
3447
|
if (reading) quality || (quality = lower);
|
|
3311
3448
|
continue;
|
|
3312
3449
|
}
|
|
3313
|
-
|
|
3450
|
+
// The sky is never a thing a photo is described by; the weather is where it is.
|
|
3451
|
+
if (SCENERY.has(lower)) continue;
|
|
3452
|
+
if (WEATHER[lower]) {
|
|
3453
|
+
if (reading) weather || (weather = WEATHER[lower]);
|
|
3454
|
+
continue;
|
|
3455
|
+
}
|
|
3456
|
+
const family = SAID_AS[lower];
|
|
3457
|
+
const said = family ? `${articleFor(family)} ${family}`.replace(/^an? (?=\S+s$)/, '') : describedTag(tag, proper);
|
|
3314
3458
|
if (!said) continue;
|
|
3315
3459
|
const bare = said.replace(/^an?\s+/, '');
|
|
3316
3460
|
const stems = stemList(bare);
|
|
3317
|
-
const head = (
|
|
3461
|
+
const head = (_ref1 = (_bare_split_pop = bare.split(/\s+/).pop()) == null ? void 0 : _bare_split_pop.toLowerCase()) != null ? _ref1 : '';
|
|
3318
3462
|
if (!head) continue;
|
|
3319
3463
|
const headStem = aiStockStem(head);
|
|
3320
3464
|
const kind = PEOPLE_NOUNS.has(head) || PEOPLE_NOUNS.has(headStem) ? 'person' : PLACES[headStem] ? 'place' : 'thing';
|
|
@@ -3358,7 +3502,12 @@ function jobPhotos(key) {
|
|
|
3358
3502
|
// silhouettes, camera, nature, photographer" men with a camera.
|
|
3359
3503
|
const leads = (part)=>portrait || part.index < ALT_PERSON_TAGS_READ || !things.length;
|
|
3360
3504
|
const role = posed ? undefined : people.find((part)=>!GENERIC_PEOPLE.has(part.head) && part.index < ALT_ROLE_TAGS_READ && leads(part));
|
|
3361
|
-
|
|
3505
|
+
// A parent beside a child is said with them (AGL-3988): "A father with a
|
|
3506
|
+
// girl", never "a child with clouds" of "child, clouds, dad, dock, father".
|
|
3507
|
+
const parent = people.find((part)=>PARENTS.has(part.head) && part.index < ALT_ROLE_TAGS_READ);
|
|
3508
|
+
const child = people.find((part)=>CHILDREN.has(part.head) && part.index < ALT_ROLE_TAGS_READ);
|
|
3509
|
+
const family = parent && child && (!role || role === parent || role === child) ? parent : undefined;
|
|
3510
|
+
const person = (_ref = family != null ? family : role) != null ? _ref : people.find(leads);
|
|
3362
3511
|
// Nothing but places: a desk is the thing in a classroom; "a school in a classroom" says one place.
|
|
3363
3512
|
if (!person && !things.length && places.length > 1) {
|
|
3364
3513
|
const object = places.find((part)=>OBJECT_PLACES.has(part.head));
|
|
@@ -3370,7 +3519,7 @@ function jobPhotos(key) {
|
|
|
3370
3519
|
} else places = places.slice(0, 1);
|
|
3371
3520
|
}
|
|
3372
3521
|
const place = places[0];
|
|
3373
|
-
if (!person && !things.length && !place) return null;
|
|
3522
|
+
if (!person && !things.length && !place && !weather) return null;
|
|
3374
3523
|
/** Every word said so far, so none is said twice. */ const said = new Set();
|
|
3375
3524
|
const fresh = (part)=>{
|
|
3376
3525
|
const list = stemList(part.said.replace(/^an?\s+/, ''));
|
|
@@ -3382,18 +3531,40 @@ function jobPhotos(key) {
|
|
|
3382
3531
|
let phrase = '';
|
|
3383
3532
|
if (person && fresh(person)) {
|
|
3384
3533
|
phrase = portrait ? `a portrait of ${person.said}` : qualified(person);
|
|
3385
|
-
const held = things.find((part)=>part.index <= 2);
|
|
3534
|
+
const held = family && child && child !== person ? child : things.find((part)=>part.index <= 2);
|
|
3386
3535
|
if (!portrait && held && fresh(held)) phrase += ` ${CLOTHING.has(held.head) ? 'in' : 'with'} ${held.said}`;
|
|
3387
3536
|
} else if (things[0] && fresh(things[0])) {
|
|
3388
3537
|
phrase = qualified(things[0]);
|
|
3389
3538
|
const second = things[1];
|
|
3390
3539
|
if (second && second.index <= 1 && !place && fresh(second)) phrase += ` and ${second.said}`;
|
|
3391
3540
|
}
|
|
3541
|
+
/** A place as it is said alone: "a classroom", "the mountains", "sunset". */ const placeOf = (part)=>{
|
|
3542
|
+
var _PLACES_SAID_part_head;
|
|
3543
|
+
return (_PLACES_SAID_part_head = PLACES_SAID[part.head]) != null ? _PLACES_SAID_part_head : BARE_PLACES.has(part.head) && /^an? \S+$/.test(part.said) ? part.head : part.said;
|
|
3544
|
+
};
|
|
3545
|
+
/** A place as it is said after what is there: "in the mountains", "at sunset", "on a bench". */ const whereOf = (part)=>{
|
|
3546
|
+
var _PLACES_part_head;
|
|
3547
|
+
return `${(_PLACES_part_head = PLACES[part.head]) != null ? _PLACES_part_head : 'in'} ${placeOf(part)}`;
|
|
3548
|
+
};
|
|
3549
|
+
// The weather is said before where (AGL-3988): "a couple in the fog at a
|
|
3550
|
+
// wedding"; alone, it is what the photo shows: "snow in the mountains".
|
|
3551
|
+
if (weather && phrase) phrase += ` ${weather}`;
|
|
3552
|
+
else if (weather) phrase = weather.replace(/^in the /, '');
|
|
3392
3553
|
if (place && fresh(place)) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3554
|
+
// A second place where the first is a time of day or a bench out of
|
|
3555
|
+
// doors: "a couple in the mountains at sunset", "a couple on a bench by
|
|
3556
|
+
// the lake"; never a bed in a room.
|
|
3557
|
+
const second = places.find((part)=>part !== place && !OBJECT_PLACES.has(part.head) && !TIME_PLACES.has(part.head) && (TIME_PLACES.has(place.head) || place.head === 'bench' && OUTDOORS.has(part.head)));
|
|
3558
|
+
const after = second && fresh(second) ? second : null;
|
|
3559
|
+
const [first, last] = after && TIME_PLACES.has(place.head) ? [
|
|
3560
|
+
after,
|
|
3561
|
+
place
|
|
3562
|
+
] : [
|
|
3563
|
+
place,
|
|
3564
|
+
after
|
|
3565
|
+
];
|
|
3566
|
+
const tail = last ? ` ${whereOf(last)}` : '';
|
|
3567
|
+
phrase = phrase ? `${phrase} ${whereOf(first)}${tail}` : `${placeOf(first)}${tail}`;
|
|
3397
3568
|
}
|
|
3398
3569
|
// Never a dangling article or preposition, whatever a tag left behind.
|
|
3399
3570
|
phrase = phrase.replace(DANGLING_END, '').trim();
|