Skip to content

Plugins support with builtin google-fonts & text fit plugin #209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d260001
resolve flex grow being blocked by positioned wrapper token
softmarshmallow Mar 31, 2023
a417ed6
add google fonts url builder
softmarshmallow Mar 31, 2023
8a83961
add google fonts meta json
softmarshmallow Mar 31, 2023
5a13243
add system fonts
softmarshmallow Mar 31, 2023
a4a9d76
init support-fonts
softmarshmallow Mar 31, 2023
33992ed
add unified fonts() function
softmarshmallow Mar 31, 2023
737bead
add bulk fonts url building
softmarshmallow Mar 31, 2023
6f1b2cb
add google fonts support for inline css vanilla html builders
softmarshmallow Mar 31, 2023
e3b0a83
Merge pull request #205 from gridaco/support-fonts
softmarshmallow Mar 31, 2023
6656cfd
init vanilla-textfit plugin pkg
softmarshmallow Apr 4, 2023
d277ba6
update docs & test
softmarshmallow Apr 5, 2023
6a2a19d
init injector & selector
softmarshmallow Apr 5, 2023
b7fc3fd
rm cleanup
softmarshmallow Apr 5, 2023
74b81c6
init plugin core
softmarshmallow Apr 12, 2023
285b6f0
update plugin core
softmarshmallow Apr 12, 2023
8152926
reserve testing utils pkg
softmarshmallow Apr 12, 2023
8cb9f3a
update with plugins - wip
softmarshmallow Apr 12, 2023
b303e60
update config
softmarshmallow Apr 14, 2023
c8873c4
fix injector
softmarshmallow Apr 14, 2023
abfab64
update mapping
softmarshmallow Apr 14, 2023
a4b0a37
add custom pkg
softmarshmallow Apr 14, 2023
5c87139
add query selector
softmarshmallow Apr 14, 2023
26e3fe2
remove default font fam
softmarshmallow Apr 14, 2023
4eba375
fix yarn
softmarshmallow Apr 14, 2023
fac43c3
update with plugin composer
softmarshmallow Apr 14, 2023
a48f86f
add `raw` option for debugging
softmarshmallow Apr 14, 2023
fb47911
plugin composing & interface update
softmarshmallow Apr 14, 2023
3892a45
clear logs
softmarshmallow Apr 14, 2023
a97f5e9
add builtin plugin resolver
softmarshmallow Apr 14, 2023
5a34064
update interface
softmarshmallow Apr 14, 2023
4c3d088
add plugin composer to main d2c
softmarshmallow Apr 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,26 @@ import type {
VanillaFrameworkConfig,
} from "@grida/builder-config";
import { LICENSE_CE } from "./license";
import type { TPlugin } from "@code-plugin/core";

export type FigmaNodeInput =
| string
| { url: string; version: string }
| { filekey: string; node: string; version: string };

export interface CodeRequest {
type DebugOptions = {
/**
* if true, the response will be a vanilla html without other data.
* @default false
*/
raw?: boolean;
};

export type CodeRequest = DebugOptions & {
figma: FigmaNodeInput;
framework: Partial<FrameworkConfig>;
}
plugins?: TPlugin[];
};

export type CodeResponse = FigmaToVanillaResponse;

Expand Down
4 changes: 4 additions & 0 deletions code/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import type { FrameworkConfig } from "@grida/builder-config";
import { defaultConfigByFramework } from "@grida/builder-config-preset";
import { Language } from "@grida/builder-platform-types";
import { formatCode } from "dart-style";
import type { TPlugin } from "@code-plugin/core";

