feat: complete TASK-WP5-03 asset allowlist
Dada P0-A isolated Windows CI / validate-and-package (push) Failing after 1m5s

This commit is contained in:
suyx
2026-08-03 18:24:16 +08:00
parent 609c71a3f7
commit 4d1ec8ba7e
27 changed files with 1078 additions and 74 deletions
+9 -2
View File
@@ -1,4 +1,5 @@
import type { CanvasState } from "@dada/shared-contracts";
import { P0A_DYNAMIC_STICKER_IDS } from "@dada/template-registry";
import { DYNAMIC_RESOURCE_VERSION } from "./dynamic-render-models.js";
import type { CanvasElementIdentity } from "./editor-elements.js";
@@ -6,7 +7,7 @@ import type { CanvasElementIdentity } from "./editor-elements.js";
type CanvasElement = CanvasState["elements"][number];
export type DynamicCategory = "identity" | "location" | "other" | "time";
export type DynamicTemplateId = "DYN001" | "DYN002" | "DYN003" | "DYN004" | "DYN007" | "DYN008" | "DYN011" | "DYN012" | "DYN015" | "DYN016";
export type DynamicTemplateId = typeof P0A_DYNAMIC_STICKER_IDS[number];
export interface DynamicStickerDefinition {
category: DynamicCategory;
@@ -44,7 +45,7 @@ export function dyn012DisplayParts(element: CanvasElement) {
} as const;
}
export const P0A_DYNAMIC_STICKERS: readonly DynamicStickerDefinition[] = [
const dynamicDefinitions: readonly DynamicStickerDefinition[] = [
{ category: "location", displayName: "地点标题", requiresLocationConsent: false, templateId: "DYN001" },
{ category: "location", displayName: "英文地点", requiresLocationConsent: false, templateId: "DYN002" },
{ category: "location", displayName: "城市地点", requiresLocationConsent: false, templateId: "DYN003" },
@@ -57,6 +58,12 @@ export const P0A_DYNAMIC_STICKERS: readonly DynamicStickerDefinition[] = [
{ category: "identity", displayName: "社交 ID", requiresLocationConsent: false, templateId: "DYN016" },
] as const;
export const P0A_DYNAMIC_STICKERS: readonly DynamicStickerDefinition[] = P0A_DYNAMIC_STICKER_IDS.map((templateId) => {
const definition = dynamicDefinitions.find((item) => item.templateId === templateId);
if (!definition) throw new Error(`missing dynamic sticker definition ${templateId}`);
return definition;
});
function twoDigits(value: number) {
return String(value).padStart(2, "0");
}
+3 -13
View File
@@ -1,17 +1,12 @@
import { MMCQ } from "@vibrant/quantizer-mmcq";
import type { CanvasState } from "@dada/shared-contracts";
import { P0A_COLOR_CARD_DEFINITIONS, type ColorCardDefinition } from "@dada/asset-renderer";
import type { CanvasElementIdentity } from "./editor-elements.js";
type CanvasElement = CanvasState["elements"][number];
export interface ColorCardDefinition {
cardId: "COLOR001" | "COLOR002" | "COLOR008" | "COLOR016";
displayName: string;
mappingStatus: "confirmed_native_mapping" | "stable_web_style_native_mapping_provisional";
rendererName: "horizontal_line" | "ticket_strip" | "vertical_stack" | "vertical_ticket";
styleId: "style_01" | "style_02" | "style_08" | "style_16";
}
export type { ColorCardDefinition } from "@dada/asset-renderer";
export interface PaletteColor {
hex: string;
@@ -19,12 +14,7 @@ export interface PaletteColor {
rgbValue: number;
}
export const P0A_COLOR_CARDS: readonly ColorCardDefinition[] = [
{ cardId: "COLOR001", displayName: "纵向票据", mappingStatus: "confirmed_native_mapping", rendererName: "vertical_ticket", styleId: "style_01" },
{ cardId: "COLOR002", displayName: "纵向色阶", mappingStatus: "stable_web_style_native_mapping_provisional", rendererName: "vertical_stack", styleId: "style_02" },
{ cardId: "COLOR008", displayName: "横向标尺", mappingStatus: "stable_web_style_native_mapping_provisional", rendererName: "horizontal_line", styleId: "style_08" },
{ cardId: "COLOR016", displayName: "横向票条", mappingStatus: "stable_web_style_native_mapping_provisional", rendererName: "ticket_strip", styleId: "style_16" },
] as const;
export const P0A_COLOR_CARDS: readonly ColorCardDefinition[] = P0A_COLOR_CARD_DEFINITIONS;
// Coordinates are translated from the archived 320x320 renderer around its 160px center.
export const COLOR_CARD_SOURCE_GEOMETRY = {
+39 -18
View File
@@ -1,4 +1,5 @@
import type { CanvasState } from "@dada/shared-contracts";
import { P0A_REQUIRED_FONT_PANEL_IDS, P0A_TEXT_TEMPLATE_IDS } from "@dada/template-registry";
import type { CanvasElementIdentity } from "./editor-elements.js";
@@ -92,25 +93,45 @@ const seeds: readonly CatalogSeed[] = [
["SIMPLE008", "simple", "周五愉快", "周五愉快", "SIMPLE008_FONT"],
];
export const P0A_TEXT_TEMPLATES: readonly TextTemplateDefinition[] = seeds.map((seed, catalogOrder) => ({
available: seed[5] === true,
catalogOrder,
category: seed[1],
defaultFontId: seed[4],
defaultFontSize: 48,
defaultText: seed[3],
displayName: seed[2],
...(seed[5] === true ? { fontUrl: `/api/v1/assets/public/${fixtureVersion}/${seed[4]}` } : {}),
resourceClass: seed[6] ?? "zip_template",
resourceVersion: fixtureVersion,
templateId: seed[0],
}));
const seedById = new Map(seeds.map((seed) => [seed[0], seed]));
export const P0A_FONT_OPTIONS: readonly FontOption[] = [
{ displayName: "默陌手写", fontId: "FONT011", url: `/api/v1/assets/public/${fixtureVersion}/FONT011` },
{ displayName: "字由油漆", fontId: "FONT039", url: `/api/v1/assets/public/${fixtureVersion}/FONT039` },
{ displayName: "Lexend Deca", fontId: "FONT081", url: `/api/v1/assets/public/${fixtureVersion}/FONT081` },
];
export const P0A_TEXT_TEMPLATES: readonly TextTemplateDefinition[] = P0A_TEXT_TEMPLATE_IDS.map((templateId, catalogOrder) => {
const seed = seedById.get(templateId);
if (!seed) throw new Error(`missing text template definition ${templateId}`);
return {
available: seed[5] === true,
catalogOrder,
category: seed[1],
defaultFontId: seed[4],
defaultFontSize: 48,
defaultText: seed[3],
displayName: seed[2],
...(seed[5] === true ? { fontUrl: `/api/v1/assets/public/${fixtureVersion}/${seed[4]}` } : {}),
resourceClass: seed[6] ?? "zip_template",
resourceVersion: fixtureVersion,
templateId,
};
});
const fontOptionDefinitions: Readonly<Record<typeof P0A_REQUIRED_FONT_PANEL_IDS[number], string>> = {
FONT005: "Rammetto",
FONT008: "正圆体",
FONT011: "默陌手写",
FONT021: "喜月体",
FONT022: "素白体",
FONT027: "锐正圆",
FONT039: "字由油漆",
FONT043: "喜脉体",
FONT046: "可口可乐",
FONT052: "Oraqle Script",
FONT081: "Lexend Deca",
};
export const P0A_FONT_OPTIONS: readonly FontOption[] = P0A_REQUIRED_FONT_PANEL_IDS.map((fontId) => ({
displayName: fontOptionDefinitions[fontId],
fontId,
url: `/api/v1/assets/public/${fixtureVersion}/${fontId}`,
}));
export function fontOption(fontId: string) {
return P0A_FONT_OPTIONS.find((option) => option.fontId === fontId);