Skip to content

feat: #30 Allow for variable-width columns and more than two columns #32

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 1 commit into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"//file-type": "have to use this version before they switched to ESM, which gives a compile error related to require()",
"//node-fetch@2.6.6file-type": "have to use this version before they switched to ESM, which gives a compile error related to require()",
"//chalk@4": "also ESM related problem",
"//notion-client@4": "also ESM related problem",
"dependencies": {
"@notionhq/client": "^1.0.4",
"chalk": "^4.1.2",
Expand All @@ -56,15 +57,16 @@
"limiter": "^2.1.0",
"markdown-table": "^2.0.0",
"node-fetch": "2.6.6",
"notion-client": "^4",
"notion-to-md": "^2.5.5",
"path": "^0.12.7",
"postinstall-postinstall": "^2.1.0",
"sanitize-filename": "^1.6.3"
},
"devDependencies": {
"@types/markdown-table": "^2.0.0",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^28.1.6",
"@types/markdown-table": "^2.0.0",
"@types/node": "^12.20.11",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
Expand Down
29 changes: 19 additions & 10 deletions src/css/notion-styles.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/* some things copied from https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934 */
/* note, I haven't figure out how a Docusaurus app can actually include this, yet */
/* Note, I haven't figure out how a Docusaurus app can actually include this, yet.
So currently this has to be duplicated by the client.
*/

/* Copied from
https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L934
and
https://github1s.com/NotionX/react-notion-x/blob/master/packages/react-notion-x/src/styles.css#L1063
*/
.notion-column {
display: flex;
flex-direction: column;
Expand All @@ -21,17 +27,10 @@
}

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

@media (max-width: 640px) {
Expand All @@ -47,3 +46,13 @@
display: none;
}
}

.notion-spacer {
/* This matches the value in ColumnTransformer.ts */
width: calc(min(32px, 4vw));
}

.notion-spacer:last-child {
display: none;
}
/* End copied from NotionX */
43 changes: 40 additions & 3 deletions src/transformers/ColumnTransformer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Client } from "@notionhq/client";
import { NotionAPI } from "notion-client";
import { NotionToMarkdown } from "notion-to-md";
import { ListBlockChildrenResponseResult } from "notion-to-md/build/types";
import { getBlockChildren } from "./CustomTransformers";
Expand All @@ -21,9 +22,45 @@ export async function notionColumnToMarkdown(

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

const columnWidth = await getColumnWidth(block);

// note: it would look better in the markup with \n, but that
// causes notion-to-md to give us ":::A" instead of \n for some reason.
return `<div class='notion-column'>\n\n${childrenStrings.join(
"\n\n"
)}\n\n</div>`;
return (
`<div class='notion-column' style={{width: '${columnWidth}'}}>\n\n${childrenStrings.join(
"\n\n"
)}\n\n</div>` +
// Spacer between columns. CSS takes care of hiding this for the last column
// and when the screen is too narrow for multiple columns.
`<div className='notion-spacer' />`
);
}

// The official API doesn't give us access to the format information, including column_ratio.
// So we use 'notion-client' which uses the unofficial API.
// Once the official API gives us access to the format information, we can remove this
// and the 'notion-client' dependency.
// This logic was mostly taken from react-notion-x (sister project of notion-client).
async function getColumnWidth(
block: ListBlockChildrenResponseResult
): Promise<string> {
const notion = new NotionAPI();
const blockId = block.id;
// Yes, it is odd to call 'getPage' for a block, but that's how we access the format info.
const recordMap = await notion.getPage(blockId);
const blockResult = recordMap.block[blockId];

const columnFormat = blockResult?.value?.format as any;
const columnRatio = (columnFormat?.column_ratio as number) || 0.5;

const parentBlock = recordMap.block[blockResult?.value?.parent_id]?.value;
// I'm not sure why we wouldn't get a parent, but the react-notion-x has
// this fallback to a guess based on the columnRatio.
const columnCount =
parentBlock?.content?.length || Math.max(2, Math.ceil(1.0 / columnRatio));

const spacerWidth = `min(32px, 4vw)`; // This matches the value in css for 'notion-spacer'.
return `calc((100% - (${spacerWidth} * ${
columnCount - 1
})) * ${columnRatio})`;
}
Loading