2023-03-06 12:59:38 +01:00
|
|
|
import sass from 'sass';
|
|
|
|
|
2023-03-06 13:02:03 +01:00
|
|
|
export function generateCodeExample(
|
|
|
|
contents: string,
|
|
|
|
autogenCSS: boolean,
|
2023-03-08 17:18:32 +01:00
|
|
|
syntax: 'sass' | 'scss' | null,
|
2023-03-06 13:02:03 +01:00
|
|
|
) {
|
2023-03-08 17:18:32 +01:00
|
|
|
const splitContents = contents.split('\n===\n');
|
2023-03-06 12:59:38 +01:00
|
|
|
|
2023-03-08 17:18:32 +01:00
|
|
|
let scssContents, sassContents, cssContents;
|
|
|
|
switch (syntax) {
|
|
|
|
case 'scss':
|
|
|
|
scssContents = splitContents[0];
|
|
|
|
cssContents = splitContents[1];
|
|
|
|
break;
|
|
|
|
case 'sass':
|
|
|
|
sassContents = splitContents[0];
|
|
|
|
cssContents = splitContents[1];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
scssContents = splitContents[0];
|
|
|
|
sassContents = splitContents[1];
|
|
|
|
cssContents = splitContents[2];
|
|
|
|
if (!sassContents) {
|
|
|
|
throw new Error(`Couldn't find === in:\n${contents}`);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
const scssExamples =
|
|
|
|
scssContents?.split('\n---\n').map((str) => str.trim()) ?? [];
|
|
|
|
const sassExamples =
|
|
|
|
sassContents?.split('\n---\n').map((str) => str.trim()) ?? [];
|
|
|
|
|
|
|
|
if (!cssContents && autogenCSS) {
|
|
|
|
const sections = scssContents ? scssExamples : sassExamples;
|
|
|
|
if (sections.length !== 1) {
|
|
|
|
throw new Error("Can't auto-generate CSS from more than one SCSS block.");
|
|
|
|
}
|
|
|
|
cssContents = sass.compileString(sections[0], {
|
|
|
|
syntax: syntax === 'sass' ? 'indented' : 'scss',
|
|
|
|
}).css;
|
|
|
|
}
|
2023-03-06 12:59:38 +01:00
|
|
|
|
2023-03-08 17:18:32 +01:00
|
|
|
const cssExamples =
|
|
|
|
cssContents?.split('\n---\n').map((str) => str.trim()) ?? [];
|
2023-03-06 12:59:38 +01:00
|
|
|
|
2023-03-08 17:18:32 +01:00
|
|
|
const { canSplit, maxSourceWidth, maxCSSWidth } = getCanSplit(
|
|
|
|
scssExamples,
|
|
|
|
sassExamples,
|
|
|
|
cssExamples,
|
|
|
|
);
|
|
|
|
let splitLocation: number | null = null;
|
|
|
|
if (canSplit) {
|
|
|
|
if (maxSourceWidth < 55 && maxCSSWidth < 55) {
|
|
|
|
splitLocation = 0.5 * 100;
|
|
|
|
} else {
|
|
|
|
// Put the split exactly in between the two longest lines.
|
|
|
|
splitLocation = 0.5 + ((maxSourceWidth - maxCSSWidth) / 110.0 / 2) * 100;
|
|
|
|
}
|
2023-03-06 12:59:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
scss: scssExamples,
|
|
|
|
sass: sassExamples,
|
2023-03-08 17:18:32 +01:00
|
|
|
css: cssExamples,
|
|
|
|
canSplit,
|
|
|
|
splitLocation,
|
2023-03-06 12:59:38 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-26 02:07:51 +01:00
|
|
|
export function getImplStatus(status: string | boolean | null) {
|
2023-02-25 13:44:14 +01:00
|
|
|
switch (status) {
|
|
|
|
case true:
|
|
|
|
return '✓';
|
|
|
|
case false:
|
|
|
|
return '✗';
|
|
|
|
case 'partial':
|
2023-03-07 18:38:28 +01:00
|
|
|
case null:
|
|
|
|
return status;
|
2023-02-25 13:44:14 +01:00
|
|
|
default:
|
|
|
|
return `since ${status}`;
|
|
|
|
}
|
|
|
|
}
|
2023-03-06 12:59:38 +01:00
|
|
|
|
2023-03-08 17:18:32 +01:00
|
|
|
function getCanSplit(
|
2023-03-06 12:59:38 +01:00
|
|
|
scssExamples: string[],
|
|
|
|
sassExamples: string[],
|
2023-03-08 17:18:32 +01:00
|
|
|
cssExamples: string[],
|
2023-03-06 12:59:38 +01:00
|
|
|
) {
|
2023-03-08 17:18:32 +01:00
|
|
|
const exampleSourceLengths = [...scssExamples, ...sassExamples].flatMap(
|
|
|
|
(source) => source.split('\n').map((line) => line.length),
|
|
|
|
);
|
|
|
|
const cssSourceLengths = cssExamples.flatMap((source) =>
|
|
|
|
source.split('\n').map((line) => line.length),
|
|
|
|
);
|
2023-03-06 12:59:38 +01:00
|
|
|
|
|
|
|
const maxSourceWidth = Math.max(...exampleSourceLengths);
|
2023-03-06 13:02:03 +01:00
|
|
|
const maxCSSWidth = Math.max(...cssSourceLengths);
|
2023-03-06 12:59:38 +01:00
|
|
|
|
2023-03-08 17:18:32 +01:00
|
|
|
const canSplit = Boolean(maxCSSWidth && maxSourceWidth + maxCSSWidth < 110);
|
|
|
|
|
|
|
|
return {
|
|
|
|
canSplit,
|
|
|
|
maxSourceWidth,
|
|
|
|
maxCSSWidth,
|
|
|
|
};
|
2023-03-06 12:59:38 +01:00
|
|
|
}
|