weasyprint-tsx 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/ReadMe.pdf +0 -0
- package/bun.lock +166 -0
- package/global.d.ts +16 -0
- package/package.json +11 -0
- package/packages/build/package.json +20 -0
- package/packages/build/src/build.ts +100 -0
- package/packages/build/src/cli.ts +13 -0
- package/packages/build/src/config.ts +90 -0
- package/packages/build/src/orchestrator.ts +61 -0
- package/packages/build/src/server.ts +36 -0
- package/packages/create/cli.js +28 -0
- package/packages/create/package.json +10 -0
- package/packages/create/template/global.d.ts +16 -0
- package/packages/create/template/package.json +18 -0
- package/packages/create/template/src/index.css +21 -0
- package/packages/create/template/src/index.tsx +25 -0
- package/packages/create/template/tsconfig.json +11 -0
- package/packages/create/template/weasyprint-tsx.config.ts +17 -0
- package/packages/ui/package.json +8 -0
- package/packages/ui/src/BlockBox.module.css +16 -0
- package/packages/ui/src/BlockBox.tsx +66 -0
- package/packages/ui/src/CodeBlock.tsx +17 -0
- package/packages/ui/src/DotLine.module.css +24 -0
- package/packages/ui/src/DotLine.tsx +45 -0
- package/packages/ui/src/Equation.module.css +4 -0
- package/packages/ui/src/Equation.tsx +38 -0
- package/packages/ui/src/List.module.css +53 -0
- package/packages/ui/src/List.tsx +120 -0
- package/packages/ui/src/Page.module.css +14 -0
- package/packages/ui/src/Page.tsx +33 -0
- package/packages/ui/src/Table.module.css +55 -0
- package/packages/ui/src/Table.tsx +164 -0
- package/packages/ui/src/Title.module.css +75 -0
- package/packages/ui/src/Titles.tsx +105 -0
- package/packages/ui/src/index.ts +9 -0
- package/packages/ui/src/utils.tsx +26 -0
- package/src/index.css +0 -0
- package/src/index.tsx +16 -0
- package/tsconfig.json +16 -0
- package/weasyprint-tsx.config.ts +7 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
|
|
3
|
+
import { H1, H2, LI, UL } from "@weasyprint-tsx/ui";
|
|
4
|
+
|
|
5
|
+
export default function Document() {
|
|
6
|
+
return (
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charSet="utf-8" />
|
|
10
|
+
<title>My Document</title>
|
|
11
|
+
<link rel="stylesheet" href="index.css" />
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<H1>My Document</H1>
|
|
15
|
+
<H2>Introduction</H2>
|
|
16
|
+
<p>Edit <code>src/index.tsx</code> to start writing your document.</p>
|
|
17
|
+
<UL>
|
|
18
|
+
<LI>Use components from <code>@weasyprint-tsx/ui</code></LI>
|
|
19
|
+
<LI>Style with Tailwind utility classes or plain CSS in <code>src/index.css</code></LI>
|
|
20
|
+
<LI>Run <code>bun run dev</code> for live preview</LI>
|
|
21
|
+
</UL>
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Config } from "@weasyprint-tsx/build";
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
io: {
|
|
5
|
+
engine: "weasyprint",
|
|
6
|
+
output: "output.pdf",
|
|
7
|
+
},
|
|
8
|
+
weasyprint: {
|
|
9
|
+
pdf_forms: true,
|
|
10
|
+
},
|
|
11
|
+
watchdog: {
|
|
12
|
+
path: "./src",
|
|
13
|
+
debounce: 500,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default config;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
margin-left: calc(-1 * var(--block-box-gap, 0));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.block {
|
|
6
|
+
display: inline-block;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
width: calc(var(--ratio, 1) * 100% / var(--block-box-basis, 1));
|
|
9
|
+
vertical-align: var(--block-box-align, middle);
|
|
10
|
+
padding-left: var(--block-box-gap, 0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.centered > * {
|
|
14
|
+
display: block;
|
|
15
|
+
margin: 0 auto;
|
|
16
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ComponentProps, toChildArray, VNode } from "preact";
|
|
2
|
+
import styles from "./BlockBox.module.css";
|
|
3
|
+
import { joinClasses, mergeStyle } from "./utils";
|
|
4
|
+
|
|
5
|
+
interface BlockBoxProps extends ComponentProps<"div"> {
|
|
6
|
+
children: VNode<BlockProps>[] | VNode<BlockProps>;
|
|
7
|
+
gap?: string;
|
|
8
|
+
basis?: number;
|
|
9
|
+
centered?: boolean;
|
|
10
|
+
align?: "middle" | "top" | "bottom";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface BlockProps extends ComponentProps<"div"> {
|
|
14
|
+
ratio?: number;
|
|
15
|
+
centered?: boolean;
|
|
16
|
+
align?: "middle" | "top" | "bottom";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function Block(_props: BlockProps): null {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function BlockBox({
|
|
24
|
+
children,
|
|
25
|
+
className,
|
|
26
|
+
basis,
|
|
27
|
+
gap,
|
|
28
|
+
align,
|
|
29
|
+
centered: parentCentered = true,
|
|
30
|
+
style,
|
|
31
|
+
...props
|
|
32
|
+
}: BlockBoxProps) {
|
|
33
|
+
const blockList = toChildArray(children).filter(
|
|
34
|
+
(child) => (child as VNode).type === Block,
|
|
35
|
+
) as VNode<BlockProps>[];
|
|
36
|
+
|
|
37
|
+
const blockBasis =
|
|
38
|
+
basis ?? blockList.reduce((acc, b) => acc + (b.props.ratio ?? 1), 0);
|
|
39
|
+
|
|
40
|
+
const child = blockList.map(
|
|
41
|
+
({ props: { style, ratio = 1, className, centered, align, ...props } }) => (
|
|
42
|
+
<div
|
|
43
|
+
style={mergeStyle(style, { "--ratio": ratio, "--block-box-align": align })}
|
|
44
|
+
className={joinClasses(
|
|
45
|
+
className,
|
|
46
|
+
styles.block,
|
|
47
|
+
(centered ?? parentCentered) ? styles.centered : undefined,
|
|
48
|
+
)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
children={child}
|
|
57
|
+
className={joinClasses(className, styles.container)}
|
|
58
|
+
style={mergeStyle(style, {
|
|
59
|
+
"--block-box-basis": blockBasis,
|
|
60
|
+
"--block-box-gap": gap,
|
|
61
|
+
"--block-box-align": align,
|
|
62
|
+
})}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import hljs from "highlight.js";
|
|
2
|
+
import "highlight.js/styles/atom-one-dark.css";
|
|
3
|
+
import { ComponentProps } from "preact";
|
|
4
|
+
|
|
5
|
+
interface CodeBlockProps extends Omit<ComponentProps<"code">, "children"> {
|
|
6
|
+
language: string;
|
|
7
|
+
code: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function CodeBlock({ code, language, ...props }: CodeBlockProps) {
|
|
11
|
+
const codeBlock = hljs.highlight(code, { language: language });
|
|
12
|
+
return (
|
|
13
|
+
<pre style={{breakInside : "avoid"}}>
|
|
14
|
+
<code {...props} dangerouslySetInnerHTML={{ __html: codeBlock.value }} />
|
|
15
|
+
</pre>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* block mode: stacked answer lines */
|
|
2
|
+
.block {
|
|
3
|
+
display: block;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.line {
|
|
7
|
+
display: block;
|
|
8
|
+
min-height: var(--dotline-height, 6mm);
|
|
9
|
+
|
|
10
|
+
margin-bottom: 2mm;
|
|
11
|
+
border-bottom: 1px dotted var(--dotline-color, #808080);
|
|
12
|
+
&:is(:last-child) {
|
|
13
|
+
margin-bottom: 3mm;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* inline mode: fill-in-the-blank inside <p> */
|
|
18
|
+
.inline {
|
|
19
|
+
display: inline-block;
|
|
20
|
+
vertical-align: baseline;
|
|
21
|
+
height: 0;
|
|
22
|
+
margin: 0 1mm;
|
|
23
|
+
border-bottom: 1px dotted var(--dotline-color, #808080);
|
|
24
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ComponentProps } from "preact";
|
|
2
|
+
import styles from "./DotLine.module.css";
|
|
3
|
+
import { joinClasses, mergeStyle } from "./utils";
|
|
4
|
+
|
|
5
|
+
interface DotLineProps extends ComponentProps<"span"> {
|
|
6
|
+
num?: number;
|
|
7
|
+
width?: number | string;
|
|
8
|
+
inline?: boolean;
|
|
9
|
+
color?: string;
|
|
10
|
+
lineHeight?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function DotLine({
|
|
14
|
+
num = 1,
|
|
15
|
+
children,
|
|
16
|
+
width = "100%",
|
|
17
|
+
style,
|
|
18
|
+
className = "",
|
|
19
|
+
inline,
|
|
20
|
+
color,
|
|
21
|
+
lineHeight,
|
|
22
|
+
...props
|
|
23
|
+
}: DotLineProps) {
|
|
24
|
+
if (num === 0) return;
|
|
25
|
+
const css = mergeStyle(style, { width, "--dotline-color": color, "--dotline-height": lineHeight });
|
|
26
|
+
|
|
27
|
+
if (inline)
|
|
28
|
+
return (
|
|
29
|
+
<span
|
|
30
|
+
className={joinClasses(className, styles.inline)}
|
|
31
|
+
style={css}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<span className={joinClasses(className, styles.block)} style={css} {...props}>
|
|
38
|
+
{Array.from({ length: num }, (_, k) => (
|
|
39
|
+
<span key={k} className={styles.line}>
|
|
40
|
+
{k === 0 ? children : null}
|
|
41
|
+
</span>
|
|
42
|
+
))}
|
|
43
|
+
</span>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { renderToString } from "katex";
|
|
2
|
+
import "katex/contrib/mhchem";
|
|
3
|
+
import "katex/dist/katex.min.css";
|
|
4
|
+
import { ComponentProps } from "preact";
|
|
5
|
+
import styles from "./Equation.module.css";
|
|
6
|
+
import { joinClasses } from "./utils";
|
|
7
|
+
|
|
8
|
+
interface EquationProps extends Omit<ComponentProps<"span">, "children"> {
|
|
9
|
+
tex: string;
|
|
10
|
+
displayMode?: boolean;
|
|
11
|
+
aligned?: boolean;
|
|
12
|
+
chemical?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export function Equation({
|
|
15
|
+
tex,
|
|
16
|
+
displayMode,
|
|
17
|
+
className = "",
|
|
18
|
+
aligned = false,
|
|
19
|
+
chemical = false,
|
|
20
|
+
...props
|
|
21
|
+
}: EquationProps) {
|
|
22
|
+
const alignedCode = aligned
|
|
23
|
+
? `\\begin{aligned}
|
|
24
|
+
${tex}
|
|
25
|
+
\\end{aligned}`
|
|
26
|
+
: tex;
|
|
27
|
+
const chemCode = chemical ? `\\ce{${alignedCode}}` : alignedCode;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<span
|
|
31
|
+
dangerouslySetInnerHTML={{
|
|
32
|
+
__html: renderToString(chemCode, { displayMode }),
|
|
33
|
+
}}
|
|
34
|
+
className={joinClasses(className, styles.equation)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
.ol {
|
|
2
|
+
& > .li {
|
|
3
|
+
counter-increment: list-items;
|
|
4
|
+
&::before {
|
|
5
|
+
content: var(--ol-marker-pre, "") counter(list-items, decimal)
|
|
6
|
+
var(--ol-marker-post, ". ");
|
|
7
|
+
margin-right: 1mm;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
&[data-counter="lower-alpha"] .li::before {
|
|
11
|
+
content: var(--ol-marker-pre, "") counter(list-items, lower-alpha)
|
|
12
|
+
var(--ol-marker-post, ". ");
|
|
13
|
+
}
|
|
14
|
+
&[data-counter="upper-alpha"] .li::before {
|
|
15
|
+
content: var(--ol-marker-pre, "") counter(list-items, upper-alpha)
|
|
16
|
+
var(--ol-marker-post, ". ");
|
|
17
|
+
}
|
|
18
|
+
&[data-counter="lower-roman"] .li::before {
|
|
19
|
+
content: var(--ol-marker-pre, "") counter(list-items, lower-roman)
|
|
20
|
+
var(--ol-marker-post, ". ");
|
|
21
|
+
}
|
|
22
|
+
&[data-counter="upper-roman"] .li::before {
|
|
23
|
+
content: var(--ol-marker-pre, "") counter(list-items, upper-roman)
|
|
24
|
+
var(--ol-marker-post, ". ");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.ul {
|
|
29
|
+
.li {
|
|
30
|
+
&::before {
|
|
31
|
+
content: var(--ul-marker, "•");
|
|
32
|
+
margin-right: 1mm;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* hanging indent so wrapped text aligns under content, not marker */
|
|
38
|
+
.li {
|
|
39
|
+
&:not(:last-child) {
|
|
40
|
+
margin-bottom: var(--list-gap, 0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* pre+body side-by-side on an inner wrapper — outer div stays unstyled */
|
|
45
|
+
.preWrapper {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: max-content 1fr;
|
|
48
|
+
align-items: start;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.pre {
|
|
52
|
+
padding-right: 1mm;
|
|
53
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { ComponentChildren, ComponentProps } from "preact";
|
|
2
|
+
import styles from "./List.module.css";
|
|
3
|
+
import { cssString, joinClasses, mergeStyle } from "./utils";
|
|
4
|
+
|
|
5
|
+
export type CounterType =
|
|
6
|
+
| "decimal"
|
|
7
|
+
| "lower-alpha"
|
|
8
|
+
| "upper-alpha"
|
|
9
|
+
| "lower-roman"
|
|
10
|
+
| "upper-roman";
|
|
11
|
+
|
|
12
|
+
interface ListItemProps extends ComponentProps<"div"> {
|
|
13
|
+
count?: number;
|
|
14
|
+
marker?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ListProps extends ComponentProps<"div"> {
|
|
18
|
+
pre?: ComponentChildren;
|
|
19
|
+
gap?: string | number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface OLProps extends ListProps {
|
|
23
|
+
start?: number;
|
|
24
|
+
counterType?: CounterType;
|
|
25
|
+
markerPre?: string;
|
|
26
|
+
markerPost?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ULProps extends ListProps {
|
|
30
|
+
marker?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function LI({
|
|
34
|
+
className = "",
|
|
35
|
+
count = NaN,
|
|
36
|
+
style,
|
|
37
|
+
marker,
|
|
38
|
+
...props
|
|
39
|
+
}: ListItemProps) {
|
|
40
|
+
const css = mergeStyle(style, {
|
|
41
|
+
counterReset: count ? `list-items ${count - 1}` : undefined,
|
|
42
|
+
"--ul-marker": cssString(marker),
|
|
43
|
+
});
|
|
44
|
+
return (
|
|
45
|
+
<div style={css} {...props} className={joinClasses(className, styles.li)} />
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function Body({
|
|
50
|
+
pre,
|
|
51
|
+
children,
|
|
52
|
+
}: {
|
|
53
|
+
pre?: ComponentChildren;
|
|
54
|
+
children: ComponentChildren;
|
|
55
|
+
}) {
|
|
56
|
+
if (!pre) return <>{children}</>;
|
|
57
|
+
return (
|
|
58
|
+
<div className={styles.preWrapper}>
|
|
59
|
+
<div className={styles.pre}>{pre}</div>
|
|
60
|
+
<div>{children}</div>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function OL({
|
|
66
|
+
className = "",
|
|
67
|
+
start = 1,
|
|
68
|
+
counterType = "decimal",
|
|
69
|
+
markerPre,
|
|
70
|
+
markerPost,
|
|
71
|
+
style,
|
|
72
|
+
pre,
|
|
73
|
+
gap,
|
|
74
|
+
children,
|
|
75
|
+
...props
|
|
76
|
+
}: OLProps) {
|
|
77
|
+
const css = mergeStyle(style, {
|
|
78
|
+
counterReset: `list-items ${start - 1}`,
|
|
79
|
+
"--ol-marker-pre": cssString(markerPre),
|
|
80
|
+
"--ol-marker-post": cssString(markerPost),
|
|
81
|
+
"--list-gap": gap,
|
|
82
|
+
});
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
{...props}
|
|
86
|
+
className={joinClasses(className, styles.ol)}
|
|
87
|
+
style={css}
|
|
88
|
+
data-counter={counterType}
|
|
89
|
+
>
|
|
90
|
+
<Body pre={pre}>{children}</Body>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function UL({
|
|
96
|
+
className = "",
|
|
97
|
+
marker,
|
|
98
|
+
style,
|
|
99
|
+
children,
|
|
100
|
+
pre,
|
|
101
|
+
gap,
|
|
102
|
+
...props
|
|
103
|
+
}: ULProps) {
|
|
104
|
+
const css = mergeStyle(style, {
|
|
105
|
+
"--ul-marker": cssString(marker),
|
|
106
|
+
"--list-gap": gap,
|
|
107
|
+
});
|
|
108
|
+
return (
|
|
109
|
+
<div {...props} className={joinClasses(className, styles.ul)} style={css}>
|
|
110
|
+
<Body pre={pre}>{children}</Body>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function List({
|
|
116
|
+
kind,
|
|
117
|
+
...props
|
|
118
|
+
}: ListProps & { kind: "ul" | "ol"; start?: number }) {
|
|
119
|
+
return kind === "ul" ? <UL {...props} /> : <OL {...props} />;
|
|
120
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ComponentProps } from "preact";
|
|
2
|
+
import styles from "./Page.module.css";
|
|
3
|
+
import { joinClasses, mergeStyle } from "./utils";
|
|
4
|
+
interface PageProps {
|
|
5
|
+
page?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function PageBreak({ page }: PageProps) {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
style={{
|
|
12
|
+
page,
|
|
13
|
+
}}
|
|
14
|
+
className={styles.pagebreak}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
export function Page({
|
|
19
|
+
page,
|
|
20
|
+
style,
|
|
21
|
+
className = "",
|
|
22
|
+
...props
|
|
23
|
+
}: PageProps & ComponentProps<"section">) {
|
|
24
|
+
const css = mergeStyle(style, { page });
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<section
|
|
28
|
+
style={css}
|
|
29
|
+
className={joinClasses(className, styles.page)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
.table {
|
|
2
|
+
--table-border-width: 1px;
|
|
3
|
+
--table-border-color: currentColor;
|
|
4
|
+
border-collapse: collapse;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.table th,
|
|
8
|
+
.table td {
|
|
9
|
+
text-align: center;
|
|
10
|
+
vertical-align: middle;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.table th {
|
|
14
|
+
background-color: var(--table-header-color, transparent);
|
|
15
|
+
font-size: var(--table-header-fontsize, inherit);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.table td {
|
|
19
|
+
background-color: var(--table-cell-color, transparent);
|
|
20
|
+
font-size: var(--table-cell-fontsize, inherit);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* ── Row orientation ──────────────────────────────────────────── */
|
|
24
|
+
.row td,
|
|
25
|
+
.row th {
|
|
26
|
+
border-right: var(--table-border-width, 1px) solid var(--table-border-color, currentColor);
|
|
27
|
+
border-bottom: var(--table-border-width, 1px) solid var(--table-border-color, currentColor);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.row tr td:last-child,
|
|
31
|
+
.row tr th:last-child {
|
|
32
|
+
border-right: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.row tr:last-child td,
|
|
36
|
+
.row tr:last-child th {
|
|
37
|
+
border-bottom: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* ── Col orientation ──────────────────────────────────────────── */
|
|
41
|
+
.col td,
|
|
42
|
+
.col th {
|
|
43
|
+
border-right: var(--table-border-width, 1px) solid var(--table-border-color, currentColor);
|
|
44
|
+
border-bottom: var(--table-border-width, 1px) solid var(--table-border-color, currentColor);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.col tr td:last-child,
|
|
48
|
+
.col tr th:last-child {
|
|
49
|
+
border-right: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.col tbody tr:last-child td,
|
|
53
|
+
.col tbody tr:last-child th {
|
|
54
|
+
border-bottom: none;
|
|
55
|
+
}
|