♻️ remove csso dependency

do a custom css optimization instead
This commit is contained in:
platane
2022-11-03 08:25:35 +01:00
committed by Platane
parent f83b9ab0c3
commit b40f17a02e
10 changed files with 654 additions and 611 deletions

View File

@@ -1,7 +1,6 @@
import * as fs from "fs";
import * as path from "path";
import * as core from "@actions/core";
import { generateContributionSnake } from "./generateContributionSnake";
import { parseOutputsOption } from "./outputsOptions";
(async () => {
@@ -14,6 +13,9 @@ import { parseOutputsOption } from "./outputsOptions";
]
);
const { generateContributionSnake } = await import(
"./generateContributionSnake"
);
const results = await generateContributionSnake(userName, outputs);
outputs.forEach((out, i) => {

View File

@@ -0,0 +1,26 @@
import { minifyCss } from "../css-utils";
it("should minify css", () => {
expect(
minifyCss(`
.c {
color : red ;
}
`)
).toBe(".c{color:red}");
expect(
minifyCss(`
.c {
top : 0;
color : red ;
}
# {
animation: linear 10;
}
`)
).toBe(".c{top:0;color:red}#{animation:linear 10}");
});

View File

@@ -0,0 +1,38 @@
const percent = (x: number) =>
parseFloat((x * 100).toFixed(2)).toString() + "%";
const mergeKeyFrames = (keyframes: { t: number; style: string }[]) => {
const s = new Map<string, number[]>();
for (const { t, style } of keyframes) {
s.set(style, [...(s.get(style) ?? []), t]);
}
return Array.from(s.entries())
.map(([style, ts]) => ({ style, ts }))
.sort((a, b) => a.ts[0] - b.ts[0]);
};
/**
* generate the keyframe animation from a list of keyframe
*/
export const createAnimation = (
name: string,
keyframes: { t: number; style: string }[]
) =>
`@keyframes ${name}{` +
mergeKeyFrames(keyframes)
.map(({ style, ts }) => ts.map(percent).join(",") + `{${style}}`)
.join("") +
"}";
/**
* remove white spaces
*/
export const minifyCss = (css: string) =>
css
.replace(/\s+/g, " ")
.replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, ""))
.replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, ""))
.replace(/.\s+[,;:{}()]/g, (a) => a.replace(/\s+/g, ""))
.replace(/[,;:{}()]\s+./g, (a) => a.replace(/\s+/g, ""))
.replace(/\;\s*\}/g, "}")
.trim();

View File

