Skip to content
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

Notion Importer #7

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Notion Importer #7

wants to merge 7 commits into from

Conversation

theianjones
Copy link

seinfeld

Comment on lines 6 to 8
const isPageLink = (s: string) => {
return !!s.match(/\.md$/)
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if theres {some string}.md then we know notion made a link

Comment on lines 10 to 13
const parseFileContents = (fileContent: string): Record<string, string>[] => {
// Looks like notion exporter inserts a Zero Width No-Break Space character at the start of the file.
return parse(fileContent.slice(1), {columns: true, skip_empty_lines: true, encoding: 'utf8', })
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using csv-parse to extract the contents. Im not married to this package if theres a better one out there.

Comment on lines 42 to 54
const createRootNode = (parsedContent: Record<string, string>): TanaIntermediateNode => {
const newNode = {
uid: idgenerator(),
name: parsedContent['Name'],
createdAt: new Date().getTime(),
editedAt: new Date().getTime(),
type: 'node',
todoState: undefined,
} as const

const children = createChildrenForRoot(parsedContent)
return {...newNode, children}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this creates a root node for each of the objects.

We statically use the Name column to determine the node.name of the root node.

Afaict, every notion table has a Name column. If not, this will need to be a param passed in from the CLI.

Comment on lines 15 to 40
const createChildrenForRoot = (parsedContent: Record<string, string>): TanaIntermediateNode[] | undefined => {
const keys = Object.keys(parsedContent)
const fields = keys.map(key => {
const newField = {
uid: idgenerator(),
name: key,
createdAt: new Date().getTime(),
editedAt: new Date().getTime(),
type: 'field',
todoState: undefined,
}

const fieldChildren = [{
uid: idgenerator(),
name: parsedContent[key],
createdAt: new Date().getTime(),
editedAt: new Date().getTime(),
type: 'node',
todoState: undefined,
}]

return {...newField, children: fieldChildren}
}) as TanaIntermediateNode[]

return fields
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the fields are created for each key found in the parsedContent. For this pokemon notion a parsedContent object would look like this:

https://gist.github.com/theianjones/82188ec7fba89ead74ed85470c2e5d16

Comment on lines 105 to 114
const createSummary = (nodes: TanaIntermediateNode[]) => {
return {
leafNodes: countLeafNodes(nodes),
calendarNodes: 0,
fields: countFields(nodes),
brokenRefs: countBrokenLinks(nodes),
topLevelNodes: nodes.length,
totalNodes: countTotalNodes(nodes)
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could definitely be more efficient (one reduce function) but I took the straight forward approach.

Comment on lines 134 to 159
const mergeAttributes = (a: AttributesMap, b: AttributesMap): AttributesMap => {
return Object.values(b).reduce((acc, curr) => {
const old = acc[curr.name]

if(!old){
return {
...acc,
[curr.name]: curr
}
}


const newPatch = {
count: old.count + curr.count,
values: [...new Set(old.values.concat(curr.values))],
}

return {
...acc,
[curr.name]: {
...old,
...newPatch
}
}
}, a)
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to deep merge attributes or only 1 will show up

Comment on lines 187 to 216
const fixPageLinks = (nodeMap: Record<TanaIntermediateAttribute['name'], TanaIntermediateNode>, nodes: TanaIntermediateNode[]): TanaIntermediateNode[] => {
return nodes.map((node) => {
const refs: string[] = []
const newName = node.name.split(',').map((potentialLink) => {
if(!isPageLink(potentialLink)){
return potentialLink
}

const linkName = getNameOutOfLink(potentialLink)

if(!linkName || !nodeMap[linkName]){
return potentialLink
}

const refFromLink = nodeMap[linkName].uid

refs.push(refFromLink)
return `[[${refFromLink}]]`
}).join(',')

const newChildren = node.children ? fixPageLinks(nodeMap, node.children) : undefined

return {
...node,
name: newName,
refs,
children: newChildren
}
})
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After nodes are created, we can go through an find an links that can be replaced with node references.

@houshuang
Copy link
Member

Could you explain how to use this? I'm assuming it's the Markdown+CSV export? When I unzipped, I got one md file, and a directory with the same name. Which one do I put in as the parameter? Putting the file, I get
image

@theianjones
Copy link
Author

Could you explain how to use this? I'm assuming it's the Markdown+CSV export? When I unzipped, I got one md file, and a directory with the same name. Which one do I put in as the parameter? Putting the file, I get image

Ill add some directions. Currently only works on exported tables which produce a CSV file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants