2 | {{ msg }}
3 |
4 |
5 | Recommended IDE setup:
6 | VSCode
7 | +
8 |
12 | Vetur
13 |
14 | or
15 | Volar
16 | (if using
17 | <script setup>
)
18 |
19 |
20 | See README.md
for more information.
21 |
22 |
23 |
24 | Vite Docs
25 |
26 | |
27 | Vue 3 Docs
28 |
29 |
30 |
31 |
32 | Edit
33 | components/HelloWorld.vue
to test hot module replacement.
34 |
35 |
36 |
37 |
53 |
54 |
71 |
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const THEMES = ['auto', 'light', 'dark'] as const
2 |
3 | export const supportNotionTypes = [
4 | // 'Unkown',
5 | 'Space',
6 | 'Page',
7 | 'CollectionViewPage',
8 | // TODO: support
9 | // 'CollectionView',
10 | // 'ToDo',
11 | // 'Bookmark',
12 | // 'Header',
13 | // 'SubHeader',
14 | // 'SubSubHeader',
15 | // 'Bookmark',
16 | // 'File',
17 | ]
18 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | function mountContainer() {
5 | window.addEventListener('load', () => {
6 | setTimeout(function polling() {
7 | const sidebar = document.querySelector('.notion-sidebar') as HTMLDivElement | null
8 | if (sidebar) {
9 | const controllerDiv = document.createElement('div')
10 | createApp(App).mount(controllerDiv)
11 | sidebar.insertBefore(controllerDiv, sidebar.firstElementChild)
12 | } else {
13 | setTimeout(polling, 150)
14 | }
15 | }, 150)
16 | })
17 | }
18 |
19 | mountContainer()
20 |
--------------------------------------------------------------------------------
/src/models/index.ts:
--------------------------------------------------------------------------------
1 | import { getBlockType } from '@/utils'
2 |
3 | // const ignoreGNodeTypes = [
4 | // 'TableOfContents',
5 | // 'Text',
6 | // 'Quote',
7 | // 'Embed',
8 | // 'Image',
9 | // 'Code',
10 | // 'Divider',
11 | // 'Callout',
12 | // 'Calendar',
13 | // // special
14 | // // 'Unkown',
15 | // // TODO: support
16 | // 'NumberedList',
17 | // 'BulletedList',
18 | // 'Table',
19 | // 'ColumnList',
20 | // 'Column',
21 | // 'Board',
22 | // 'List',
23 | // ] as const
24 | // export type IgnoreGNodeType = typeof ignoreGNodeTypes[number]
25 | // export const ignoreGNodeTypeSet = new Set(ignoreGNodeTypes)
26 |
27 |
28 | export const gNodeTypes = [
29 | 'Unkown',
30 | 'Space',
31 | 'Page',
32 | ] as const
33 | export type GNodeType = typeof gNodeTypes[number]
34 | export const GNodeTypeSet = new Set(gNodeTypes)
35 |
36 | export class GNode {
37 | static nodes: { [id: string]: GNode } = {}
38 | static types = gNodeTypes
39 | get type(): GNodeType {
40 | switch (this.opts.type) {
41 | case 'Space':
42 | return 'Space'
43 | case 'CollectionViewPage':
44 | case 'Page':
45 | return 'Page'
46 | default:
47 | return 'Unkown'
48 | }
49 | }
50 | get size() {
51 | switch (this.type) {
52 | case 'Space':
53 | return 80
54 | case 'Page':
55 | return 30
56 | case 'Unkown':
57 | default:
58 | return 10
59 | }
60 | }
61 |
62 | get name() {
63 | switch (this.opts.type) {
64 | case 'Space':
65 | return this.source.name
66 | case 'Bookmark': {
67 | return (
68 | this.source.properties.title ?? this.source.properties.link
69 | ).join(' ')
70 | };
71 | case 'File': {
72 | return this.source.properties?.title.join(' ') ?? 'Unkown File'
73 | }
74 | case 'Header':
75 | case 'SubHeader':
76 | case 'SubSubHeader':
77 | case 'ToDo':
78 | case 'Page':
79 | return this.source.properties?.title.join(' ') ?? 'Unkown Title'
80 | case 'CollectionViewPage': {
81 | const c = GNode.nodes[this.source.collection_id]
82 | return c?.source.name?.join(' ') ?? 'Unkown CollectionView'
83 | }
84 | case 'Unkown': return 'Unkown'
85 | default: {
86 | let check = this.opts.type
87 | return this.opts.type ?? 'Unkown Block'
88 | }
89 | }
90 | }
91 |
92 | constructor(
93 | public opts: {
94 | type: string
95 | id: string
96 | },
97 | public source: any
98 | ) {}
99 |
100 | static from(value: any) {
101 | const type = getBlockType(value)
102 | const n = new GNode(
103 | {
104 | type,
105 | id: value.id,
106 | },
107 | value
108 | )
109 | GNode.nodes[n.opts.id] = n
110 | return n
111 | }
112 | }
113 |
114 | export class GEdge {
115 | constructor(
116 | public opts: {
117 | from: string
118 | to: string
119 | }
120 | ) {}
121 |
122 | static of(from: string, to: string) {
123 | const e = new GEdge({ from, to })
124 | return e
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/pages/Controller/index.vue:
--------------------------------------------------------------------------------
1 |