@@ -1,6 +1,7 @@
import type { Color, Empty } from "@snk/types/grid";
import type { Point } from "@snk/types/point";
import { h } from "./utils";
import { createAnimation } from "./css-utils";
import { h } from "./xml-utils";
export type Options = {
colorDots: Record<Color, string>;
@@ -11,8 +12,6 @@ export type Options = {
sizeDotBorderRadius: number;
};
const percent = (x: number) => (x * 100).toFixed(2);
export const createGrid = (
cells: (Point & { t: number | null; color: Color | Empty })[],
{ sizeDotBorderRadius, sizeDot, sizeCell }: Options,
@@ -26,38 +25,40 @@ export const createGrid = (
stroke-width: 1px;
stroke: var(--cb);
animation: none ${duration}ms linear infinite;
width: ${sizeDot}px;
height: ${sizeDot}px;
}`,
];
let i = 0;
for (const { x, y, color, t } of cells) {
const id = t && "c" + (i++).toString(36);
const s = sizeCell;
const d = sizeDot;
const m = (s - d) / 2;
const m = (sizeCell - sizeDot) / 2;
if (t !== null) {
if (t !== null && id) {
const animationName = id;
styles.push(
`@keyframes ${animationName} {` +
`${percent(t - 0.0001)}%{fill:var(--c${color})}` +
`${percent(t + 0.0001)}%,100%{fill:var(--ce)}` +
"}",
createAnimation(animationName, [
{ t: t - 0.0001, style: `fill:var(--c${color})` },
{ t: t + 0.0001, style: `fill:var(--ce)` },
{ t: 1, style: `fill:var(--ce)` },
]),
`.c.${id}{fill: var(--c${color}); animation-name: ${animationName}}`
`.c.${id}{
fill: var(--c${color});
animation-name: ${animationName}
}`
);
}
svgElements.push(
h("rect", {
class: ["c", id].filter(Boolean).join(" "),
x: x * s + m,
y: y * s + m,
x: x * sizeCell + m,
y: y * sizeCell + m,
rx: sizeDotBorderRadius,
ry: sizeDotBorderRadius,
width: d,
height: d,
})
);
}

View File

@@ -9,12 +9,12 @@ import { getHeadX, getHeadY } from "@snk/types/snake";
import type { Snake } from "@snk/types/snake";
import type { Grid, Color, Empty } from "@snk/types/grid";
import type { Point } from "@snk/types/point";
import type { AnimationOptions } from "@snk/gif-creator";
import { createSnake } from "./snake";
import { createGrid } from "./grid";
import { createStack } from "./stack";
import { h } from "./utils";
import * as csso from "csso";
import { AnimationOptions } from "@snk/gif-creator";
import { h } from "./xml-utils";
import { minifyCss } from "./css-utils";
export type DrawOptions = {
colorDots: Record<Color, string>;
@@ -132,7 +132,7 @@ export const createSvg = (
return optimizeSvg(svg);
};
const optimizeCss = (css: string) => csso.minify(css).css;
const optimizeCss = (css: string) => minifyCss(css);
const optimizeSvg = (svg: string) => svg;
const generateColorVar = (drawOptions: DrawOptions) =>

View File

@@ -2,10 +2,7 @@
"name": "@snk/svg-creator",
"version": "1.0.0",
"dependencies": {
"@snk/solver": "1.0.0",
"csso": "5.0.3"
"@snk/solver": "1.0.0"
},
"devDependencies": {
"@types/csso": "5.0.0"
}
"devDependencies": {}
}

View File

@@ -1,7 +1,8 @@
import { getSnakeLength, snakeToCells } from "@snk/types/snake";
import type { Snake } from "@snk/types/snake";
import type { Point } from "@snk/types/point";
import { h } from "./utils";
import { h } from "./xml-utils";
import { createAnimation } from "./css-utils";
export type Options = {
colorSnake: string;
@@ -9,8 +10,6 @@ export type Options = {
sizeDot: number;
};
const percent = (x: number) => (x * 100).toFixed(2);
const lerp = (k: number, a: number, b: number) => (1 - k) * a + k * b;
export const createSnake = (
@@ -55,8 +54,8 @@ export const createSnake = (
const styles = [
`.s{
shape-rendering:geometricPrecision;
fill:var(--cs);
shape-rendering: geometricPrecision;
fill: var(--cs);
animation: none linear ${duration}ms infinite
}`,
@@ -64,16 +63,17 @@ export const createSnake = (
const id = `s${i}`;
const animationName = id;
return [
`@keyframes ${animationName} {` +
removeInterpolatedPositions(
positions.map((tr, i, { length }) => ({ ...tr, t: i / length }))
)
.map((p) => `${percent(p.t)}%{${transform(p)}}`)
.join("") +
"}",
const keyframes = removeInterpolatedPositions(
positions.map((tr, i, { length }) => ({ ...tr, t: i / length }))
).map(({ t, ...p }) => ({ t, style: transform(p) }));
`.s.${id}{${transform(positions[0])};animation-name: ${animationName}}`,
return [
createAnimation(animationName, keyframes),
`.s.${id}{
${transform(positions[0])};
animation-name: ${animationName}
}`,
];
}),
].flat();

View File

@@ -1,12 +1,11 @@
import type { Color, Empty } from "@snk/types/grid";
import { h } from "./utils";
import { createAnimation } from "./css-utils";
import { h } from "./xml-utils";
export type Options = {
sizeDot: number;
};
const percent = (x: number) => (x * 100).toFixed(2);
export const createStack = (
cells: { t: number | null; color: Color | Empty }[],
{ sizeDot }: Options,
@@ -56,23 +55,28 @@ export const createStack = (
);
styles.push(
`@keyframes ${animationName} {` +
createAnimation(
animationName,
[
...ts.map((t, i, { length }) => [
{ scale: i / length, t: t - 0.0001 },
{ scale: (i + 1) / length, t: t + 0.0001 },
]),
[{ scale: 1, t: 1 }],
]
.flat()
.map(
({ scale, t }) =>
`${percent(t)}%{transform:scale(${scale.toFixed(2)},1)}`
)
.join("\n") +
"}",
...ts
.map((t, i, { length }) => [
{ scale: i / length, t: t - 0.0001 },
{ scale: (i + 1) / length, t: t + 0.0001 },
])
.flat(),
{ scale: 1, t: 1 },
].map(({ scale, t }) => ({
t,
style: `transform:scale(${scale.toFixed(3)},1)`,
}))
),
`.u.${id}{fill:var(--c${color});animation-name:${animationName};transform-origin:${x}px 0}`
`.u.${id} {
fill: var(--c${color});
animation-name: ${animationName};
transform-origin: ${x}px 0
}
`
);
}

1081
yarn.lock

File diff suppressed because it is too large Load Diff