notion2hast 0.1.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.
@@ -0,0 +1,16 @@
1
+ import { HChild, HProperties } from 'hastscript/lib/core';
2
+ import { ColorProps } from './color.js';
3
+ import { RichTextItem, RichTexttoHastOpts } from './types.js';
4
+ export declare type RichTextTextItem = Extract<RichTextItem, {
5
+ type?: 'text';
6
+ }>;
7
+ export declare function colorText(richTextColor: string): [string, string];
8
+ export declare class RichTextToHast {
9
+ protected colorProps: ColorProps;
10
+ protected defaultClassName: boolean;
11
+ private propertiesMap;
12
+ constructor(opts?: RichTexttoHastOpts, colorProps?: ColorProps);
13
+ protected props(key: string): HProperties;
14
+ textToHast(text: RichTextTextItem): HChild;
15
+ build(richTextItems: RichTextItem[]): Promise<HChild[]>;
16
+ }
@@ -0,0 +1,87 @@
1
+ import { h } from 'hastscript';
2
+ import { ColorProps } from './color.js';
3
+ import { mergeProps } from './props.js';
4
+ export function colorText(richTextColor) {
5
+ const colors = richTextColor.split('_', 2);
6
+ if (colors.length > 1) {
7
+ return ['', colors[0]];
8
+ }
9
+ return [richTextColor, ''];
10
+ }
11
+ export class RichTextToHast {
12
+ constructor(opts = {}, colorProps) {
13
+ this.propertiesMap = {};
14
+ this.colorProps = colorProps || new ColorProps({});
15
+ this.defaultClassName = opts.defaultClassName || false;
16
+ Object.assign(this.propertiesMap, opts.richTexttoHastBuilderOpts?.richTexttoHastBuildePropertiesMap || {});
17
+ }
18
+ props(key) {
19
+ const ret = { ...(this.propertiesMap[key] || {}) };
20
+ if (this.defaultClassName) {
21
+ if (typeof ret.className === 'undefined') {
22
+ ret.className = key;
23
+ }
24
+ }
25
+ return ret;
26
+ }
27
+ textToHast(text) {
28
+ let tag = [];
29
+ const value = text.plain_text;
30
+ if (text.href) {
31
+ tag.push({
32
+ name: 'a',
33
+ properties: Object.assign(this.props('text-link'), { href: text.href })
34
+ });
35
+ }
36
+ if (text.annotations.code) {
37
+ tag.push({ name: 'code', properties: this.props('text-code') });
38
+ }
39
+ if (text.annotations.bold) {
40
+ tag.push({ name: 'strong', properties: this.props('text-bold') });
41
+ }
42
+ if (text.annotations.italic) {
43
+ tag.push({ name: 'em', properties: this.props('text-italic') });
44
+ }
45
+ if (text.annotations.strikethrough) {
46
+ tag.push({ name: 's', properties: this.props('text-strikethrough') });
47
+ }
48
+ if (text.annotations.underline) {
49
+ const props = this.props('text-underline');
50
+ const entries = Object.entries(props);
51
+ tag.push({
52
+ name: 'span',
53
+ properties: entries.length === 0 ||
54
+ (entries.length === 1 &&
55
+ entries[0][0] === 'className' &&
56
+ entries[0][1] === 'text-underline')
57
+ ? mergeProps(props, { style: 'text-decoration: underline;' })
58
+ : props
59
+ });
60
+ }
61
+ if (text.annotations.color && text.annotations.color !== 'default') {
62
+ if (tag.length == 0) {
63
+ tag.push({ name: 'span', properties: {} });
64
+ }
65
+ const len = tag.length;
66
+ tag[len - 1].properties = mergeProps(tag[len - 1].properties, this.colorProps.props(text.annotations.color));
67
+ }
68
+ const len = tag.length;
69
+ if (len === 0) {
70
+ return value;
71
+ }
72
+ let nest = h(tag[len - 1].name, tag[len - 1].properties, [value]);
73
+ for (let i = len - 2; i >= 0; i--) {
74
+ nest = h(tag[i].name, tag[i].properties, nest);
75
+ }
76
+ return nest;
77
+ }
78
+ async build(richTextItems) {
79
+ const ret = [];
80
+ for (const item of richTextItems) {
81
+ if (item.type === 'text') {
82
+ ret.push(this.textToHast(item));
83
+ }
84
+ }
85
+ return ret;
86
+ }
87
+ }
@@ -0,0 +1,42 @@
1
+ import { Client } from '@notionhq/client';
2
+ import { HProperties } from 'hastscript/lib/core';
3
+ import { BlockToHastBuilder } from './block';
4
+ export declare type ToHastOpts = {
5
+ block_id: string;
6
+ parent?: Block;
7
+ blocktoHastOpts?: BlockToHastOpts;
8
+ richTexttoHastOpts?: RichTexttoHastOpts;
9
+ colorPropsOpts?: ColorPropsOpts;
10
+ };
11
+ export declare type Block = Extract<Awaited<ReturnType<InstanceType<typeof Client>['blocks']['retrieve']>>, {
12
+ type: string;
13
+ }>;
14
+ export declare type BlockToHastBuilderPropertiesKey = `paragraph` | `heading-1` | `heading-2` | `heading-3` | `code` | `code-pre` | `code-code` | `code-caption` | `callout` | `callout-icon-emoji` | `callout-icon-image` | `callout-paragraph` | `divider` | `column-list` | `column` | `bulleted-list` | `bulleted-list-item` | `numbered-list` | `numbered-list-item` | `quote` | `todo` | `todo-checked` | `todo-not-checked` | `todo-text` | `toggle` | `toggle-summary` | `table` | `table-row` | `table-row-cell` | `table-row-header` | `table-row-header-top-left` | `table-row-header-top` | `table-row-header-left` | `bookmark` | `bookmark-link` | `bookmark-caption` | `image` | `image-img` | `image-caption` | `text-link` | `text-bold` | `text-code` | `text-italic` | `text-strikethrough` | `text-underline`;
15
+ export declare type BlockToHastBuilderPropertiesMap = {
16
+ [key in BlockToHastBuilderPropertiesKey]?: HProperties;
17
+ };
18
+ export declare type BlockToHastBuilderOpts = {
19
+ defaultClassname?: boolean;
20
+ propertiesMap?: BlockToHastBuilderPropertiesMap;
21
+ };
22
+ export declare type BlockToHastBuilders = Record<string, BlockToHastBuilder<Block['type']>>;
23
+ export declare type RichTextItem = Extract<Block, {
24
+ type: 'paragraph';
25
+ }>['paragraph']['rich_text'][0];
26
+ export declare type BlockToHastOpts = {
27
+ defaultClassName?: boolean;
28
+ blockToHastBuilderOpts?: BlockToHastBuilderOpts;
29
+ blockToHastBuilders?: BlockToHastBuilders;
30
+ };
31
+ export declare type ColorPropertiesMap = Record<string, HProperties>;
32
+ export declare type ColorPropsOpts = {
33
+ colorPropertiesMap?: ColorPropertiesMap;
34
+ };
35
+ export declare type RichTexttoHastBuildePropertiesMap = Record<string, HProperties>;
36
+ export declare type RichTexttoHastBuilderOpts = {
37
+ richTexttoHastBuildePropertiesMap?: RichTexttoHastBuildePropertiesMap;
38
+ };
39
+ export declare type RichTexttoHastOpts = {
40
+ defaultClassName?: boolean;
41
+ richTexttoHastBuilderOpts?: RichTexttoHastBuilderOpts;
42
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ import yargs from 'yargs';
3
+ import { hideBin } from 'yargs/helpers';
4
+ import { cli } from './cli.js';
5
+ const envVarsPrefix = process.env['NOTION2HAST_ENV_VARS_PREFIX'] || 'NOTION2HAST';
6
+ (async () => {
7
+ const argv = await yargs(hideBin(process.argv))
8
+ .scriptName('notion2hast')
9
+ .env(envVarsPrefix)
10
+ .usage('$0 [OPTIONS]...')
11
+ .demand(0)
12
+ .options({
13
+ 'api-key': {
14
+ type: 'string',
15
+ array: false,
16
+ required: true,
17
+ description: 'API Key to API endpoint'
18
+ },
19
+ 'block-id': {
20
+ type: 'string',
21
+ array: false,
22
+ required: true,
23
+ description: 'The id of root block in Notion'
24
+ },
25
+ 'default-class-name': {
26
+ type: 'boolean',
27
+ array: false,
28
+ required: false,
29
+ description: 'Set default name to class of each elements'
30
+ },
31
+ 'to-html': {
32
+ type: 'boolean',
33
+ array: false,
34
+ required: false,
35
+ description: 'Convert hast to html'
36
+ }
37
+ })
38
+ .help().argv;
39
+ process.exit(await cli({
40
+ apiKey: argv['api-key'],
41
+ blockId: argv['block-id'],
42
+ defaultClassName: argv['default-class-name'],
43
+ toHtml: argv['to-html'],
44
+ stdout: process.stdout,
45
+ stderr: process.stderr
46
+ }));
47
+ })();
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "notion2hast",
3
+ "version": "0.1.1",
4
+ "description": "Notion blocks to hast",
5
+ "license": "MIT",
6
+ "author": "hankei6km <hankei6km@gmail.com> (https://github.com/hankei6km)",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git@github.com:hankei6km/notion2hast.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/hankei6km/notion2hast/issues"
13
+ },
14
+ "keywords": [
15
+ "notion",
16
+ "hast"
17
+ ],
18
+ "main": "dist/index.js",
19
+ "exports": "./dist/index.js",
20
+ "type": "module",
21
+ "types": "dist/index.d.ts",
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "engines": {
26
+ "node": "^14.13.1 || >=16.0.0"
27
+ },
28
+ "bin": {
29
+ "notion2hast": "dist/main.js"
30
+ },
31
+ "scripts": {
32
+ "start": "npm run build && node dist/main.js",
33
+ "build": "npm run clean && tsc && rimraf dist/test && mv dist/src/* dist/ && rimraf dist/src",
34
+ "test": "node --experimental-vm-modules node_modules/.bin/jest",
35
+ "clean": "rimraf \"dist/*\"",
36
+ "upgrade-interactive": "npm-check --update",
37
+ "csb:test": "npm test -- --runInBand --watchAll"
38
+ },
39
+ "dependencies": {
40
+ "@notionhq/client": "^2.2.0",
41
+ "hash.js": "^1.1.7",
42
+ "hast-util-classnames": "^2.0.0",
43
+ "hast-util-to-html": "^8.0.3",
44
+ "hastscript": "^7.0.2",
45
+ "sha.js": "^2.4.11",
46
+ "yargs": "^17.5.1"
47
+ },
48
+ "devDependencies": {
49
+ "@types/jest": "^28.1.8",
50
+ "@types/node": "^16.11.1",
51
+ "@types/sha.js": "^2.4.0",
52
+ "@types/yargs": "^17.0.12",
53
+ "jest": "^28.1.3",
54
+ "rimraf": "^3.0.2",
55
+ "ts-jest": "^28.0.8",
56
+ "ts-node": "^10.9.1",
57
+ "typescript": "^4.8.3"
58
+ }
59
+ }