diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 5cfcf1df..b1781c36 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -7,6 +7,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: run pre-deploy (build docs and more) + run: | + chmod +x ./scripts/docs-deploy/pre-deploy.sh + ./scripts/docs-deploy/pre-deploy.sh + shell: bash - name: copy docs to gridaco/grida.co uses: DevOpenWRT-Router/github-action-push-to-another-repository@main env: diff --git a/docs/flags/.gitignore b/docs/flags/.gitignore new file mode 100644 index 00000000..a646b350 --- /dev/null +++ b/docs/flags/.gitignore @@ -0,0 +1,7 @@ +## Learn more at scripts/docs-copy/flags-api-docs.js +# custom +----ignore.md +---custom.md + +# flags api docs +--*.md \ No newline at end of file diff --git a/docs/flags/README.md b/docs/flags/README.md new file mode 100644 index 00000000..607c2660 --- /dev/null +++ b/docs/flags/README.md @@ -0,0 +1,5 @@ +# Flags Documentation directory. + +Go to [Index](./index.md) + +## Flags Api references are copied from support-flags package via script - `/scripts/docs-copy/flags-api-docs.sh` diff --git a/docs/flags.md b/docs/flags/index.md similarity index 100% rename from docs/flags.md rename to docs/flags/index.md diff --git a/externals/design-sdk b/externals/design-sdk index 54d7aae0..a958b264 160000 --- a/externals/design-sdk +++ b/externals/design-sdk @@ -1 +1 @@ -Subproject commit 54d7aae0b6b1b41ca7de23f063f09de2c32e3fc0 +Subproject commit a958b264ac2f37fe67e7b9c5dc3eed047b5756c6 diff --git a/externals/reflect-core b/externals/reflect-core index cc76dca6..f0663b2a 160000 --- a/externals/reflect-core +++ b/externals/reflect-core @@ -1 +1 @@ -Subproject commit cc76dca6a282d323353fbc1fa9d784fa06e949bd +Subproject commit f0663b2aa0b76ace158fef054a67a520b01d94eb diff --git a/packages/builder-web-core/widget-core/widget-with-style.ts b/packages/builder-web-core/widget-core/widget-with-style.ts index c7fd8b45..1dd1995e 100644 --- a/packages/builder-web-core/widget-core/widget-with-style.ts +++ b/packages/builder-web-core/widget-core/widget-with-style.ts @@ -27,9 +27,14 @@ export abstract class WidgetWithStyle IWHStyleWidget, IPositionedWidget, IBoxShadowWidget, - IEdgeInsetsWidget { - width?: number; - height?: number; + IEdgeInsetsWidget +{ + width?: DimensionLength; + height?: DimensionLength; + minWidth?: DimensionLength; + minHeight?: DimensionLength; + maxWidth?: DimensionLength; + maxHeight?: DimensionLength; constraint?: { left?: DimensionLength; @@ -90,7 +95,8 @@ export abstract class WidgetWithStyle */ export abstract class MultiChildWidgetWithStyle extends WidgetWithStyle - implements IWidgetWithStyle, IMultiChildJsxWidget { + implements IWidgetWithStyle, IMultiChildJsxWidget +{ readonly children: Array = []; constructor({ key }: { key: WidgetKey }) { diff --git a/packages/builder-web-core/widgets-native/container/index.ts b/packages/builder-web-core/widgets-native/container/index.ts index 26755c90..2c4a9e41 100644 --- a/packages/builder-web-core/widgets-native/container/index.ts +++ b/packages/builder-web-core/widgets-native/container/index.ts @@ -4,6 +4,7 @@ import { Border, BorderRadiusManifest, BoxShadowManifest, + DimensionLength, } from "@reflect-ui/core"; import { Background } from "@reflect-ui/core/lib/background"; import * as css from "@web-builder/styles"; @@ -21,16 +22,28 @@ export class Container extends StylableJsxWidget { key: WidgetKey; x?: number; y?: number; - width?: number; - height?: number; + + width?: DimensionLength; + height?: DimensionLength; + minWidth?: DimensionLength; + maxWidth?: DimensionLength; + minHeight?: DimensionLength; + maxHeight?: DimensionLength; + background?: Background; borderRadius?: BorderRadiusManifest; boxShadow?: BoxShadowManifest[]; border?: Border; }) { super(p); + this.width = p.width; this.height = p.height; + this.minWidth = p.minWidth; + this.maxWidth = p.maxWidth; + this.minHeight = p.minHeight; + this.maxHeight = p.maxHeight; + this.x = p.x; this.y = p.y; this.background = p.background; @@ -41,8 +54,13 @@ export class Container extends StylableJsxWidget { styleData(): CSSProperties { return { - width: css.px(this.width), - height: css.px(this.height), + width: css.length(this.width), + height: css.length(this.height), + "min-width": css.length(this.minWidth), + "max-width": css.length(this.maxWidth), + "min-height": css.length(this.minHeight), + "max-height": css.length(this.maxHeight), + "box-shadow": css.boxshadow(...(this.boxShadow ?? [])), ...css.background(this.background), ...css.border(this.border), @@ -59,6 +77,7 @@ export class Container extends StylableJsxWidget { export abstract class SelfClosingContainer extends Container - implements Omit { + implements Omit +{ readonly children?: undefined; } diff --git a/packages/builder-web-core/widgets-native/flex/index.ts b/packages/builder-web-core/widgets-native/flex/index.ts index 54aea003..9c4baa2c 100644 --- a/packages/builder-web-core/widgets-native/flex/index.ts +++ b/packages/builder-web-core/widgets-native/flex/index.ts @@ -45,16 +45,24 @@ export class Flex extends MultiChildWidget implements CssMinHeightMixin { borderRadius?: BorderRadiusManifest; border?: Border; + + minWidth?: DimensionLength; + maxWidth?: DimensionLength; minHeight?: DimensionLength; + maxHeight?: DimensionLength; + flexWrap?: FlexWrap; constructor( p: IFlexManifest & { // direction: "row" | "column"; key: WidgetKey; - width?: number; - height?: number; + width?: DimensionLength; + height?: DimensionLength; + minWidth?: DimensionLength; + maxWidth?: DimensionLength; minHeight?: DimensionLength; + maxHeight?: DimensionLength; mainAxisAlignment?: MainAxisAlignment; mainAxisSize?: MainAxisSize; crossAxisAlignment?: CrossAxisAlignment; @@ -74,6 +82,11 @@ export class Flex extends MultiChildWidget implements CssMinHeightMixin { this.width = p.width; this.height = p.height; + this.minWidth = p.minWidth; + this.maxWidth = p.maxWidth; + this.minHeight = p.minHeight; + this.maxHeight = p.maxHeight; + // flex related this.direction = p.direction; this.itemSpacing = p.itemSpacing; @@ -94,7 +107,6 @@ export class Flex extends MultiChildWidget implements CssMinHeightMixin { // css only this.overflow = p.overflow; - this.minHeight = p.minHeight; this.flexWrap = p.flexWrap; } @@ -119,7 +131,12 @@ export class Flex extends MultiChildWidget implements CssMinHeightMixin { ...css.border(this.border), ...css.borderRadius(this.borderRadius), ...flexsizing({ ...this }), - "min-height": css.minHeight(this.minHeight), + + "min-width": css.length(this.minWidth), + "max-width": css.length(this.maxWidth), + "min-height": css.length(this.minHeight), + "max-height": css.length(this.maxHeight), + ...css.background(this.background), "box-sizing": (this.padding && "border-box") || undefined, ...css.padding(this.padding), @@ -146,8 +163,8 @@ function flexsizing({ }: { direction: Axis; mainAxisSize?: MainAxisSize; - width?: number; - height?: number; + width?: DimensionLength; + height?: DimensionLength; flex?: number; }): CSSProperties { switch (mainAxisSize) { @@ -163,8 +180,8 @@ function flexsizing({ case Axis.vertical: return { flex: "none", - width: width && css.px(width), - height: height && css.px(height), + width: width && css.length(width), + height: height && css.length(height), }; } } diff --git a/packages/builder-web-core/widgets-native/html-svg/index.ts b/packages/builder-web-core/widgets-native/html-svg/index.ts index 8709f1d0..76a7def5 100644 --- a/packages/builder-web-core/widgets-native/html-svg/index.ts +++ b/packages/builder-web-core/widgets-native/html-svg/index.ts @@ -1,7 +1,7 @@ import { StylableJsxWidget } from "@web-builder/core/widget-tree/widget"; import { CSSProperties } from "@coli.codes/css"; -import { JSXElementConfig, StylableJSXElementConfig, WidgetKey } from "../.."; -import { px, color } from "@web-builder/styles"; +import { StylableJSXElementConfig, WidgetKey } from "../.."; +import * as css from "@web-builder/styles"; import { JSX, JSXAttribute, @@ -10,7 +10,6 @@ import { JSXIdentifier, JSXOpeningElement, JSXSelfClosingElement, - Snippet, StringLiteral, } from "coli"; import { Color, GradientType } from "@reflect-ui/core"; @@ -110,7 +109,7 @@ export class SvgElement extends StylableJsxWidget { } else { switch (this.fill.type) { case "solid-color": { - return [path_with_fill(color(this.fill as Color))]; + return [path_with_fill(css.color(this.fill as Color))]; } case "graphics": { console.error("graphics fill for svg not supported."); @@ -127,7 +126,7 @@ export class SvgElement extends StylableJsxWidget { new JSXAttribute("offset", new StringLiteral(`${stop}%`)), new JSXAttribute( "style", - new StringLiteral(`stop-color: ${color(c)}`) + new StringLiteral(`stop-color: ${css.color(c)}`) ), ], }); @@ -194,9 +193,9 @@ export class SvgElement extends StylableJsxWidget { }; } return { - width: px(this.width), - height: px(this.height), - color: color(this.color), + width: css.length(this.width), + height: css.length(this.height), + color: css.color(this.color), }; } diff --git a/packages/builder-web-core/widgets-native/html-text-span/index.ts b/packages/builder-web-core/widgets-native/html-text-element/index.ts similarity index 72% rename from packages/builder-web-core/widgets-native/html-text-span/index.ts rename to packages/builder-web-core/widgets-native/html-text-element/index.ts index 88cd91ab..8611aaee 100644 --- a/packages/builder-web-core/widgets-native/html-text-span/index.ts +++ b/packages/builder-web-core/widgets-native/html-text-element/index.ts @@ -1,17 +1,18 @@ -import { JSXElementConfig, StylableJSXElementConfig, WidgetKey } from "../.."; -import { - TextDataWidget, - TextChildWidget, - StylableJsxWidget, -} from "@web-builder/core"; +import { StylableJSXElementConfig, WidgetKey } from "../.."; +import { TextDataWidget, TextChildWidget } from "@web-builder/core"; import * as core from "@reflect-ui/core"; -import { TextOverflow } from "@reflect-ui/core"; +import { TextOverflow, WebTextElement } from "@reflect-ui/core"; import { CSSProperties } from "@coli.codes/css"; import { JSX } from "coli"; import { RGBA } from "@reflect-ui/core"; import * as css from "@web-builder/styles"; import { Dynamic } from "@reflect-ui/core/lib/_utility-types"; +/** + * Html Text Representative. + * + * You can select wich element to render with `elementPreference`. - choose between h1 ~ h6, p, span, etc. + */ export class Text extends TextChildWidget { _type: "Text"; @@ -23,6 +24,9 @@ export class Text extends TextChildWidget { width?: number; height?: number; + // experimental + elementPreference?: WebTextElement; + constructor(p: { key: WidgetKey; data: string; @@ -31,6 +35,7 @@ export class Text extends TextChildWidget { textAlign: core.TextAlign; width?: number; height?: number; + elementPreference?: WebTextElement; }) { super(p); @@ -41,6 +46,9 @@ export class Text extends TextChildWidget { this.textAlign = p.textAlign; this.width = p.width; this.height = p.height; + + // experimental + this.elementPreference = p.elementPreference; } textData() { @@ -54,7 +62,7 @@ export class Text extends TextChildWidget { let textStyle: any = { // text style // ------------------------------------------ - color: css.color((this.textStyle.color as any) as RGBA), + color: css.color(this.textStyle.color as any as RGBA), "text-overflow": this.overflow, "font-size": css.px(this.textStyle.fontSize), "font-family": css.fontFamily(this.textStyle.fontFamily), @@ -78,7 +86,16 @@ export class Text extends TextChildWidget { jsxConfig(): StylableJSXElementConfig { return { type: "tag-and-attr", - tag: JSX.identifier("span"), + tag: JSX.identifier(__get_dedicated_element_tag(this.elementPreference)), }; } } + +const __default_element_tag = "span"; +const __get_dedicated_element_tag = (t?: WebTextElement | undefined) => { + if (t) { + return t; + } else { + return __default_element_tag; + } +}; diff --git a/packages/builder-web-core/widgets-native/index.ts b/packages/builder-web-core/widgets-native/index.ts index 4ab9432e..428e10d6 100644 --- a/packages/builder-web-core/widgets-native/index.ts +++ b/packages/builder-web-core/widgets-native/index.ts @@ -3,7 +3,7 @@ export * from "./container"; export * from "./row"; export * from "./flex"; export * from "./stack"; -export * from "./html-text-span"; +export * from "./html-text-element"; export * from "./html-svg"; export * from "./html-image"; export * from "./error-widget"; diff --git a/packages/builder-web-core/widgets-native/stack/index.ts b/packages/builder-web-core/widgets-native/stack/index.ts index 36c384e2..2315b0d8 100644 --- a/packages/builder-web-core/widgets-native/stack/index.ts +++ b/packages/builder-web-core/widgets-native/stack/index.ts @@ -20,9 +20,13 @@ import { Background } from "@reflect-ui/core/lib/background"; export class Stack extends MultiChildWidget implements CssMinHeightMixin { readonly _type = "stack"; - width: number; - height: number; + width: DimensionLength; + height: DimensionLength; + minWidth?: DimensionLength; + maxWidth?: DimensionLength; minHeight?: DimensionLength; + maxHeight?: DimensionLength; + borderRadius?: BorderRadiusManifest; border?: Border; clipBehavior?: Clip; @@ -30,9 +34,14 @@ export class Stack extends MultiChildWidget implements CssMinHeightMixin { constructor(p: { key: WidgetKey; children: Array; - width: number; - height: number; + + width: DimensionLength; + height: DimensionLength; + minWidth?: DimensionLength; + maxWidth?: DimensionLength; minHeight?: DimensionLength; + maxHeight?: DimensionLength; + boxShadow?: BoxShadowManifest[]; borderRadius?: BorderRadiusManifest; border?: Border; @@ -40,10 +49,13 @@ export class Stack extends MultiChildWidget implements CssMinHeightMixin { clipBehavior?: Clip; }) { super(p); + this.width = p.width; this.height = p.height; - + this.minWidth = p.minWidth; + this.maxWidth = p.maxWidth; this.minHeight = p.minHeight; + this.maxHeight = p.maxHeight; this.background = p.background; this.borderRadius = p.borderRadius; @@ -63,10 +75,13 @@ export class Stack extends MultiChildWidget implements CssMinHeightMixin { styleData(): CSSProperties { return { - width: css.px(this.width), - height: css.px(this.height), + width: css.length(this.width), + height: css.length(this.height), + "min-width": css.length(this.minWidth), + "max-width": css.length(this.maxWidth), + "min-height": css.length(this.minHeight), + "max-height": css.length(this.maxHeight), - "min-height": css.minHeight(this.minHeight), overflow: clip(this.clipBehavior), ...css.background(this.background), ...css.border(this.border), diff --git a/packages/designto-token/config/config.ts b/packages/designto-token/config/config.ts index abf13be3..90e58bf9 100644 --- a/packages/designto-token/config/config.ts +++ b/packages/designto-token/config/config.ts @@ -12,7 +12,7 @@ export interface TokenizerConfig { */ id?: string; - sanitizer_ignore_masking_node: boolean; + sanitizer_ignore_masking_node?: boolean; /** * @default false - flags support enabled by default. diff --git a/packages/designto-token/support-flags/index.ts b/packages/designto-token/support-flags/index.ts index 4125c2da..d0184e63 100644 --- a/packages/designto-token/support-flags/index.ts +++ b/packages/designto-token/support-flags/index.ts @@ -1,14 +1,26 @@ -import { parse } from "@code-features/flags"; +import { + parse, + keys, + FlagsParseResult, + WHDeclarationFlag, + FixWHFlag, +} from "@code-features/flags"; import type { ReflectSceneNode } from "@design-sdk/figma"; import { tokenize_flagged_artwork } from "./token-artwork"; +import { tokenize_flagged_heading } from "./token-heading"; +import { tokenize_flagged_paragraph } from "./token-p"; +import { tokenize_flagged_span } from "./token-span"; import { tokenize_flagged_wrap } from "./token-wrap"; +import { tokenize_flagged_wh_declaration } from "./token-wh"; +import { tokenize_flagged_fix_wh } from "./token-wh-fix"; export default function (node: ReflectSceneNode) { const flags = parse(node.name); return handle_with_flags(node, flags); } -function handle_with_flags(node, flags) { +function handle_with_flags(node, flags: FlagsParseResult) { + // artwork const artwork_flag_alias = flags["artwork"] || flags["export-as"] || @@ -23,8 +35,53 @@ function handle_with_flags(node, flags) { return tokenize_flagged_artwork(node, artwork_flag_alias); } + // wrap const wrap_flag_alias = flags["wrap"] || flags["as-wrap"] || flags["is-wrap"]; if (wrap_flag_alias) { return tokenize_flagged_wrap(node, wrap_flag_alias); } + + // heading + const heading_flag_alias = + flags[keys.flag_key__as_h1] || + flags[keys.flag_key__as_h2] || + flags[keys.flag_key__as_h3] || + flags[keys.flag_key__as_h4] || + flags[keys.flag_key__as_h5] || + flags[keys.flag_key__as_h6]; + + if (heading_flag_alias) { + return tokenize_flagged_heading(node, heading_flag_alias); + } + + const span_flag_alias = flags[keys.flag_key__as_span]; + if (span_flag_alias) { + return tokenize_flagged_span(node, span_flag_alias); + } + + const paragraph_flag_alias = flags[keys.flag_key__as_p]; + if (paragraph_flag_alias) { + return tokenize_flagged_paragraph(node, paragraph_flag_alias); + } + + const wh_declaration_flags: WHDeclarationFlag[] = [ + flags[keys.flag_key__width], + flags[keys.flag_key__min_width], + flags[keys.flag_key__max_width], + flags[keys.flag_key__height], + flags[keys.flag_key__min_height], + flags[keys.flag_key__max_height], + ].filter(Boolean); + + if (wh_declaration_flags.length) { + return tokenize_flagged_wh_declaration(node, wh_declaration_flags); + } + + const fix_wh_flags: FixWHFlag[] = [ + flags[keys.flag_key__fix_width], + flags[keys.flag_key__fix_height], + ].filter(Boolean); + if (fix_wh_flags.length) { + return tokenize_flagged_fix_wh(node, fix_wh_flags); + } } diff --git a/packages/designto-token/support-flags/token-heading/index.ts b/packages/designto-token/support-flags/token-heading/index.ts new file mode 100644 index 00000000..ea22eb3d --- /dev/null +++ b/packages/designto-token/support-flags/token-heading/index.ts @@ -0,0 +1,75 @@ +import { HeadingFlag } from "@code-features/flags"; +import { ReflectSceneNode } from "@design-sdk/figma-node"; +import type { Text } from "@reflect-ui/core"; +import { tokenizeText } from "../../token-text"; + +type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; + +export function tokenize_flagged_heading( + node: ReflectSceneNode, + flag: HeadingFlag +): Text { + if (flag.value === false) return; + if (node.type !== "TEXT") return; + + const level = get_level(flag); + if (level === undefined) return; // this won't be happening + + const text = tokenizeText.fromText(node); + text.element_preference_experimental = `h${level}`; + return text; +} + +function get_level(flag: HeadingFlag): HeadingLevel { + switch (flag.flag) { + case "h1": + case "as-h1": + case "as-heading1": + case "heading1": + case "as-headline1": + case "headline1": + return 1; + + case "h2": + case "as-h2": + case "as-heading2": + case "heading2": + case "as-headline2": + case "headline2": + return 2; + + case "h3": + case "as-h3": + case "as-heading3": + case "heading3": + case "as-headline3": + case "headline3": + return 3; + + case "h4": + case "as-h4": + case "as-heading4": + case "heading4": + case "as-headline4": + case "headline4": + return 4; + + case "h5": + case "as-h5": + case "as-heading5": + case "heading5": + case "as-headline5": + case "headline5": + return 5; + + case "h6": + case "as-h6": + case "as-heading6": + case "heading6": + case "as-headline6": + case "headline6": + return 6; + } + + console.trace("level parsing from heading flag failed."); +} diff --git a/packages/designto-token/support-flags/token-p/index.ts b/packages/designto-token/support-flags/token-p/index.ts new file mode 100644 index 00000000..ff71ef56 --- /dev/null +++ b/packages/designto-token/support-flags/token-p/index.ts @@ -0,0 +1,16 @@ +import { AsParagraphFlag } from "@code-features/flags"; +import { ReflectSceneNode } from "@design-sdk/figma-node"; +import type { Text } from "@reflect-ui/core"; +import { tokenizeText } from "../../token-text"; + +export function tokenize_flagged_paragraph( + node: ReflectSceneNode, + flag: AsParagraphFlag +): Text { + if (flag.value === false) return; + if (node.type !== "TEXT") return; + + const text = tokenizeText.fromText(node); + text.element_preference_experimental = `p`; + return text; +} diff --git a/packages/designto-token/support-flags/token-span/index.ts b/packages/designto-token/support-flags/token-span/index.ts new file mode 100644 index 00000000..db4b51fd --- /dev/null +++ b/packages/designto-token/support-flags/token-span/index.ts @@ -0,0 +1,16 @@ +import { AsTextSpanFlag } from "@code-features/flags"; +import { ReflectSceneNode } from "@design-sdk/figma-node"; +import type { Text } from "@reflect-ui/core"; +import { tokenizeText } from "../../token-text"; + +export function tokenize_flagged_span( + node: ReflectSceneNode, + flag: AsTextSpanFlag +): Text { + if (flag.value === false) return; + if (node.type !== "TEXT") return; + + const text = tokenizeText.fromText(node); + text.element_preference_experimental = `span`; + return text; +} diff --git a/packages/designto-token/support-flags/token-wh-fix/index.ts b/packages/designto-token/support-flags/token-wh-fix/index.ts new file mode 100644 index 00000000..1c366f34 --- /dev/null +++ b/packages/designto-token/support-flags/token-wh-fix/index.ts @@ -0,0 +1,57 @@ +import { FixWHFlag } from "@code-features/flags"; +import { ReflectSceneNode } from "@design-sdk/figma-node"; +import { IWHStyleWidget, Widget } from "@reflect-ui/core"; +import { tokenize } from "../../main"; +import { unwrappedChild } from "../../wrappings"; + +export function tokenize_flagged_fix_wh( + node: ReflectSceneNode, + flag: FixWHFlag[] +): Widget { + if (!flag.length) return; + const widget = tokenize(node, { + should_ignore_flag: (n) => { + return node.id == n.id; + }, + }); + + const flag_target = unwrappedChild(widget) as IWHStyleWidget; + + const merged = flag + .map((f) => f) + .reduce((a, b) => { + let rec: IWHStyleWidget = {}; + /// + /// NOTE: + /// we are currently fixing the width of the target by specifying all of the current, min, max value. + /// this is not ideal, but it is the best we can do for now. + /// why we are also specifying min, max is because we yet don't have a correct handling system to determine if the current token's value is modified by flag or not. + /// so it is very possible that width/height will be modified, or remvoed by other logic gates. to prevent this, we also specify min, max. + /// + switch (b.flag) { + case "fix-width": + rec["width"] = flag_target.width; + rec["minWidth"] = flag_target.width; + rec["maxWidth"] = flag_target.width; + break; + case "fix-height": + rec["height"] = flag_target.height; + rec["minHeight"] = flag_target.height; + rec["maxHeight"] = flag_target.height; + break; + } + return { + ...a, + ...rec, + }; + }, {}); + + merged.width && (flag_target.width = merged.width); + merged.minWidth && (flag_target.minWidth = merged.minWidth); + merged.maxWidth && (flag_target.maxWidth = merged.maxWidth); + merged.height && (flag_target.height = merged.height); + merged.minHeight && (flag_target.minHeight = merged.minHeight); + merged.maxHeight && (flag_target.maxHeight = merged.maxHeight); + + return widget; +} diff --git a/packages/designto-token/support-flags/token-wh/index.ts b/packages/designto-token/support-flags/token-wh/index.ts new file mode 100644 index 00000000..aa873f71 --- /dev/null +++ b/packages/designto-token/support-flags/token-wh/index.ts @@ -0,0 +1,69 @@ +import { WHDeclarationFlag } from "@code-features/flags"; +import { ReflectSceneNode } from "@design-sdk/figma-node"; +import { + DimensionLength, + isPossibleDimensionLength, + IWHStyleWidget, + Widget, +} from "@reflect-ui/core"; +import { tokenize } from "../../main"; +import { unwrappedChild } from "../../wrappings"; + +export function tokenize_flagged_wh_declaration( + node: ReflectSceneNode, + flag: WHDeclarationFlag[] +): Widget { + if (!flag.length) return; + + const merged = flag + .map((f) => f) + .reduce((a, b) => { + if (isPossibleDimensionLength(b.value)) { + let rec: IWHStyleWidget = {}; + switch (b.flag) { + case "width": + rec["width"] = b.value as DimensionLength; + break; + case "min-width": + rec["minWidth"] = b.value; + break; + case "max-width": + rec["maxWidth"] = b.value; + break; + case "height": + rec["height"] = b.value as DimensionLength; + break; + case "min-height": + rec["minHeight"] = b.value; + break; + case "max-height": + rec["maxHeight"] = b.value; + break; + } + return { + ...a, + ...rec, + }; + } else { + // TODO: support complex values + } + return a; + }, {}); + + const widget = tokenize(node, { + should_ignore_flag: (n) => { + return node.id == n.id; + }, + }); + + const flag_target = unwrappedChild(widget) as IWHStyleWidget; + + merged.width && (flag_target.width = merged.width); + merged.minWidth && (flag_target.minWidth = merged.minWidth); + merged.maxWidth && (flag_target.maxWidth = merged.maxWidth); + merged.height && (flag_target.height = merged.height); + merged.minHeight && (flag_target.minHeight = merged.minHeight); + merged.maxHeight && (flag_target.maxHeight = merged.maxHeight); + + return widget; +} diff --git a/packages/designto-token/support-flags/token-wrap/index.ts b/packages/designto-token/support-flags/token-wrap/index.ts index bc29c8f3..a159e7d5 100644 --- a/packages/designto-token/support-flags/token-wrap/index.ts +++ b/packages/designto-token/support-flags/token-wrap/index.ts @@ -35,7 +35,9 @@ import { unwrappedChild } from "../../wrappings"; export function tokenize_flagged_wrap( node: ReflectSceneNode, flag: AsWrapFlag -) { +): Wrap { + if (flag.value === false) return; + const validated = validate_input(node as any); if (validated.error === false) { // console.log("validated as wrap", validated); @@ -73,9 +75,7 @@ export function tokenize_flagged_wrap( * 2. the children should be columns or rows * @param input */ -function validate_input( - node: ReflectFrameNode -): +function validate_input(node: ReflectFrameNode): | { error: false; wrap_root: ReflectFrameNode; diff --git a/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts b/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts index bfe612aa..2cc495e6 100644 --- a/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts +++ b/packages/designto-web/tokens-to-web-widget/compose-wrapped-with-positioned.ts @@ -10,8 +10,8 @@ export function compose_wrapped_with_positioned( // ------------------------------------- // override w & h with position provided w/h child.extendStyle({ - width: css.px(widget.width), - height: css.px(widget.height), + width: css.length(widget.width), + height: css.length(widget.height), }); // ------------------------------------- child.constraint = { diff --git a/packages/designto-web/tokens-to-web-widget/index.ts b/packages/designto-web/tokens-to-web-widget/index.ts index 54d17d52..959a2c60 100644 --- a/packages/designto-web/tokens-to-web-widget/index.ts +++ b/packages/designto-web/tokens-to-web-widget/index.ts @@ -141,10 +141,12 @@ function compose( else if (widget instanceof core.RenderedText) { thisWebWidget = new web.Text({ ...widget, + key: _key, textStyle: widget.style /** explicit assignment - field name is different */, data: widget.data, - key: _key, + // experimental element specification + elementPreference: widget.element_preference_experimental, }); } else if (widget instanceof core.VectorWidget) { thisWebWidget = new web.SvgElement({ diff --git a/packages/support-flags/--artwork/README.md b/packages/support-flags/--artwork/README.md new file mode 100644 index 00000000..192273c1 --- /dev/null +++ b/packages/support-flags/--artwork/README.md @@ -0,0 +1,40 @@ +## Artwork flag + +**Accepted keys** + +- `--artwork` + +## Syntax + +```ts +`--artwork${"="typeof boolean}` +``` + +## Example + +``` +--artwork + +--artwork=true +--artwork=false + +--artwork=yes +--artwork=no + +----artwork +``` + +## Behavior + +**Interpreter** + +When applied, this will force the node to be exported as an image. + +**Render** + +- HTML: rendered as an `` element. +- Flutter: rendered as an `Image` widget. + +## See Also + +- [`--export-as`](../--export-as) diff --git a/packages/support-flags/--as-br/README.md b/packages/support-flags/--as-br/README.md index 840be114..b6054b02 100644 --- a/packages/support-flags/--as-br/README.md +++ b/packages/support-flags/--as-br/README.md @@ -1,3 +1,17 @@ -# As Break +--- +stage: + - proposal + - draft +--- + + + + + +# (Draft) `--as-br` As Break ## Interprets the flagged element as break (`
`). + +## When to use + +While designing a text layout, or a paragraph, we tend to use autolayout (a flex layout) to contain multiple text to be visually displayed as single text. diff --git a/packages/support-flags/--as-char/README.md b/packages/support-flags/--as-char/README.md new file mode 100644 index 00000000..659c2e40 --- /dev/null +++ b/packages/support-flags/--as-char/README.md @@ -0,0 +1,18 @@ +# As Character + +## See also + +- `--as-space` +- `--as-text-group` + +## When to use + +Some characters can't be displayed in design tool with only using pure text. + +Special characters, custom emoji, custom image, etc. + +## Example + +``` +--as-char="🤔" +``` diff --git a/packages/support-flags/--as-h1/README.md b/packages/support-flags/--as-h1/README.md index e69de29b..e5cd9812 100644 --- a/packages/support-flags/--as-h1/README.md +++ b/packages/support-flags/--as-h1/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h1` As Heading1 + +**Accepted keys** + +- `--as-h1` +- `--as-heading1` +- `--as-headline1` +- `--h1` +- `--heading1` +- `--headline1` + +## Syntax + +```ts +`--h1${"="typeof boolean}` +``` + +## Example + +``` +--h1 + +--h1=true +--h1=false + +--h1=yes +--h1=no + +----h1 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--h1` flag. + +## See Also + +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h1/index.ts b/packages/support-flags/--as-h1/index.ts new file mode 100644 index 00000000..e0ec0afb --- /dev/null +++ b/packages/support-flags/--as-h1/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h1 = "as-h1"; +// alias +const flag_key__as_heading1 = "as-heading1"; +const flag_key__as_headline1 = "as-headline1"; +const flag_key__h1 = "h1"; +const flag_key__heading1 = "heading1"; +const flag_key__headline1 = "headline1"; + +export const flag_key_alias__as_h1 = [ + flag_key__as_h1, + flag_key__as_heading1, + flag_key__as_headline1, + flag_key__h1, + flag_key__heading1, + flag_key__headline1, +]; + +export interface AsHeading1Flag { + flag: + | typeof flag_key__as_h1 + | typeof flag_key__as_heading1 + | typeof flag_key__as_headline1 + | typeof flag_key__h1 + | typeof flag_key__heading1 + | typeof flag_key__headline1; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-h2/README.md b/packages/support-flags/--as-h2/README.md index e69de29b..9bd9cc32 100644 --- a/packages/support-flags/--as-h2/README.md +++ b/packages/support-flags/--as-h2/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h2` As Heading2 + +**Accepted keys** + +- `--as-h2` +- `--as-heading2` +- `--as-headline2` +- `--h2` +- `--heading2` +- `--headline2` + +## Syntax + +```ts +`--h2${"="typeof boolean}` +``` + +## Example + +``` +--h2 + +--h2=true +--h2=false + +--h2=yes +--h2=no + +----h2 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--h2` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h2/index.ts b/packages/support-flags/--as-h2/index.ts new file mode 100644 index 00000000..ecb238db --- /dev/null +++ b/packages/support-flags/--as-h2/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h2 = "as-h2"; +// alias +const flag_key__as_heading2 = "as-heading2"; +const flag_key__as_headline2 = "as-headline2"; +const flag_key__h2 = "h2"; +const flag_key__heading2 = "heading2"; +const flag_key__headline2 = "headline2"; + +export const flag_key_alias__as_h2 = [ + flag_key__as_h2, + flag_key__as_heading2, + flag_key__as_headline2, + flag_key__h2, + flag_key__heading2, + flag_key__headline2, +]; + +export interface AsHeading2Flag { + flag: + | typeof flag_key__as_h2 + | typeof flag_key__as_heading2 + | typeof flag_key__as_headline2 + | typeof flag_key__h2 + | typeof flag_key__heading2 + | typeof flag_key__headline2; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-h3/README.md b/packages/support-flags/--as-h3/README.md index e69de29b..8adfd930 100644 --- a/packages/support-flags/--as-h3/README.md +++ b/packages/support-flags/--as-h3/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h3` As Heading3 + +**Accepted keys** + +- `--as-h3` +- `--as-heading3` +- `--as-headline3` +- `--h3` +- `--heading3` +- `--headline3` + +## Syntax + +```ts +`--h3${"="typeof boolean}` +``` + +## Example + +``` +--h3 + +--h3=true +--h3=false + +--h3=yes +--h3=no + +----h3 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--h3` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h3/index.ts b/packages/support-flags/--as-h3/index.ts new file mode 100644 index 00000000..96e53acf --- /dev/null +++ b/packages/support-flags/--as-h3/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h3 = "as-h3"; +// alias +const flag_key__as_heading3 = "as-heading3"; +const flag_key__as_headline3 = "as-headline3"; +const flag_key__h3 = "h3"; +const flag_key__heading3 = "heading3"; +const flag_key__headline3 = "headline3"; + +export const flag_key_alias__as_h3 = [ + flag_key__as_h3, + flag_key__as_heading3, + flag_key__as_headline3, + flag_key__h3, + flag_key__heading3, + flag_key__headline3, +]; + +export interface AsHeading3Flag { + flag: + | typeof flag_key__as_h3 + | typeof flag_key__as_heading3 + | typeof flag_key__as_headline3 + | typeof flag_key__h3 + | typeof flag_key__heading3 + | typeof flag_key__headline3; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-h4/README.md b/packages/support-flags/--as-h4/README.md index e69de29b..bbae2a70 100644 --- a/packages/support-flags/--as-h4/README.md +++ b/packages/support-flags/--as-h4/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h4` As Heading4 + +**Accepted keys** + +- `--as-h4` +- `--as-heading4` +- `--as-headline4` +- `--h4` +- `--heading4` +- `--headline4` + +## Syntax + +```ts +`--h4${"="typeof boolean}` +``` + +## Example + +``` +--h4 + +--h4=true +--h4=false + +--h4=yes +--h4=no + +----h4 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--h4` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h4/index.ts b/packages/support-flags/--as-h4/index.ts new file mode 100644 index 00000000..7e76d91e --- /dev/null +++ b/packages/support-flags/--as-h4/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h4 = "as-h4"; +// alias +const flag_key__as_heading4 = "as-heading4"; +const flag_key__as_headline4 = "as-headline4"; +const flag_key__h4 = "h4"; +const flag_key__heading4 = "heading4"; +const flag_key__headline4 = "headline4"; + +export const flag_key_alias__as_h4 = [ + flag_key__as_h4, + flag_key__as_heading4, + flag_key__as_headline4, + flag_key__h4, + flag_key__heading4, + flag_key__headline4, +]; + +export interface AsHeading4Flag { + flag: + | typeof flag_key__as_h4 + | typeof flag_key__as_heading4 + | typeof flag_key__as_headline4 + | typeof flag_key__h4 + | typeof flag_key__heading4 + | typeof flag_key__headline4; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-h5/README.md b/packages/support-flags/--as-h5/README.md index e69de29b..5503a80a 100644 --- a/packages/support-flags/--as-h5/README.md +++ b/packages/support-flags/--as-h5/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h5` As Heading5 + +**Accepted keys** + +- `--as-h5` +- `--as-heading5` +- `--as-headline5` +- `--h5` +- `--heading5` +- `--headline5` + +## Syntax + +```ts +`--h5${"="typeof boolean}` +``` + +## Example + +``` +--h5 + +--h5=true +--h5=false + +--h5=yes +--h5=no + +----h5 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--h5` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h5/index.ts b/packages/support-flags/--as-h5/index.ts new file mode 100644 index 00000000..34d1e7ef --- /dev/null +++ b/packages/support-flags/--as-h5/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h5 = "as-h5"; +// alias +const flag_key__as_heading5 = "as-heading5"; +const flag_key__as_headline5 = "as-headline5"; +const flag_key__h5 = "h5"; +const flag_key__heading5 = "heading5"; +const flag_key__headline5 = "headline5"; + +export const flag_key_alias__as_h5 = [ + flag_key__as_h5, + flag_key__as_heading5, + flag_key__as_headline5, + flag_key__h5, + flag_key__heading5, + flag_key__headline5, +]; + +export interface AsHeading5Flag { + flag: + | typeof flag_key__as_h5 + | typeof flag_key__as_heading5 + | typeof flag_key__as_headline5 + | typeof flag_key__h5 + | typeof flag_key__heading5 + | typeof flag_key__headline5; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-h6/README.md b/packages/support-flags/--as-h6/README.md index e69de29b..3db14248 100644 --- a/packages/support-flags/--as-h6/README.md +++ b/packages/support-flags/--as-h6/README.md @@ -0,0 +1,55 @@ +--- +stage: + - production + - staging + - experimental +--- + +# `--as-h6` As Heading6 + +**Accepted keys** + +- `--as-h6` +- `--as-heading6` +- `--as-headline6` +- `--h6` +- `--heading6` +- `--headline6` + +## Syntax + +```ts +`--h6${"="typeof boolean}` +``` + +## Example + +``` +--h6 + +--h6=true +--h6=false + +--h6=yes +--h6=no + +----h6 +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `
` element. + +**Text style** +We don't yet support text style matching with `--h6` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-h6/index.ts b/packages/support-flags/--as-h6/index.ts new file mode 100644 index 00000000..e70c8949 --- /dev/null +++ b/packages/support-flags/--as-h6/index.ts @@ -0,0 +1,30 @@ +// primary +export const flag_key__as_h6 = "as-h6"; +// alias +const flag_key__as_heading6 = "as-heading6"; +const flag_key__as_headline6 = "as-headline6"; +const flag_key__h6 = "h6"; +const flag_key__heading6 = "heading6"; +const flag_key__headline6 = "headline6"; + +export const flag_key_alias__as_h6 = [ + flag_key__as_h6, + flag_key__as_heading6, + flag_key__as_headline6, + flag_key__h6, + flag_key__heading6, + flag_key__headline6, +]; + +export interface AsHeading6Flag { + flag: + | typeof flag_key__as_h6 + | typeof flag_key__as_heading6 + | typeof flag_key__as_headline6 + | typeof flag_key__h6 + | typeof flag_key__heading6 + | typeof flag_key__headline6; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-nbsp/README.md b/packages/support-flags/--as-nbsp/README.md new file mode 100644 index 00000000..b0630ed3 --- /dev/null +++ b/packages/support-flags/--as-nbsp/README.md @@ -0,0 +1,36 @@ +# `--as-nbsp` As Non-Breaking Space + +**Accepted keys** + +- `--as-nbsp` +- `--as-space` +- `--nbsp` + +**`--as-nbsp` Extends `--as-char`** + +> `--as-nbsp` is equivalent to `--as-char= ` or `--as-char=" "` + +## Syntax + +```ts +`--nbsp${"="typeof number}` +``` + +## Example + +``` +--nbsp // 1 space, with `" "` on html +--as-nbsp // 1 space, with `" "` on html +--as-space // 1 space, with `" "` on html, if not available, e.g. on trailing, uses `" "`. + + +--nbsp=2 // 2 spaces +--nbsp=3 // 3 spaces + + +----nbsp=2 // commented out +``` + +## See also + +- [`--as-char`](../--as-char) diff --git a/packages/support-flags/--as-p/README.md b/packages/support-flags/--as-p/README.md index e69de29b..c33c2aca 100644 --- a/packages/support-flags/--as-p/README.md +++ b/packages/support-flags/--as-p/README.md @@ -0,0 +1,48 @@ +# `--as-p` As Paragraph (Text) + +> This flag is for web platform. Otherwise, it will be ignored, have no impact on the final output. + +**Accepted keys** + +- `--as-p` +- `--as-paragraph` +- `--paragraph` + +## Syntax + +```ts +`--as-p${"="typeof boolean}` +``` + +## Example + +``` +--paragraph + +--paragraph=true +--paragraph=false + +--paragraph=yes +--paragraph=no + +----paragraph +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `

` element. + +**Text style** +We don't yet support text style matching with `--p` flag. + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) +- [`--as-br`](../--as-br) diff --git a/packages/support-flags/--as-p/index.ts b/packages/support-flags/--as-p/index.ts new file mode 100644 index 00000000..5157b7cb --- /dev/null +++ b/packages/support-flags/--as-p/index.ts @@ -0,0 +1,21 @@ +// priamry +export const flag_key__as_p = "as-p"; +// alias +const flag_key__as_paragraph = "as-paragraph"; +const flag_key__paragraph = "paragraph"; + +export const flag_key_alias__as_p = [ + flag_key__as_p, + flag_key__as_paragraph, + flag_key__paragraph, +]; + +export interface AsParagraphFlag { + flag: + | typeof flag_key__as_p + | typeof flag_key__as_paragraph + | typeof flag_key__paragraph; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-span/README.md b/packages/support-flags/--as-span/README.md new file mode 100644 index 00000000..85325de1 --- /dev/null +++ b/packages/support-flags/--as-span/README.md @@ -0,0 +1,59 @@ +# `--as-span` As TextSpan (Text) + +> This flag is for web platform. Otherwise, it will be ignored, have no impact on the final output. + +**Accepted keys** + +- `--as-span` +- `--as-text-span` +- `--as-textspan` +- `--text-span` +- `--textspan` + +## Syntax + +```ts +`--as-span${"="typeof boolean}` +``` + +## Example + +``` +--as-span + +--as-span=true +--as-span=false + +--as-span=yes +--as-span=no + +----as-span +``` + +## Behavior + +**Element** +When applied, this will force the node to be rendered as a `` element. + +**Text style** +We don't yet support text style matching with `--as-span` flag. + +## Anatomy + +```ts +export interface AsSpanFlag { + flag: "as-span" | "as-text-span" | "as-textspan" | "text-span" | "textspan"; + + value?: boolean; +} +``` + +## See Also + +- [`--as-h1`](../--as-h1) +- [`--as-h2`](../--as-h2) +- [`--as-h3`](../--as-h3) +- [`--as-h4`](../--as-h4) +- [`--as-h5`](../--as-h5) +- [`--as-h6`](../--as-h6) +- [`--as-p`](../--as-p) diff --git a/packages/support-flags/--as-span/index.ts b/packages/support-flags/--as-span/index.ts new file mode 100644 index 00000000..4ccad77c --- /dev/null +++ b/packages/support-flags/--as-span/index.ts @@ -0,0 +1,27 @@ +// primary +export const flag_key__as_span = "as-span"; +// alias +const flag_key__as_text_span = "as-text-span"; +const flag_key__as_textspan = "as-textspan"; +const flag_key__text_span = "text-span"; +const flag_key__textspan = "textspan"; + +export const flag_key_alias__as_span = [ + flag_key__as_span, + flag_key__as_text_span, + flag_key__as_textspan, + flag_key__text_span, + flag_key__textspan, +]; + +export interface AsTextSpanFlag { + flag: + | typeof flag_key__as_span + | typeof flag_key__as_text_span + | typeof flag_key__as_textspan + | typeof flag_key__text_span + | typeof flag_key__textspan; + + value: boolean; + _raw?: string; +} diff --git a/packages/support-flags/--as-text-group/README.md b/packages/support-flags/--as-text-group/README.md new file mode 100644 index 00000000..69332d0e --- /dev/null +++ b/packages/support-flags/--as-text-group/README.md @@ -0,0 +1,3 @@ +## (Draft) Text group + +While creating a multilined, complex text, for example, inserting a custom emoji, or a custom image, we need to use a text group. This is usually done by using a autolayout or col-row oriented multiple autolayouts. diff --git a/packages/support-flags/--exact-height/README.md b/packages/support-flags/--exact-height/README.md deleted file mode 100644 index 26cdc8a5..00000000 --- a/packages/support-flags/--exact-height/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# `--exact-height` Flag (Draft) - -When applied, this will force dedicated layer's height to be ignore responsive height, use current height as fixed height instead. - -## Syntax - -```ts -`--exact-height${"="typeof boolean}` -``` - -## Example - -``` ---exact-height - ---exact-height=true ---exact-height=false - ---exact-height=True ---exact-height=False - ---exact-height=yes ---exact-height=no -``` diff --git a/packages/support-flags/--exact-width/README.md b/packages/support-flags/--exact-width/README.md deleted file mode 100644 index 1f2c3d00..00000000 --- a/packages/support-flags/--exact-width/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# `--exact-width` Flag (Draft) - -When applied, this will force dedicated layer's `width` to be ignore responsive width, use current width as fixed width instead. - -## Syntax - -```ts -`--exact-width${"="typeof boolean}` -``` - -## Example - -``` ---exact-width - ---exact-width=true ---exact-width=false - ---exact-width=True ---exact-width=False - ---exact-width=yes ---exact-width=no -``` diff --git a/packages/support-flags/--export-as/README.md b/packages/support-flags/--export-as/README.md new file mode 100644 index 00000000..e892b75d --- /dev/null +++ b/packages/support-flags/--export-as/README.md @@ -0,0 +1,6 @@ +# Export As + +**Accepted keys** + +- `--export-as` +- `--export` diff --git a/packages/support-flags/--export/README.md b/packages/support-flags/--export/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/support-flags/--fix-bottom/README.md b/packages/support-flags/--fix-bottom/README.md new file mode 100644 index 00000000..216594a6 --- /dev/null +++ b/packages/support-flags/--fix-bottom/README.md @@ -0,0 +1,7 @@ +# `--fix-bottom` Flag (Draft) + +When applied, this will force dedicated layer's bottom to be ignore responsive bottom, use current bottom as fixed bottom instead. + +> ⚠️ This is different from `--position-fixed`. In general, this flag is not used for designing a footer. + +## See also diff --git a/packages/support-flags/--fix-height/README.md b/packages/support-flags/--fix-height/README.md new file mode 100644 index 00000000..e6e13e7a --- /dev/null +++ b/packages/support-flags/--fix-height/README.md @@ -0,0 +1,24 @@ +# `--fix-height` Flag (Draft) + +When applied, this will force dedicated layer's `height` to be ignore responsive `height`, use current `height` as fixed `height` instead. + +## Syntax + +```ts +`--fix-height${"="typeof boolean}` +``` + +## Example + +``` +--fix-height + +--fix-height=true +--fix-height=false + +--fix-height=True +--fix-height=False + +--fix-height=yes +--fix-height=no +``` diff --git a/packages/support-flags/--fix-height/index.ts b/packages/support-flags/--fix-height/index.ts new file mode 100644 index 00000000..72a8d0c5 --- /dev/null +++ b/packages/support-flags/--fix-height/index.ts @@ -0,0 +1,10 @@ +export const flag_key__fix_height = "fix-height"; + +export const flag_key_alias__fix_height = [flag_key__fix_height]; + +export interface FixHeightFlag { + flag: typeof flag_key__fix_height; + + value: true; + _raw?: string; +} diff --git a/packages/support-flags/--fix-width/README.md b/packages/support-flags/--fix-width/README.md new file mode 100644 index 00000000..5e7b57f9 --- /dev/null +++ b/packages/support-flags/--fix-width/README.md @@ -0,0 +1,28 @@ +# `--fix-width` Flag (Draft) + +When applied, this will force dedicated layer's `width` to be ignore responsive width, use current width as fixed width instead. + +**Accepted keys** + +- `--fix-width` + +## Syntax + +```ts +`--fix-width${"="typeof boolean}` +``` + +## Example + +``` +--fix-width + +--fix-width=true +--fix-width=false + +--fix-width=True +--fix-width=False + +--fix-width=yes +--fix-width=no +``` diff --git a/packages/support-flags/--fix-width/index.ts b/packages/support-flags/--fix-width/index.ts new file mode 100644 index 00000000..1d8d23c8 --- /dev/null +++ b/packages/support-flags/--fix-width/index.ts @@ -0,0 +1,9 @@ +export const flag_key__fix_width = "fix-width"; + +export const flag_key_alias__fix_width = [flag_key__fix_width]; +export interface FixWidthFlag { + flag: typeof flag_key__fix_width; + + value: true; + _raw?: string; +} diff --git a/packages/support-flags/--height/README.md b/packages/support-flags/--height/README.md new file mode 100644 index 00000000..275732a6 --- /dev/null +++ b/packages/support-flags/--height/README.md @@ -0,0 +1,117 @@ +# `--height` for explicit height + +**Accepted keys** + +- `--height` +- `--h` + +## Syntax + +```ts +`--height=${typeof length}`; +``` + +## Example + +``` +--height=100 +--h=100 + +--height=100px + +--height=100vh +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a `height` style. + +## (Proposal) (Draft) Advanced use + +> This feature is a proposal, won't work on production use. + +height and height support specifying min, max, and initial values. + +This is how it looks like: + +`--height=(initial)` or `--height=(min)-(max)-(initial)` + +``` +--height=100px // initial only +--height=100px-1080px-50vh // min, max, initial +--height=100px-1080px // min, max +--height=?-1080px // min (none), max +--height=100px-? // min , max (none) +--height=100px-?-50vh // min , max (none), initial +``` + +you can skip the declaration with `?` keyword. this is a special keyword, interpreted as `undefined` + +"`--height=100px-?-50vh`" this will make css for example, as below. + +```css +.foo { + min-height: 100px; + height: 50vh; +} +``` + +"`--height=100px-1080px`" this indicates only min and max, yet, still the height will be specified based on current height of the origin design. + +```css +.foo { + min-height: 100px; + max-height: 1080px; + height: 400px; /* this is from the design */ +} +``` + +### Ignoring one of the property + +**Using explicit `--ignore` flag** +to ignore the height, you can use new flag `--ignore` set to height. like so - `--ignore=height` + +```css +.foo { + min-height: 100px; + max-height: 1080px; + /* height: 400px; this is ignored by --ignore flag */ +} +``` + +**Using `?` keyword** +Otherwise, you can simply use silincer keyword `?` to ignore the height, like so - `--height=100px-1080px-?` + +This will also generate style like below. + +```css +.foo { + min-height: 100px; + max-height: 1080px; + /* height: 400px; this is ignored by "?" keyword */ +} +``` + +### Referencing current value with `.` + +Setting max-height to current height (based on design) with - `--height=100px-.-.` + +This will generate style like below. + +```css +.foo { + min-height: 100px; + max-height: 400px; /* the current height from design */ + height: 400px; /* the current height from design */ +} +``` + +## See Also + +- [`--max-height`](../--max-height) +- [`--min-height`](../--min-height) +- [`--width`](../--width) diff --git a/packages/support-flags/--height/index.ts b/packages/support-flags/--height/index.ts new file mode 100644 index 00000000..52409ceb --- /dev/null +++ b/packages/support-flags/--height/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +export const flag_key__height = "height"; + +export const flag_key_alias__height = [flag_key__height]; + +export interface HeightFlag { + flag: typeof flag_key__height; + + value: + | DimensionLength + | { + min?: DimensionLength; + max?: DimensionLength; + initial?: DimensionLength; + }; + _raw?: string; +} diff --git a/packages/support-flags/--max-height/README.md b/packages/support-flags/--max-height/README.md new file mode 100644 index 00000000..c5a2f735 --- /dev/null +++ b/packages/support-flags/--max-height/README.md @@ -0,0 +1,36 @@ +# Max height + +**Accepted keys** + +- `--max-height` +- `--maxheight` + +## Syntax + +```ts +`--max-height=${typeof length}`; +``` + +## Example + +``` +--max-height=100 + +--max-height=100px + +--max-height=100vh +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a `max-height` style. + +## See Also + +- [`--max-width`](../--max-width) +- [`--min-height`](../--max-height) +- [`--height`](../--height) diff --git a/packages/support-flags/--max-height/index.ts b/packages/support-flags/--max-height/index.ts new file mode 100644 index 00000000..c5bf888a --- /dev/null +++ b/packages/support-flags/--max-height/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +// primary +export const flag_key__max_height = "max-height"; +// alias +const flag_key__maxheight = "maxheight"; + +export const flag_key_alias__max_height = [ + flag_key__max_height, + flag_key__maxheight, +]; + +export interface MaxHeightFlag { + flag: typeof flag_key__max_height | typeof flag_key__maxheight; + + value: DimensionLength; + _raw?: string; +} diff --git a/packages/support-flags/--max-width/README.md b/packages/support-flags/--max-width/README.md new file mode 100644 index 00000000..6dd58b83 --- /dev/null +++ b/packages/support-flags/--max-width/README.md @@ -0,0 +1,36 @@ +# Max width + +**Accepted keys** + +- `--max-width` +- `--maxwidth` + +## Syntax + +```ts +`--max-width=${typeof length}`; +``` + +## Example + +``` +--max-width=100 + +--max-width=100px + +--max-width=400vw +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a max-width style. + +## See Also + +- [`--max-height`](../--max-height) +- [`--min-width`](../--max-width) +- [`--width`](../--max-width) diff --git a/packages/support-flags/--max-width/index.ts b/packages/support-flags/--max-width/index.ts new file mode 100644 index 00000000..00b8afa1 --- /dev/null +++ b/packages/support-flags/--max-width/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +// primary +export const flag_key__max_width = "max-width"; +// alias +const flag_key__maxwidth = "maxwidth"; + +export const flag_key_alias__max_width = [ + flag_key__max_width, + flag_key__maxwidth, +]; + +export interface MaxWidthFlag { + flag: typeof flag_key__max_width | typeof flag_key__maxwidth; + + value: DimensionLength; + _raw?: string; +} diff --git a/packages/support-flags/--min-height/README.md b/packages/support-flags/--min-height/README.md new file mode 100644 index 00000000..059d7771 --- /dev/null +++ b/packages/support-flags/--min-height/README.md @@ -0,0 +1,36 @@ +# Min height + +**Accepted keys** + +- `--min-height` +- `--minheight` + +## Syntax + +```ts +`--min-height=${typeof length}`; +``` + +## Example + +``` +--min-height=100 + +--min-height=100px + +--min-height=100vh +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a `min-height` style. + +## See Also + +- [`--max-height`](../--max-height) +- [`--min-width`](../--max-width) +- [`--height`](../--height) diff --git a/packages/support-flags/--min-height/index.ts b/packages/support-flags/--min-height/index.ts new file mode 100644 index 00000000..e8b59db3 --- /dev/null +++ b/packages/support-flags/--min-height/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +// primary +export const flag_key__min_height = "min-height"; +// alias +const flag_key__minheight = "minheight"; + +export const flag_key_alias__min_height = [ + flag_key__min_height, + flag_key__minheight, +]; + +export interface MinHeightFlag { + flag: typeof flag_key__min_height | typeof flag_key__minheight; + + value: DimensionLength; + _raw?: string; +} diff --git a/packages/support-flags/--min-width/README.md b/packages/support-flags/--min-width/README.md new file mode 100644 index 00000000..28df8815 --- /dev/null +++ b/packages/support-flags/--min-width/README.md @@ -0,0 +1,36 @@ +# Min width + +**Accepted keys** + +- `--min-width` +- `--minwidth` + +## Syntax + +```ts +`--min-width=${typeof length}`; +``` + +## Example + +``` +--min-width=100 + +--min-width=100px + +--min-width=100vw +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a `min-width` style. + +## See Also + +- [`--max-width`](../--max-width) +- [`--min-height`](../--min-height) +- [`--width`](../--width) diff --git a/packages/support-flags/--min-width/index.ts b/packages/support-flags/--min-width/index.ts new file mode 100644 index 00000000..bd5be19c --- /dev/null +++ b/packages/support-flags/--min-width/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +// primary +export const flag_key__min_width = "min-width"; +// alias +const flag_key__minwidth = "minwidth"; + +export const flag_key_alias__min_width = [ + flag_key__min_width, + flag_key__minwidth, +]; + +export interface MinWidthFlag { + flag: typeof flag_key__min_width | typeof flag_key__minwidth; + + value: DimensionLength; + _raw?: string; +} diff --git a/packages/support-flags/--position-sticky/README.md b/packages/support-flags/--position-sticky/README.md new file mode 100644 index 00000000..79ed0a42 --- /dev/null +++ b/packages/support-flags/--position-sticky/README.md @@ -0,0 +1 @@ +# (WIP) Position as Sticky. diff --git a/packages/support-flags/--width/README.md b/packages/support-flags/--width/README.md new file mode 100644 index 00000000..40beb9cb --- /dev/null +++ b/packages/support-flags/--width/README.md @@ -0,0 +1,117 @@ +# `--width` for explicit width + +**Accepted keys** + +- `--width` +- `--w` + +## Syntax + +```ts +`--width=${typeof length}`; +``` + +## Example + +``` +--width=100 +--w=100 + +--width=100px + +--width=400vw +``` + +## Behavior + +**Element** +There is no impact on element itself, but it can break relative layouts. + +**Style** +When applied, this will force the node to be rendered with a `width` style. + +## (Proposal) (Draft) Advanced use + +> This feature is a proposal, won't work on production use. + +width and height support specifying min, max, and initial values. + +This is how it looks like: + +`--width=(initial)` or `--width=(min)-(max)-(initial)` + +``` +--width=100px // initial only +--width=100px-1080px-50vw // min, max, initial +--width=100px-1080px // min, max +--width=?-1080px // min (none), max +--width=100px-? // min , max (none) +--width=100px-?-50vw // min , max (none), initial +``` + +you can skip the declaration with `?` keyword. this is a special keyword, interpreted as `undefined` + +"`--width=100px-?-50vw`" this will make css for example, as below. + +```css +.foo { + min-width: 100px; + width: 50vw; +} +``` + +"`--width=100px-1080px`" this indicates only min and max, yet, still the width will be specified based on current width of the origin design. + +```css +.foo { + min-width: 100px; + max-width: 1080px; + width: 400px; /* this is from the design */ +} +``` + +### Ignoring one of the property + +**Using explicit `--ignore` flag** +to ignore the width, you can use new flag `--ignore` set to width. like so - `--ignore=width` + +```css +.foo { + min-width: 100px; + max-width: 1080px; + /* width: 400px; this is ignored by --ignore flag */ +} +``` + +**Using `?` keyword** +Otherwise, you can simply use silincer keyword `?` to ignore the width, like so - `--width=100px-1080px-?` + +This will also generate style like below. + +```css +.foo { + min-width: 100px; + max-width: 1080px; + /* width: 400px; this is ignored by "?" keyword */ +} +``` + +### Referencing current value with `.` + +Setting max-width to current width (based on design) with - `--width=100px-.-.` + +This will generate style like below. + +```css +.foo { + min-width: 100px; + max-width: 400px; /* the current width from design */ + width: 400px; /* the current width from design */ +} +``` + +## See Also + +- [`--max-width`](../--max-width) +- [`--min-width`](../--min-width) +- [`--height`](../--height) diff --git a/packages/support-flags/--width/index.ts b/packages/support-flags/--width/index.ts new file mode 100644 index 00000000..44b9fabb --- /dev/null +++ b/packages/support-flags/--width/index.ts @@ -0,0 +1,18 @@ +import { DimensionLength } from "@reflect-ui/core"; + +export const flag_key__width = "width"; + +export const flag_key_alias__width = [flag_key__width]; + +export interface WidthFlag { + flag: typeof flag_key__width; + + value: + | DimensionLength + | { + min?: DimensionLength; + max?: DimensionLength; + initial?: DimensionLength; + }; + _raw?: string; +} diff --git a/packages/support-flags/index.ts b/packages/support-flags/index.ts index a1d48997..85d4a3ef 100644 --- a/packages/support-flags/index.ts +++ b/packages/support-flags/index.ts @@ -1,29 +1,4 @@ -import { parse as parseflags } from "@design-sdk/flags/parsing-strategy-dashdash"; - -import { flag_key__artwork } from "./--artwork"; -import { flag_key__as_wrap } from "./--as-wrap"; -import { flag_key__module } from "./--module"; export * from "./types"; - -export function parse(name: string) { - try { - return parseflags(name, [ - { - name: flag_key__artwork, - type: "bool", - }, - { - name: flag_key__as_wrap, - type: "bool", - }, - { - name: flag_key__module, - type: "bool", // TODO: support string also. - }, - //. TODO: add other flags under here. - ]); - } catch (_) { - console.error("error while parsing flags", _); - return {}; - } -} +export * as keys from "./keys"; +export { parse } from "./parse"; +export type { FlagsParseResult } from "./parse"; diff --git a/packages/support-flags/keys.ts b/packages/support-flags/keys.ts new file mode 100644 index 00000000..3761cb8e --- /dev/null +++ b/packages/support-flags/keys.ts @@ -0,0 +1,61 @@ +import { flag_key_alias__as_h1, flag_key__as_h1 } from "./--as-h1"; +import { flag_key_alias__as_h2, flag_key__as_h2 } from "./--as-h2"; +import { flag_key_alias__as_h3, flag_key__as_h3 } from "./--as-h3"; +import { flag_key_alias__as_h4, flag_key__as_h4 } from "./--as-h4"; +import { flag_key_alias__as_h5, flag_key__as_h5 } from "./--as-h5"; +import { flag_key_alias__as_h6, flag_key__as_h6 } from "./--as-h6"; +import { flag_key_alias__as_p, flag_key__as_p } from "./--as-p"; +import { flag_key_alias__as_span, flag_key__as_span } from "./--as-span"; + +import { flag_key_alias__width, flag_key__width } from "./--width"; +import { flag_key_alias__min_width, flag_key__min_width } from "./--min-width"; +import { flag_key_alias__max_width, flag_key__max_width } from "./--max-width"; + +import { flag_key_alias__height, flag_key__height } from "./--height"; +// prettier-ignore +import { flag_key_alias__min_height, flag_key__min_height } from "./--min-height"; +// prettier-ignore +import { flag_key_alias__max_height, flag_key__max_height } from "./--max-height"; +import { flag_key_alias__fix_width, flag_key__fix_width } from "./--fix-width"; +// prettier-ignore +import { flag_key_alias__fix_height, flag_key__fix_height } from "./--fix-height"; + +export { + flag_key__as_h1, + flag_key__as_h2, + flag_key__as_h3, + flag_key__as_h4, + flag_key__as_h5, + flag_key__as_h6, +}; +export { flag_key__as_p }; +export { flag_key__as_span }; + +export { + flag_key__width, + flag_key__min_width, + flag_key__max_width, + flag_key__height, + flag_key__min_height, + flag_key__max_height, +}; +export { flag_key__fix_width, flag_key__fix_height }; + +export const alias = { + as_h1: flag_key_alias__as_h1, + as_h2: flag_key_alias__as_h2, + as_h3: flag_key_alias__as_h3, + as_h4: flag_key_alias__as_h4, + as_h5: flag_key_alias__as_h5, + as_h6: flag_key_alias__as_h6, + as_p: flag_key_alias__as_p, + as_span: flag_key_alias__as_span, + width: flag_key_alias__width, + min_width: flag_key_alias__min_width, + max_width: flag_key_alias__max_width, + height: flag_key_alias__height, + min_height: flag_key_alias__min_height, + max_height: flag_key_alias__max_height, + fix_width: flag_key_alias__fix_width, + fix_height: flag_key_alias__fix_height, +}; diff --git a/packages/support-flags/parse.ts b/packages/support-flags/parse.ts new file mode 100644 index 00000000..319fc834 --- /dev/null +++ b/packages/support-flags/parse.ts @@ -0,0 +1,301 @@ +import { + parse as parseflags, + Option, + Results, +} from "@design-sdk/flags/parsing-strategy-dashdash"; + +import * as keys from "./keys"; + +import { flag_key__artwork } from "./--artwork"; +import { flag_key__as_wrap } from "./--as-wrap"; +import { flag_key__module } from "./--module"; +import type { + HeadingFlag, + TextElementPreferenceFlag, + AsParagraphFlag, + AsTextSpanFlag, + SimpleBooleanValueFlag, + FixWHFlag, + WHDeclarationFlag, +} from "./types"; + +export type FlagsParseResult = Results & { + __meta: { + [key: string]: boolean; + }; +}; + +export function parse(name: string): FlagsParseResult { + try { + const _raw_parsed = parseflags(name, [ + { + name: flag_key__artwork, + type: "bool", + }, + { + name: flag_key__as_wrap, + type: "bool", + }, + //#region + __h1_alias_pref, + __h2_alias_pref, + __h3_alias_pref, + __h4_alias_pref, + __h5_alias_pref, + __h6_alias_pref, + __p_alias_pref, + __textspan_alias_pref, + //#endregion + + //#region + __width_alias_pref, + __max_width_alias_pref, + __min_width_alias_pref, + __height_alias_pref, + __max_height_alias_pref, + __min_height_alias_pref, + //#endregion + + //#region + __fix_width_alias_pref, + __fix_height_alias_pref, + //#endregion + + { + name: flag_key__module, + type: "bool", // TODO: support string also. + }, + //. TODO: add other flags under here. + ]); + + const as_heading_flag = transform_heading_alias_from_raw(_raw_parsed); + const as_paragraph_flag = handle_single_boolean_flag_alias( + _raw_parsed, + keys.alias.as_p + ); + const as_span_flag = handle_single_boolean_flag_alias( + _raw_parsed, + keys.alias.as_span + ); + + const wh_declaration_flag = + transform_wh_declaration_alias_from_raw(_raw_parsed); + const fix_wh_flag = handle_single_boolean_flag_alias( + _raw_parsed, + [...keys.alias.fix_width, ...keys.alias.fix_height] + ); + // console.log("_raw_parsed", _raw_parsed); + + return { + ..._raw_parsed, + ...as_heading_flag, + ...(as_paragraph_flag ?? {}), + ...(as_span_flag ?? {}), + ...(wh_declaration_flag ?? {}), + ...(fix_wh_flag ?? {}), + __meta: { + contains_heading_flag: notempty(as_heading_flag), + contains_paragraph_flag: notempty(as_paragraph_flag), + contains_span_flag: notempty(as_span_flag), + contains_wh_declaration_flag: notempty(as_span_flag), + contains_fix_wh_flag: notempty(fix_wh_flag), + }, + }; + } catch (_) { + // TODO: this can happen when unregistered flag is used. this will be fixed. + console.error("error while parsing flags", _); + return {} as any; + } +} + +const notempty = (obj) => Object.keys(obj ?? {}).length > 0; + +const _simple_boolean_value_flag_prefernce_mapper = ( + k: string | Array +): Option => + Array.isArray(k) + ? { + names: k, + type: "bool", + } + : { + name: k, + type: "bool", + }; + +function handle_single_boolean_flag_alias( + raw: { [key: string]: boolean }, + alias: string[] +) { + // e.g. `[ { h1: true } ]` + const mapped: { key: string; value: boolean }[] = alias.map((_) => ({ + key: _, + value: raw[_], + })); + + // e.g `{ h1: {flag: "h1", value: true} }` + const converted: { [key: string]: T } = mapped.reduce((acc, c, i) => { + if (raw[c.key]) { + return { + ...acc, + [c.key]: { flag: c.key, value: raw[c.key], _raw: String(raw) }, + }; + } + return acc; + }, {}); + + if (Object.keys(converted).length > 0) return converted; +} + +function transform_heading_alias_from_raw(raw: { [key: string]: boolean }): { + [key: string]: HeadingFlag; +} { + const _h1_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h1 + ); + if (_h1_alias) return _h1_alias; + + const _h2_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h2 + ); + if (_h2_alias) return _h2_alias; + + const _h3_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h3 + ); + if (_h3_alias) return _h3_alias; + + const _h4_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h4 + ); + if (_h4_alias) return _h4_alias; + + const _h5_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h5 + ); + if (_h5_alias) return _h5_alias; + + const _h6_alias = handle_single_boolean_flag_alias( + raw, + keys.alias.as_h6 + ); + if (_h6_alias) return _h6_alias; +} + +const __h1_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h1 +); + +const __h2_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h2 +); + +const __h3_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h3 +); + +const __h4_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h4 +); + +const __h5_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h5 +); + +const __h6_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_h6 +); + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- + +const __p_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_p +); + +const __textspan_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.as_span +); + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- + +const _simple_custom_string_value_flag_prefernce_mapper = ( + k: string | Array +): Option => + Array.isArray(k) + ? { + names: k, + // e.g. 100, 100px, 100%, . + type: "string", + } + : { + name: k, + // e.g. 100, 100px, 100%, . + type: "string", + }; + +const __width_alias_pref = _simple_custom_string_value_flag_prefernce_mapper( + keys.alias.width +); +const __max_width_alias_pref = + _simple_custom_string_value_flag_prefernce_mapper(keys.alias.max_width); +const __min_width_alias_pref = + _simple_custom_string_value_flag_prefernce_mapper(keys.alias.min_width); + +const __height_alias_pref = _simple_custom_string_value_flag_prefernce_mapper( + keys.alias.height +); +const __max_height_alias_pref = + _simple_custom_string_value_flag_prefernce_mapper(keys.alias.max_height); +const __min_height_alias_pref = + _simple_custom_string_value_flag_prefernce_mapper(keys.alias.min_height); + +function transform_wh_declaration_alias_from_raw(raw: { [key: string]: any }): { + [key: string]: WHDeclarationFlag; +} { + const handle = (key) => { + if (raw[key]) { + return { + [key]: { + flag: key, + value: Number(raw[key]), // TODO: add more parser + _raw: raw[key] as string, + } as WHDeclarationFlag, + }; + } + }; + + return [ + keys.flag_key__width, + keys.flag_key__min_width, + keys.flag_key__max_width, + + keys.flag_key__height, + keys.flag_key__min_height, + keys.flag_key__max_height, + ].reduce((acc, c) => { + const d = handle(c); + if (d) { + return { + ...acc, + ...d, + }; + } + return acc; + }, {}); +} + +const __fix_width_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.fix_width +); +const __fix_height_alias_pref = _simple_boolean_value_flag_prefernce_mapper( + keys.alias.fix_height +); diff --git a/packages/support-flags/types.ts b/packages/support-flags/types.ts index fdfec241..8fc6ca12 100644 --- a/packages/support-flags/types.ts +++ b/packages/support-flags/types.ts @@ -1,5 +1,100 @@ -import { ArtworkFlag } from "./--artwork"; +import type { ArtworkFlag } from "./--artwork"; +import type { AsHeading1Flag } from "./--as-h1"; +import type { AsHeading2Flag } from "./--as-h2"; +import type { AsHeading3Flag } from "./--as-h3"; +import type { AsHeading4Flag } from "./--as-h4"; +import type { AsHeading5Flag } from "./--as-h5"; +import type { AsHeading6Flag } from "./--as-h6"; +import type { AsParagraphFlag } from "./--as-p"; +import type { AsTextSpanFlag } from "./--as-span"; +import type { WidthFlag } from "./--width"; +import type { MinWidthFlag } from "./--min-width"; +import type { MaxWidthFlag } from "./--max-width"; +import type { HeightFlag } from "./--height"; +import type { MinHeightFlag } from "./--min-height"; +import type { MaxHeightFlag } from "./--max-height"; +import { FixWidthFlag } from "./--fix-width"; +import { FixHeightFlag } from "./--fix-height"; -// export { ArtworkFlag }; +export type Flag = + // + ArtworkFlag | TextElementPreferenceFlag | WHDeclarationFlag | FixWHFlag; -export type Flag = ArtworkFlag; +export interface SimpleBooleanValueFlag { + flag: string; + value: boolean; + _raw?: string; +} + +export type WHDeclarationFlag = WidthDeclarationFlag | HeightDeclarationFlag; + +export type WidthDeclarationFlag = WidthFlag | MinWidthFlag | MaxWidthFlag; +export type HeightDeclarationFlag = HeightFlag | MinHeightFlag | MaxHeightFlag; + +export type FixWHFlag = FixWidthFlag | FixHeightFlag; + +/** + * Type alias for a flag that can be used to set the element preference to render a text + * + * - `h1` + * - `h2` + * - `h3` + * - `h4` + * - `h5` + * - `h6` + * - `p` + * - `span` + */ +export type TextElementPreferenceFlag = + | HeadingFlag + | AsParagraphFlag + | AsTextSpanFlag; + +/** + * Type alias for a flag that can be used to set the heading level. + * from 1 to 6. + * + * - `--as-h1` + * - `--as-h2` + * - `--as-h3` + * - `--as-h4` + * - `--as-h5` + * - `--as-h6` + */ +export type HeadingFlag = + | AsHeading1Flag + | AsHeading2Flag + | AsHeading3Flag + | AsHeading4Flag + | AsHeading5Flag + | AsHeading6Flag; + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +export type { ArtworkFlag }; + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +export type { + AsHeading1Flag, + AsHeading2Flag, + AsHeading3Flag, + AsHeading4Flag, + AsHeading5Flag, + AsHeading6Flag, +}; + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +export type { AsParagraphFlag }; +export type { AsTextSpanFlag }; + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +export type { WidthFlag, MinWidthFlag, MaxWidthFlag }; +export type { HeightFlag, MinHeightFlag, MaxHeightFlag }; +export type { FixWidthFlag, FixHeightFlag }; diff --git a/packages/support-flags/v/README.md b/packages/support-flags/v/README.md new file mode 100644 index 00000000..d495213b --- /dev/null +++ b/packages/support-flags/v/README.md @@ -0,0 +1,41 @@ +# Reserved Values + +## Falsy Values + +- true +- False +- yes + +## Truthy Values + +- True +- false +- no + +## Units + +- vw +- vh +- em +- px + +## Length + +## Keywords + +- this + +## Explicit String + +- "string value" + +**Example** + +> When specific key only excepts a string value, it will be treated as a string value. Otherwise, by default, It will be ignored. (It may also break whole process. be careful with it) + +``` +--name=0 // invalid 🚫 +--name="0" // valid 👍 +--name=true // invalid 🚫 +--name=true // valid 👍 +``` diff --git a/scripts/docs-copy/flags-api-docs.js b/scripts/docs-copy/flags-api-docs.js new file mode 100644 index 00000000..463bd6bb --- /dev/null +++ b/scripts/docs-copy/flags-api-docs.js @@ -0,0 +1,64 @@ +const fs = require("fs"); +const path = require("path"); + +const origin = "./packages/support-flags"; +const target = "./docs/flags"; +const github_base_url = + "https://github.com/gridaco/designto-code/tree/main/packages/support-flags"; +/** + * copies the README.md file under each directory under "origin" to "target" + * the README.md content will be preserved, but the file name will be changed to current folder name + * for example, if the file is `--action/README.md`, the file will be copied and renamed to `--action.md` + * + * the origin directory will have multiple subdirectory with one README.md file. + * these files under each subdirectory will be copied directly under "target" with above new file name. + */ +function copy() { + const files = []; + + // read all directories under origin directory with pattern that matches regex `/^--[a-z]+(.*?)$/` as prefix + // add README.md files to files array + fs.readdirSync(origin).forEach((dir) => { + if (dir.match(/^--[a-z]+(.*?)$/)) { + const dirPath = path.join(origin, dir); + const filesInDir = fs.readdirSync(dirPath); + filesInDir.forEach((file) => { + if (file === "README.md") { + files.push(path.join(dirPath, file)); + } + }); + } + }); + + // these are custom directories under origin. [`----disable`, `---custom`] + // add README.md under these directory, add to files array + ["----disable", "---custom"].forEach((dir) => { + const dirPath = path.join(origin, dir); + const filesInDir = fs.readdirSync(dirPath); + filesInDir.forEach((file) => { + if (file === "README.md") { + files.push(path.join(dirPath, file)); + } + }); + }); + + // read the content and extension of each file, save it to a map. where key being the file path, value being the content and extension + const fileMap = new Map(); + files.forEach((file) => { + const content = fs.readFileSync(file, "utf8"); + const ext = path.extname(file); + // make a key. the key is extracted from var - file, which is a paht. extract last directory name and use it as key. e.g. "../../--action/README.md" -> "--action" + const key = path.basename(path.dirname(file)); + fileMap.set(key, { content, ext }); + }); + + // copy each file to target directory + fileMap.forEach((value, key) => { + const newFile = path.join(target, `${key}${value.ext}`); + fs.writeFileSync(newFile, value.content); + }); +} + +if (require.main === module) { + copy(); +} diff --git a/scripts/docs-deploy/pre-deploy.sh b/scripts/docs-deploy/pre-deploy.sh new file mode 100644 index 00000000..6de5a01a --- /dev/null +++ b/scripts/docs-deploy/pre-deploy.sh @@ -0,0 +1 @@ +node ../docs-copy/flags-api-docs.js \ No newline at end of file