@vectoriox/iox-ui 5.59.1 → 5.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6296,29 +6296,47 @@ declare function publishVerdict(audit: SiteAudit, acknowledged?: ReadonlyArray<s
6296
6296
  * into the studio's own storage (never hot-linked), placed only in an EMPTY picture slot of a section that may show
6297
6297
  * one — never the owner's work (a collection, a detail page, a gallery: what the nine portfolio types sell is theirs),
6298
6298
  * never a person (testimonials, the team), never anywhere when the business type says `stock: false`. Its alt text is
6299
- * the provider's description of what it shows (never a claim), and the credit line its licence requires is placed in
6300
- * the footer. Pure: the build step does the copying.
6299
+ * the provider's description of what it shows (never a claim), and the credit line its licence requires — when it
6300
+ * requires one — is placed in the footer. Pure: the build step does the copying.
6301
6301
  */
6302
6302
  /** Where a stock photo comes from (the library's provider). */
6303
6303
  declare enum StockProviderId {
6304
- Magnific = "magnific"
6304
+ Magnific = "magnific",
6305
+ Pixabay = "pixabay"
6305
6306
  }
6306
- /** What a picture's licence asks of the site that shows it. */
6307
+ /** Words and the address they link to. */
6308
+ interface StockLink {
6309
+ line: string;
6310
+ url: string;
6311
+ }
6312
+ /** What a provider's terms ask of IOX, per provider — the ONE place a credit line is decided. */
6313
+ interface StockProviderTerms {
6314
+ name: string;
6315
+ /** The line a site showing one of its pictures must carry (in the footer), or null when its licence asks none. */
6316
+ credit: StockLink | null;
6317
+ /** What to show wherever its SEARCH RESULTS are displayed — the operator's review of the library, never a site. */
6318
+ sourceNotice: StockLink;
6319
+ }
6320
+ /**
6321
+ * The providers' terms (AI plan §3g, I2; read 2026-10-25 / 2026-10-27). Magnific's free licence requires "Designed by
6322
+ * Magnific", linked, next to the resource or in the site's footer. Pixabay's Content License: "You do not need to credit
6323
+ * Pixabay or the contributor" — but its API asks to "show your users where the images and videos are from, whenever
6324
+ * search results are displayed", which only the operator's review does.
6325
+ */
6326
+ declare const STOCK_PROVIDER_TERMS: Readonly<Record<StockProviderId, StockProviderTerms>>;
6327
+ /** Where a picture came from and under which licence — recorded with every library photo and every studio copy. */
6307
6328
  interface StockCredit {
6308
6329
  provider: `${StockProviderId}`;
6309
6330
  /** The provider's id of the picture. */
6310
6331
  resourceId: string;
6311
6332
  /** The provider's page for it. */
6312
6333
  sourceUrl: string;
6313
- /** The provider's own title — what the picture shows. */
6334
+ /** The provider's own words for what the picture shows (Magnific's title, Pixabay's tags). */
6314
6335
  title: string;
6315
6336
  author: string;
6316
- /** `freemium` — the free licence (premium pictures never enter the library). */
6337
+ /** The licence it is used under, as the provider names it (Magnific `freemium`, Pixabay `content-license`). */
6317
6338
  licence: string;
6318
6339
  licenceUrl: string;
6319
- /** The words the licence requires, and where they link. */
6320
- line: string;
6321
- lineUrl: string;
6322
6340
  }
6323
6341
  /** One picture of the platform library (`iox-stock/<type>/`), as its manifest lists it. */
6324
6342
  interface StockPhoto {
@@ -6356,26 +6374,19 @@ declare function applyStockPhotos(trees: ReadonlyArray<SerializedNode>, placed:
6356
6374
  url: string;
6357
6375
  alt: string;
6358
6376
  }>): number;
6359
- /** The credit lines a set of photos needs — one per distinct line (a free Magnific photo: "Designed by Magnific"). */
6360
- declare function stockCreditLines(photos: ReadonlyArray<Pick<StockPhoto, 'credit'>>): Array<{
6361
- line: string;
6362
- url: string;
6363
- }>;
6377
+ /** The line a picture's licence requires on the site, or null when it requires none (`STOCK_PROVIDER_TERMS`). */
6378
+ declare function stockCreditLine(credit: Pick<StockCredit, 'provider'>): StockLink | null;
6379
+ /** The credit lines a set of photos needs — one per distinct line, none for a provider whose licence asks none. */
6380
+ declare function stockCreditLines(photos: ReadonlyArray<Pick<StockPhoto, 'credit'>>): StockLink[];
6364
6381
  /** The footer node id of a credit line (stable — a build that runs twice finds it). */
6365
6382
  declare const stockCreditNodeId: (index: number) => string;
6366
6383
  /**
6367
6384
  * The credit line, as the builder would create a Link (a plain node the owner may move or restyle): the licence's words,
6368
6385
  * linking where it asks, opening in a new tab. Placed at the end of the footer — the place the licence names for a site.
6369
6386
  */
6370
- declare function stockCreditNode(index: number, credit: {
6371
- line: string;
6372
- url: string;
6373
- }): SerializedNode;
6387
+ declare function stockCreditNode(index: number, credit: StockLink): SerializedNode;
6374
6388
  /** Append the credit lines to the footer root (once each). Returns how many it added. */
6375
- declare function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<{
6376
- line: string;
6377
- url: string;
6378
- }>): number;
6389
+ declare function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<StockLink>): number;
6379
6390
 