export async function code({
auth,
uri,
framework,
plugins,
}: {
auth:
| {
Expand All @@ -24,6 +26,7 @@ export async function code({
| { accessToken: string };
uri: string;
framework: FrameworkConfig;
plugins?: TPlugin[];
}) {
//

Expand Down Expand Up @@ -59,6 +62,7 @@ export async function code({
...framework,
},
asset_config: { asset_repository: MainImageRepository.instance },
plugins,
});

const src = postproc_src(
Expand Down
5 changes: 5 additions & 0 deletions editor/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const packages = [
"@code-features/documentation",
"@code-features/component",
"@code-features/flags",
"@code-features/fonts",
// -----------------------------
// plugins
"@code-plugin/core",
"@code-plugin/text-fit",
// -----------------------------

// reflect-ui ui framework
Expand Down
23 changes: 14 additions & 9 deletions editor/pages/api/v1/code/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ export default async function handler(req, res) {
const figma_access_token_type: FigmaAccessTokenType =
figma_access_token.startsWith("figd") ? "fpat" : "fat";

const { figma: figmaInput, framework } = req.body as CodeRequest;
const {
figma: figmaInput,
framework,
plugins,
raw,
} = req.body as CodeRequest;

assert(typeof figmaInput === "string", "`body.figma` must be a string");

try {
const coderes = await code({
uri: figmaInput,
framework: framework as FrameworkConfig,
plugins,
auth:
figma_access_token_type === "fat"
? {
Expand All @@ -44,9 +50,7 @@ export default async function handler(req, res) {
},
});

const { src: spchar_src, figma, target } = coderes;

const src = replaceSpecialChars(spchar_src);
const { src, figma, target } = coderes;

const response: FigmaToVanillaResponse = {
figma: {
Expand Down Expand Up @@ -82,7 +86,12 @@ export default async function handler(req, res) {
warnings: [],
};

res.status(200).json(response);
if (raw) {
// if debug option raw is set, return raw html
res.status(200).send(src);
} else {
res.status(200).json(response);
}
} catch (e) {
res.status(500).json({
message: e.message,
Expand All @@ -98,7 +107,3 @@ export default async function handler(req, res) {
});
}
}

function replaceSpecialChars(input: string): string {
return input.replace(/\\t/g, "\t").replace(/\\n/g, "\n");
}
1 change: 1 addition & 0 deletions packages/builder-config/configure/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./framework-config";
export * from "./target-build-platform";
export * from "./build-config";
export * from "./plugin-config";
2 changes: 2 additions & 0 deletions packages/builder-config/configure/plugin-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import type { TPlugin } from "@code-plugin/core";
export type Plugins = ReadonlyArray<TPlugin>;
2 changes: 1 addition & 1 deletion packages/builder-web-core/k/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const image_smallest_fallback_source_base_64 =

export const user_agent_stylesheet_override_default = <CSSProperties>{
margin: "0px",
"font-family": `Helvetica, "Helvetica Neue", Roboto, Noto, Arial, sans-serif`,
// we don't set default font-family here, because we don't want to add !important to every other font-family.
};

export const default_generic_fallback_font_family = "sans-serif";
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export function export_vanilla_preview_source(
const builder = new HtmlIdCssModuleBuilder({
entry: widget,
config: {
fonts: {
services: ["system", "fonts.google.com"],
},
...config,
// required (for safety, for consistant preview)
disable_all_optimizations: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import {
} from "coli";
import { Framework } from "@grida/builder-platform-types";
import { stringfy as stringfyHtmlMeta, HtmlMeta } from "../html-meta";
import { TFontService } from "@code-features/fonts";
import { htmlFontsMiddleware } from "./html-fonts-middleware";
import type { Plugin } from "@code-plugin/core";

interface CssDeclaration {
key: {
Expand All @@ -36,6 +39,10 @@ interface CssDeclaration {
export type HtmlModuleBuilderConfig = {
disable_all_optimizations?: boolean;
additional_css_declarations?: CssDeclaration[];
fonts?: {
services: ReadonlyArray<TFontService>;
};
plugins?: ReadonlyArray<Plugin>;
};

export class HtmlIdCssModuleBuilder {
Expand All @@ -44,6 +51,7 @@ export class HtmlIdCssModuleBuilder {
private readonly stylesMapper: StylesConfigMapBuilder;
private readonly stylesRepository: StylesRepository;
private readonly namer: ScopedVariableNamer;
private readonly _head: string[] = [];
readonly config: HtmlModuleBuilderConfig;

constructor({
Expand Down Expand Up @@ -77,6 +85,24 @@ export class HtmlIdCssModuleBuilder {
: // ALWAYS USE EXACT OVERLAPPING STYLE REDUCTION STRATEGY FOR PREVIEW VANILLA
create_duplication_reduction_map
);

if (config.fonts) {
htmlFontsMiddleware(this, config.fonts.services);
}
}

private afterVanillaCSSBundle() {
this.config.plugins?.forEach((p) => {
p.apply({
hooks: {
afterVanillaCSSBundle: {
tap: (name, fn) => {
fn({ builder: this });
},
},
},
});
});
}

private styledConfig(
Expand All @@ -98,6 +124,21 @@ export class HtmlIdCssModuleBuilder {
);
}

/**
* adds literal string to <head> tag
*/
head(...items: string[]) {
this._head.push(...items);
return this;
}

/**
* build the part head, excluding styles
*/
partHead(): string {
return this._head.join("\n");
}

partStyles(): string {
const css_declarations: CssDeclaration[] = [];

Expand Down Expand Up @@ -180,8 +221,14 @@ export class HtmlIdCssModuleBuilder {
indentation: "\t",
});

const strfied_css = this.partStyles();

// hook TODO: (execution matters due to textfit plugin contributes to head. this is a design flaw. needs to be fixed.)
this.afterVanillaCSSBundle();

const final = html_render({
css: this.partStyles(),
head: this.partHead(),
css: strfied_css,
body: strfied_body,
});

Expand Down Expand Up @@ -224,7 +271,15 @@ function injectIdToJsx(jsx: JSXElementLike, id: string) {
}
}

const html_render = ({ css, body }: { css: string; body: string }) => {
const html_render = ({
head,
css,
body,
}: {
head: string;
css: string;
body: string;
}) => {
// TODO: fixme - this is inacurate (the first line won't be indented)
const indenter = (s: string, tabs: number = 0) =>
s.replace(/\n/g, "\n" + "\t".repeat(tabs));
Expand All @@ -238,6 +293,7 @@ ${indenter(
}),
2
)}
${indenter(head, 2)}
<style>
${indenter(css, 3)}
</style>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { TFontService, fonts } from "@code-features/fonts";
import type { HtmlIdCssModuleBuilder } from "./html-css-id-module-builder";

export function htmlFontsMiddleware(
builder: HtmlIdCssModuleBuilder,
services: ReadonlyArray<TFontService>
) {
try {
// TODO: we need better way to get used fonts.
const styles = builder.partStyles();

// parse lines with "font-family: ..."
const matches = styles.match(/font-family:.*?;/g);
if (!matches) {
return;
} else {
const font_families = matches
.map((m) => {
return m
.replace(/font-family:/, "")
.replace(/;/, "")
.trim()
.split(",")
.map((f) => f.trim().replace(/"/g, "").replace(/'/g, "").trim());
})
.flat()
.filter((f) => f.length > 0)
.filter(
(f) =>
f !== "inherit" &&
f !== "initial" &&
f !== "unset" &&
f !== "serif" &&
f !== "sans-serif" &&
f !== "monospace" &&
f !== "cursive" &&
f !== "fantasy" &&
f !== "system-ui"
);

const resolved = fonts({
fonts: font_families,
resolution: "fonts.googleapis.com/css2",
services,
});

// create <link> tag for each font, which is going to be added to <head> tag.
const links = [
`<link rel="preconnect" href="https://fonts.googleapis.com">`,
`<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>`,
...Object.keys(resolved).map((f) => {
const { urls } = resolved[f];
return `<link rel="stylesheet" href="${urls["*"]}">`;
}),
];

builder.head(...links);
}
} catch (e) {
console.error(`error while resolving fonts from [${services.join(",")}]`);
}
}
16 changes: 16 additions & 0 deletions packages/designto-code/plugin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import VanillaTextFitPlugin from "@code-plugin/text-fit";
import { TPlugin, composePlugin as composeAnyPlugin } from "@code-plugin/core";

const BUILTIN_PLUGINS = {
"@code-plugin/text-fit": VanillaTextFitPlugin,
};

function resolver(name, params) {
if (name in BUILTIN_PLUGINS) {
return new BUILTIN_PLUGINS[name](params);
}
}

export function composePlugin(input: TPlugin) {
return composeAnyPlugin(input, resolver);
}
3 changes: 3 additions & 0 deletions packages/designto-code/plugin/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Builtin plugins composition

- `@code-plugin/text-fit`
Loading