Skip to content

Commit 4fc81c7

Browse files
authored
Merge pull request #32 from sillsdev/VariableColumnWidth
feat: #30 Allow for variable-width columns and more than two columns
2 parents d04c867 + 0ba29b6 commit 4fc81c7

File tree

4 files changed

+265
-17
lines changed

4 files changed

+265
-17
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"//file-type": "have to use this version before they switched to ESM, which gives a compile error related to require()",
4848
"//node-fetch@2.6.6file-type": "have to use this version before they switched to ESM, which gives a compile error related to require()",
4949
"//chalk@4": "also ESM related problem",
50+
"//notion-client@4": "also ESM related problem",
5051
"dependencies": {
5152
"@notionhq/client": "^1.0.4",
5253
"chalk": "^4.1.2",
@@ -56,15 +57,16 @@
5657
"limiter": "^2.1.0",
5758
"markdown-table": "^2.0.0",
5859
"node-fetch": "2.6.6",
60+
"notion-client": "^4",
5961
"notion-to-md": "^2.5.5",
6062
"path": "^0.12.7",
6163
"postinstall-postinstall": "^2.1.0",
6264
"sanitize-filename": "^1.6.3"
6365
},
6466
"devDependencies": {
65-
"@types/markdown-table": "^2.0.0",
6667
"@types/fs-extra": "^9.0.13",
6768
"@types/jest": "^28.1.6",
69+
"@types/markdown-table": "^2.0.0",
6870
"@types/node": "^12.20.11",
6971
"@typescript-eslint/eslint-plugin": "^4.22.0",
7072
"@typescript-eslint/parser": "^4.22.0",

src/css/notion-styles.css

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
/* some things copied from https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934 */
2-
/* note, I haven't figure out how a Docusaurus app can actually include this, yet */
1+
/* Note, I haven't figure out how a Docusaurus app can actually include this, yet.
2+
So currently this has to be duplicated by the client.
3+
*/
34

5+
/* Copied from
6+
https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934
7+
and
8+
https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L1063
9+
*/
410
.notion-column {
511
display: flex;
612
flex-direction: column;
@@ -21,17 +27,10 @@
2127
}
2228

2329
.notion-row {
24-
display: grid;
25-
grid-auto-flow: column;
26-
/* at the moment, docu-notion doesn't give us column widths or ratios. So we
27-
could let css layout decide the widths. Instead at the moment we're saying
28-
let's just have each column be equal. This is easier for the author using
29-
Notion to remember than having to guess at what the layout will be. */
30-
grid-auto-columns: 1fr;
30+
display: flex;
3131
overflow: hidden;
3232
width: 100%;
3333
max-width: 100%;
34-
gap: 30px;
3534
}
3635

3736
@media (max-width: 640px) {
@@ -47,3 +46,13 @@
4746
display: none;
4847
}
4948
}
49+
50+
.notion-spacer {
51+
/* This matches the value in ColumnTransformer.ts */
52+
width: calc(min(32px, 4vw));
53+
}
54+
55+
.notion-spacer:last-child {
56+
display: none;
57+
}
58+
/* End copied from NotionX */

src/transformers/ColumnTransformer.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Client } from "@notionhq/client";
2+
import { NotionAPI } from "notion-client";
23
import { NotionToMarkdown } from "notion-to-md";
34
import { ListBlockChildrenResponseResult } from "notion-to-md/build/types";
45
import { getBlockChildren } from "./CustomTransformers";
@@ -21,9 +22,45 @@ export async function notionColumnToMarkdown(
2122

2223
const childrenStrings: string[] = await Promise.all(childrenPromise);
2324

25+
const columnWidth = await getColumnWidth(block);
26+
2427
// note: it would look better in the markup with \n, but that
2528
// causes notion-to-md to give us ":::A" instead of \n for some reason.
26-
return `<div class='notion-column'>\n\n${childrenStrings.join(
27-
"\n\n"
28-
)}\n\n</div>`;
29+
return (
30+
`<div class='notion-column' style={{width: '${columnWidth}'}}>\n\n${childrenStrings.join(
31+
"\n\n"
32+
)}\n\n</div>` +
33+
// Spacer between columns. CSS takes care of hiding this for the last column
34+
// and when the screen is too narrow for multiple columns.
35+
`<div className='notion-spacer' />`
36+
);
37+
}
38+
39+
// The official API doesn't give us access to the format information, including column_ratio.
40+
// So we use 'notion-client' which uses the unofficial API.
41+
// Once the official API gives us access to the format information, we can remove this
42+
// and the 'notion-client' dependency.
43+
// This logic was mostly taken from react-notion-x (sister project of notion-client).
44+
async function getColumnWidth(
45+
block: ListBlockChildrenResponseResult
46+
): Promise<string> {
47+
const notion = new NotionAPI();
48+
const blockId = block.id;
49+
// Yes, it is odd to call 'getPage' for a block, but that's how we access the format info.
50+
const recordMap = await notion.getPage(blockId);
51+
const blockResult = recordMap.block[blockId];
52+
53+
const columnFormat = blockResult?.value?.format as any;
54+
const columnRatio = (columnFormat?.column_ratio as number) || 0.5;
55+
56+
const parentBlock = recordMap.block[blockResult?.value?.parent_id]?.value;
57+
// I'm not sure why we wouldn't get a parent, but the react-notion-x has
58+
// this fallback to a guess based on the columnRatio.
59+
const columnCount =
60+
parentBlock?.content?.length || Math.max(2, Math.ceil(1.0 / columnRatio));
61+
62+
const spacerWidth = `min(32px, 4vw)`; // This matches the value in css for 'notion-spacer'.
63+
return `calc((100% - (${spacerWidth} * ${
64+
columnCount - 1
65+
})) * ${columnRatio})`;
2966
}

0 commit comments

Comments
 (0)