6380
- export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, AI_STEP_TYPICAL_TOKENS, AiCallStatus, AiCapability, AiFeature, AiGenerationStage, AiKeyMode, AiLimit, AiNextKind, AiProviderId, AiRefusalCode, AiStep, BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BUILD_STEPS, BaselineRole, BindScope, BuildNoticeCode, BuildStep, CONTENT_ROLE_MEANINGS, CREDITS_PER_USD, CardBindTarget, CheckSeverity, ComposeError, ComposeIssueCode, ContentRole, ContentTypeAction, CreatedKind, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, DEFAULT_SITE_LOCALE, ENTRANCE_EASING, ENTRANCE_ORIGIN_LOOK, ENTRANCE_TRIGGER, EntrancePart, EntranceSide, FACT_KEYS, FINAL_GENERATION_STAGES, FINDING_SEVERITY, GlobalSlot, HEBREW_PREFIXES, JSON_SCHEMA_BANNED_KEYWORDS, JsonSchemaShapeError, KeptReason, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NO_TOKENS, NavPagesSource, NavRole, NavShape, NavShapeError, PAGE_ARCHETYPES, PLAN_EDITS_ANSWER_SHAPE, PLAN_EDITS_SCHEMA_NAME, PLAN_EDIT_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, PlanWordIssueCode, PreflightRefusalCode, PublishRefusalCode, REQUIRED_CONTENT_ROLES, RelativeOp, SAMPLE_IMAGE_REF, SITE_CHECKS, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_LIBRARY, SITE_LOCALES, SITE_NEED_IDS, SITE_PATTERNS, SITE_PLAN_SCHEMA_NAME, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_ARCHETYPES, SPEC_SITE_COPY_LENGTHS, SPEC_SITE_DENSITY_COPY, SPEC_SITE_FACTS, SPEC_SITE_LIBRARY, SPEC_SITE_LOCALES, SPEC_SITE_NEED_IDS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES, SPEC_SITE_TEMPLATES, STOCK_FAMILIES, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SitePlanWireKey, SiteTemplateError, SiteTemplateId, StepState, StockProviderId, addBarItem, addStockCredits, applyPlanEdits, applyStockPhotos, archetypeIssues, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypeFromWire, contentTypeJsonSchema, contentTypePreviewFields, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceJsonSchema, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, failedBuildStep, fieldJsonSchema, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, pageJsonSchema, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditsFromWire, planEditsJsonSchema, planEntrances, planFromTemplate, planNavShape, planStockPhotos, planWordIssues, publishRefusal, publishVerdict, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, sectionEntrances, sectionFromWire, sectionJsonSchema, sectionPatternIds, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, sitePlanFromWire, sitePlanJsonSchema, sitePlanToWire, slotBudget, stockCopyKey, stockCreditLines, stockCreditNode, stockCreditNodeId, stockSlots, validatePlanEdits, validateSitePlan, walkSerialized, wordPattern, writtenTexts };
6381
- export type { AddBarItemResult, AiEntitlementsView, AiMeter, AiModelEntry, AiRefusal, AiTokenCounts, AiTokenPrice, AuditPage, AuditPlaceholder, BarItemsEditResult, BuildNotice, BuildStepError, BuildStepFacts, BuildStepRecord, CmsDataSourcePlan, ComposeContext, ComposeIssue, ComposedDataSource, ComposedItem, ComposedNavHeader, ComposedPage, ComposedPlaceholder, ComposedRoute, ComposedSection, ComposedSite, ContentFieldPlan, ContentRoles, ContentSeedPlan, ContentTypePlan, CreateNodeOptions, CreatedRecord, DataSourcePlan, DynamicKeysAsList, EntranceAction, EntranceActionOptions, EntranceInteraction, EntranceMark, EntranceSpec, EntranceStamp, FactKey, JsonSchema, NavHeaderInput, NavHeaderOptions, NavPage, NavShapeOptions, NavShapeResult, NodeBaseline, PageArchetype, PageArchetypeId, PageArchetypeSlot, PageData, PageDataLine, PagePlan, PageSectionPlan, PageSeoPlan, PathIssue, PatternManifestEntry, PatternNode, PatternPath, PatternRoleNeed, PlainObject, PlanChange, PlanEdit, PlanEditIssue, PlanEditResult, PlanEditsAnswer, PlanEntrancesInput, PlanWordContext, PlanWordIssue, PreflightRefusal, PublishRefusal, RelativeDataSourcePlan, SectionEntrances, SectionInput, SectionOptions, SerializedBinding, SerializedNode, SerializedResponsive, ShapeEntry, ShapeIssueCodes, ShowcaseInput, SiteAudit, SiteAuditOptions, SiteAuditSnapshot, SiteBuildRun, SiteBusiness, SiteCheck, SiteFinding, SiteNeedId, SitePageRef, SitePattern, SitePlan, SitePlanIssue, SitePlanSchemaPin, SitePlanSource, SitePlanValidation, SiteTemplate, StockCredit, StockPhoto, StockPlacement, StockSlot, TemplatePlanInput, UndoKept, UndoPreview, UndoRecord, WrittenText };
6391
+ export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, AI_STEP_TYPICAL_TOKENS, AiCallStatus, AiCapability, AiFeature, AiGenerationStage, AiKeyMode, AiLimit, AiNextKind, AiProviderId, AiRefusalCode, AiStep, BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BUILD_STEPS, BaselineRole, BindScope, BuildNoticeCode, BuildStep, CONTENT_ROLE_MEANINGS, CREDITS_PER_USD, CardBindTarget, CheckSeverity, ComposeError, ComposeIssueCode, ContentRole, ContentTypeAction, CreatedKind, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, DEFAULT_SITE_LOCALE, ENTRANCE_EASING, ENTRANCE_ORIGIN_LOOK, ENTRANCE_TRIGGER, EntrancePart, EntranceSide, FACT_KEYS, FINAL_GENERATION_STAGES, FINDING_SEVERITY, GlobalSlot, HEBREW_PREFIXES, JSON_SCHEMA_BANNED_KEYWORDS, JsonSchemaShapeError, KeptReason, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NO_TOKENS, NavPagesSource, NavRole, NavShape, NavShapeError, PAGE_ARCHETYPES, PLAN_EDITS_ANSWER_SHAPE, PLAN_EDITS_SCHEMA_NAME, PLAN_EDIT_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, PlanWordIssueCode, PreflightRefusalCode, PublishRefusalCode, REQUIRED_CONTENT_ROLES, RelativeOp, SAMPLE_IMAGE_REF, SITE_CHECKS, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_LIBRARY, SITE_LOCALES, SITE_NEED_IDS, SITE_PATTERNS, SITE_PLAN_SCHEMA_NAME, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_ARCHETYPES, SPEC_SITE_COPY_LENGTHS, SPEC_SITE_DENSITY_COPY, SPEC_SITE_FACTS, SPEC_SITE_LIBRARY, SPEC_SITE_LOCALES, SPEC_SITE_NEED_IDS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES, SPEC_SITE_TEMPLATES, STOCK_FAMILIES, STOCK_PROVIDER_TERMS, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SitePlanWireKey, SiteTemplateError, SiteTemplateId, StepState, StockProviderId, addBarItem, addStockCredits, applyPlanEdits, applyStockPhotos, archetypeIssues, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypeFromWire, contentTypeJsonSchema, contentTypePreviewFields, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceJsonSchema, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, failedBuildStep, fieldJsonSchema, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, pageJsonSchema, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditsFromWire, planEditsJsonSchema, planEntrances, planFromTemplate, planNavShape, planStockPhotos, planWordIssues, publishRefusal, publishVerdict, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, sectionEntrances, sectionFromWire, sectionJsonSchema, sectionPatternIds, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, sitePlanFromWire, sitePlanJsonSchema, sitePlanToWire, slotBudget, stockCopyKey, stockCreditLine, stockCreditLines, stockCreditNode, stockCreditNodeId, stockSlots, validatePlanEdits, validateSitePlan, walkSerialized, wordPattern, writtenTexts };
6392
+ export type { AddBarItemResult, AiEntitlementsView, AiMeter, AiModelEntry, AiRefusal, AiTokenCounts, AiTokenPrice, AuditPage, AuditPlaceholder, BarItemsEditResult, BuildNotice, BuildStepError, BuildStepFacts, BuildStepRecord, CmsDataSourcePlan, ComposeContext, ComposeIssue, ComposedDataSource, ComposedItem, ComposedNavHeader, ComposedPage, ComposedPlaceholder, ComposedRoute, ComposedSection, ComposedSite, ContentFieldPlan, ContentRoles, ContentSeedPlan, ContentTypePlan, CreateNodeOptions, CreatedRecord, DataSourcePlan, DynamicKeysAsList, EntranceAction, EntranceActionOptions, EntranceInteraction, EntranceMark, EntranceSpec, EntranceStamp, FactKey, JsonSchema, NavHeaderInput, NavHeaderOptions, NavPage, NavShapeOptions, NavShapeResult, NodeBaseline, PageArchetype, PageArchetypeId, PageArchetypeSlot, PageData, PageDataLine, PagePlan, PageSectionPlan, PageSeoPlan, PathIssue, PatternManifestEntry, PatternNode, PatternPath, PatternRoleNeed, PlainObject, PlanChange, PlanEdit, PlanEditIssue, PlanEditResult, PlanEditsAnswer, PlanEntrancesInput, PlanWordContext, PlanWordIssue, PreflightRefusal, PublishRefusal, RelativeDataSourcePlan, SectionEntrances, SectionInput, SectionOptions, SerializedBinding, SerializedNode, SerializedResponsive, ShapeEntry, ShapeIssueCodes, ShowcaseInput, SiteAudit, SiteAuditOptions, SiteAuditSnapshot, SiteBuildRun, SiteBusiness, SiteCheck, SiteFinding, SiteNeedId, SitePageRef, SitePattern, SitePlan, SitePlanIssue, SitePlanSchemaPin, SitePlanSource, SitePlanValidation, SiteTemplate, StockCredit, StockLink, StockPhoto, StockPlacement, StockProviderTerms, StockSlot, TemplatePlanInput, UndoKept, UndoPreview, UndoRecord, WrittenText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectoriox/iox-ui",
3
- "version": "5.59.1",
3
+ "version": "5.60.0",
4
4
  "peerDependencies": {
5
5
  "@angular/common": ">=20.0.0",
6
6
  "@angular/core": ">=20.0.0",
@@ -8,31 +8,63 @@ import { SitePlan } from './site-plan.model';
8
8
  * into the studio's own storage (never hot-linked), placed only in an EMPTY picture slot of a section that may show
9
9
  * one — never the owner's work (a collection, a detail page, a gallery: what the nine portfolio types sell is theirs),
10
10
  * never a person (testimonials, the team), never anywhere when the business type says `stock: false`. Its alt text is
11
- * the provider's description of what it shows (never a claim), and the credit line its licence requires is placed in
12
- * the footer. Pure: the build step does the copying.
11
+ * the provider's description of what it shows (never a claim), and the credit line its licence requires — when it
12
+ * requires one — is placed in the footer. Pure: the build step does the copying.
13
13
  */
14
14
 
15
15
  /** Where a stock photo comes from (the library's provider). */
16
16
  export enum StockProviderId {
17
17
  Magnific = 'magnific',
18
+ Pixabay = 'pixabay',
18
19
  }
19
20
 
20
- /** What a picture's licence asks of the site that shows it. */
21
+ /** Words and the address they link to. */
22
+ export interface StockLink {
23
+ line: string;
24
+ url: string;
25
+ }
26
+
27
+ /** What a provider's terms ask of IOX, per provider — the ONE place a credit line is decided. */
28
+ export interface StockProviderTerms {
29
+ name: string;
30
+ /** The line a site showing one of its pictures must carry (in the footer), or null when its licence asks none. */
31
+ credit: StockLink | null;
32
+ /** What to show wherever its SEARCH RESULTS are displayed — the operator's review of the library, never a site. */
33
+ sourceNotice: StockLink;
34
+ }
35
+
36
+ /**
37
+ * The providers' terms (AI plan §3g, I2; read 2026-10-25 / 2026-10-27). Magnific's free licence requires "Designed by
38
+ * Magnific", linked, next to the resource or in the site's footer. Pixabay's Content License: "You do not need to credit
39
+ * Pixabay or the contributor" — but its API asks to "show your users where the images and videos are from, whenever
40
+ * search results are displayed", which only the operator's review does.
41
+ */
42
+ export const STOCK_PROVIDER_TERMS: Readonly<Record<StockProviderId, StockProviderTerms>> = {
43
+ [StockProviderId.Magnific]: {
44
+ name: 'Magnific',
45
+ credit: { line: 'Designed by Magnific', url: 'https://www.magnific.com' },
46
+ sourceNotice: { line: 'Designed by Magnific', url: 'https://www.magnific.com' },
47
+ },
48
+ [StockProviderId.Pixabay]: {
49
+ name: 'Pixabay',
50
+ credit: null,
51
+ sourceNotice: { line: 'Images from Pixabay', url: 'https://pixabay.com/' },
52
+ },
53
+ };
54
+
55
+ /** Where a picture came from and under which licence — recorded with every library photo and every studio copy. */
21
56
  export interface StockCredit {
22
57
  provider: `${StockProviderId}`;
23
58
  /** The provider's id of the picture. */
24
59
  resourceId: string;
25
60
  /** The provider's page for it. */
26
61
  sourceUrl: string;
27
- /** The provider's own title — what the picture shows. */
62
+ /** The provider's own words for what the picture shows (Magnific's title, Pixabay's tags). */
28
63
  title: string;
29
64
  author: string;
30
- /** `freemium` — the free licence (premium pictures never enter the library). */
65
+ /** The licence it is used under, as the provider names it (Magnific `freemium`, Pixabay `content-license`). */
31
66
  licence: string;
32
67
  licenceUrl: string;
33
- /** The words the licence requires, and where they link. */
34
- line: string;
35
- lineUrl: string;
36
68
  }
37
69
 
38
70
  /** One picture of the platform library (`iox-stock/<type>/`), as its manifest lists it. */
@@ -105,10 +137,18 @@ export function applyStockPhotos(trees: ReadonlyArray<SerializedNode>, placed: R
105
137
  return changed;
106
138
  }
107
139
 
108
- /** The credit lines a set of photos needs — one per distinct line (a free Magnific photo: "Designed by Magnific"). */
109
- export function stockCreditLines(photos: ReadonlyArray<Pick<StockPhoto, 'credit'>>): Array<{ line: string; url: string }> {
140
+ /** The line a picture's licence requires on the site, or null when it requires none (`STOCK_PROVIDER_TERMS`). */
141
+ export function stockCreditLine(credit: Pick<StockCredit, 'provider'>): StockLink | null {
142
+ return STOCK_PROVIDER_TERMS[credit.provider as StockProviderId]?.credit ?? null;
143
+ }
144
+
145
+ /** The credit lines a set of photos needs — one per distinct line, none for a provider whose licence asks none. */
146
+ export function stockCreditLines(photos: ReadonlyArray<Pick<StockPhoto, 'credit'>>): StockLink[] {
110
147
  const seen = new Map<string, string>();
111
- for (const p of photos) if (!seen.has(p.credit.line)) seen.set(p.credit.line, p.credit.lineUrl);
148
+ for (const p of photos) {
149
+ const credit = stockCreditLine(p.credit);
150
+ if (credit && !seen.has(credit.line)) seen.set(credit.line, credit.url);
151
+ }
112
152
  return [...seen.entries()].map(([line, url]) => ({ line, url }));
113
153
  }
114
154
 
@@ -119,12 +159,12 @@ export const stockCreditNodeId = (index: number) => `stock-credit-${index + 1}`;
119
159
  * The credit line, as the builder would create a Link (a plain node the owner may move or restyle): the licence's words,
120
160
  * linking where it asks, opening in a new tab. Placed at the end of the footer — the place the licence names for a site.
121
161
  */
122
- export function stockCreditNode(index: number, credit: { line: string; url: string }): SerializedNode {
162
+ export function stockCreditNode(index: number, credit: StockLink): SerializedNode {
123
163
  return createSerializedNode(stockCreditNodeId(index), 'Link', { label: credit.line, linkType: 'external', url: credit.url, target: '_blank' }, 'link');
124
164
  }
125
165
 
126
166
  /** Append the credit lines to the footer root (once each). Returns how many it added. */
127
- export function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<{ line: string; url: string }>): number {
167
+ export function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<StockLink>): number {
128
168
  footer.children ??= [];
129
169
  let added = 0;
130
170
  credits.forEach((credit, i) => {