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,555 @@
1
+ import { h } from 'hastscript';
2
+ import { classnames } from 'hast-util-classnames';
3
+ import { mergeProps } from './props.js';
4
+ export function isBlock(o) {
5
+ if (o.object === 'block' && typeof o.type === 'string') {
6
+ return true;
7
+ }
8
+ return false;
9
+ }
10
+ export class BlockItem {
11
+ constructor(client, opts) {
12
+ this.client = client;
13
+ this.opts = opts;
14
+ this.blocks = [];
15
+ this.next_cursor = null;
16
+ this.blocksLen = 0;
17
+ this.idx = 0;
18
+ }
19
+ async init() {
20
+ let res = await this.client.listBlockChildren({
21
+ block_id: this.opts.block_id
22
+ });
23
+ this.blocks = res.results || [];
24
+ this.next_cursor = res.next_cursor;
25
+ this.blocksLen = this.blocks.length;
26
+ this.idx = 0;
27
+ }
28
+ async block() {
29
+ if (this.idx >= this.blocksLen) {
30
+ if (this.next_cursor) {
31
+ let res = await this.client.listBlockChildren({
32
+ block_id: this.opts.block_id,
33
+ start_cursor: this.next_cursor || undefined
34
+ });
35
+ this.blocks = res.results || [];
36
+ this.next_cursor = res.next_cursor;
37
+ this.blocksLen = this.blocks.length;
38
+ this.idx = 0;
39
+ }
40
+ else {
41
+ return null;
42
+ }
43
+ }
44
+ if (this.blocksLen === 0) {
45
+ return null;
46
+ }
47
+ const ret = this.blocks[this.idx];
48
+ this.idx++;
49
+ if (isBlock(ret)) {
50
+ return ret;
51
+ }
52
+ return null;
53
+ }
54
+ }
55
+ export class BlockToHastBuilder {
56
+ constructor(blockType, opts) {
57
+ this.propertiesMap = {};
58
+ this.blockType = blockType;
59
+ this.defaultClassname = opts.defaultClassname || false;
60
+ this.propertiesMap = { ...(opts.propertiesMap || {}) };
61
+ }
62
+ props(key) {
63
+ const ret = { ...(this.propertiesMap[key] || {}) };
64
+ if (this.defaultClassname) {
65
+ if (typeof ret.className === 'undefined') {
66
+ ret.className = key;
67
+ }
68
+ }
69
+ return ret;
70
+ }
71
+ }
72
+ export class BlockParagraphToHast extends BlockToHastBuilder {
73
+ constructor(opts = {}) {
74
+ super('paragraph', opts);
75
+ }
76
+ outerTag() {
77
+ return { name: null };
78
+ }
79
+ async build({ block, nest, richTextToHast, colorProps }) {
80
+ if (this.blockType === block.type) {
81
+ return [
82
+ h('p', mergeProps(this.props('paragraph'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
83
+ ];
84
+ }
85
+ return [];
86
+ }
87
+ isBreak(_prevType) {
88
+ return true;
89
+ }
90
+ }
91
+ export class BlockHeading1ToHast extends BlockToHastBuilder {
92
+ constructor(opts = {}) {
93
+ super('heading_1', opts);
94
+ }
95
+ outerTag() {
96
+ return { name: null };
97
+ }
98
+ async build({ block, nest, richTextToHast, colorProps }) {
99
+ if (this.blockType === block.type) {
100
+ return [
101
+ h('h1', mergeProps(this.props('heading-1'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
102
+ ];
103
+ }
104
+ return [];
105
+ }
106
+ isBreak(_prevType) {
107
+ return true;
108
+ }
109
+ }
110
+ export class BlockHeading2ToHast extends BlockToHastBuilder {
111
+ constructor(opts = {}) {
112
+ super('heading_2', opts);
113
+ }
114
+ outerTag() {
115
+ return { name: null };
116
+ }
117
+ async build({ block, nest, richTextToHast, colorProps }) {
118
+ if (this.blockType === block.type) {
119
+ return [
120
+ h('h2', mergeProps(this.props('heading-2'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
121
+ ];
122
+ }
123
+ return [];
124
+ }
125
+ isBreak(_prevType) {
126
+ return true;
127
+ }
128
+ }
129
+ export class BlockHeading3ToHast extends BlockToHastBuilder {
130
+ constructor(opts = {}) {
131
+ super('heading_3', opts);
132
+ }
133
+ outerTag() {
134
+ return { name: null };
135
+ }
136
+ async build({ block, nest, richTextToHast, colorProps }) {
137
+ if (this.blockType === block.type) {
138
+ return [
139
+ h('h3', mergeProps(this.props('heading-3'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
140
+ ];
141
+ }
142
+ return [];
143
+ }
144
+ isBreak(_prevType) {
145
+ return true;
146
+ }
147
+ }
148
+ export class BlockCodeToHast extends BlockToHastBuilder {
149
+ constructor(opts = {}) {
150
+ super('code', opts);
151
+ }
152
+ outerTag() {
153
+ return { name: null };
154
+ }
155
+ async build({ block, nest, richTextToHast }) {
156
+ if (this.blockType === block.type) {
157
+ const lang = block[block.type].language || '';
158
+ const codeCode = h('code', this.props('code-code'), ...(await richTextToHast.build(block[block.type].rich_text)));
159
+ classnames(codeCode, lang);
160
+ const caption = await richTextToHast.build(block[block.type].caption);
161
+ const codeCaptin = caption.length > 0
162
+ ? h('figcaption', this.props('code-caption'), ...caption)
163
+ : null;
164
+ return [
165
+ h('figure', this.props('code'), h('pre', this.props('code-pre'), codeCode), codeCaptin, ...nest)
166
+ ];
167
+ }
168
+ return [];
169
+ }
170
+ isBreak(_prevType) {
171
+ return true;
172
+ }
173
+ }
174
+ export class BlockCalloutToHast extends BlockToHastBuilder {
175
+ constructor(opts = {}) {
176
+ super('callout', opts);
177
+ }
178
+ outerTag() {
179
+ return { name: null };
180
+ }
181
+ async build({ block, nest, richTextToHast, colorProps }) {
182
+ if (this.blockType === block.type) {
183
+ const iconSrc = block[block.type].icon;
184
+ let icon = '';
185
+ if (iconSrc?.type === 'emoji') {
186
+ icon = h('div', this.props('callout-icon-emoji'), iconSrc.emoji);
187
+ }
188
+ else if (iconSrc?.type === 'external') {
189
+ icon = h('div', this.props('callout-icon-image'), h('img', { src: iconSrc.external.url }));
190
+ }
191
+ else if (iconSrc?.type === 'file') {
192
+ icon = h('div', this.props('callout-icon-image'), h('img', { src: iconSrc.file.url }));
193
+ }
194
+ return [
195
+ h('div', mergeProps(this.props('callout'), colorProps.props(block[block.type].color)), icon, h('div', this.props('callout-paragraph'), h('p', {}, ...(await richTextToHast.build(block[block.type].rich_text)))), ...nest)
196
+ ];
197
+ }
198
+ return [];
199
+ }
200
+ isBreak(_prevType) {
201
+ return true;
202
+ }
203
+ }
204
+ export class BlockDividerToHast extends BlockToHastBuilder {
205
+ constructor(opts = {}) {
206
+ super('divider', opts);
207
+ }
208
+ outerTag() {
209
+ return { name: null };
210
+ }
211
+ async build({ block, nest }) {
212
+ if (this.blockType === block.type) {
213
+ return [h('hr', this.props('divider'), ...nest)];
214
+ }
215
+ return [];
216
+ }
217
+ isBreak(_prevType) {
218
+ return true;
219
+ }
220
+ }
221
+ export class BlockColumnListToHast extends BlockToHastBuilder {
222
+ constructor(opts = {}) {
223
+ super('column_list', opts);
224
+ }
225
+ outerTag() {
226
+ return { name: null };
227
+ }
228
+ async build({ block, nest, richTextToHast }) {
229
+ if (this.blockType === block.type) {
230
+ return [h('div', this.props('column-list'), ...nest)];
231
+ }
232
+ return [];
233
+ }
234
+ isBreak(_prevType) {
235
+ return true;
236
+ }
237
+ }
238
+ export class BlockColumnToHast extends BlockToHastBuilder {
239
+ constructor(opts = {}) {
240
+ super('column', opts);
241
+ }
242
+ outerTag() {
243
+ return { name: null };
244
+ }
245
+ async build({ block, nest, richTextToHast }) {
246
+ if (this.blockType === block.type) {
247
+ return [h('div', this.props('column'), ...nest)];
248
+ }
249
+ return [];
250
+ }
251
+ isBreak(_prevType) {
252
+ return true;
253
+ }
254
+ }
255
+ export class BlockBulletedListItemToHast extends BlockToHastBuilder {
256
+ constructor(opts = {}) {
257
+ super('bulleted_list_item', opts);
258
+ }
259
+ outerTag() {
260
+ return { name: 'ul', properties: this.props('bulleted-list') };
261
+ }
262
+ async build({ block, nest, richTextToHast, colorProps }) {
263
+ if (this.blockType === block.type) {
264
+ return [
265
+ h('li', mergeProps(this.props('bulleted-list-item'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
266
+ ];
267
+ }
268
+ return [];
269
+ }
270
+ isBreak(prevType) {
271
+ if (this.blockType === prevType) {
272
+ return false;
273
+ }
274
+ return true;
275
+ }
276
+ }
277
+ export class BlockNumberedListItemToHast extends BlockToHastBuilder {
278
+ constructor(opts = {}) {
279
+ super('numbered_list_item', opts);
280
+ }
281
+ outerTag() {
282
+ return { name: 'ol', properties: this.props('numbered-list') };
283
+ }
284
+ async build({ block, nest, richTextToHast, colorProps }) {
285
+ if (this.blockType === block.type) {
286
+ return [
287
+ h('li', mergeProps(this.props('numbered-list-item'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
288
+ ];
289
+ }
290
+ return [];
291
+ }
292
+ isBreak(prevType) {
293
+ if (this.blockType === prevType) {
294
+ return false;
295
+ }
296
+ return true;
297
+ }
298
+ }
299
+ export class BlockQuoteToHast extends BlockToHastBuilder {
300
+ constructor(opts = {}) {
301
+ super('quote', opts);
302
+ }
303
+ outerTag() {
304
+ return { name: null };
305
+ }
306
+ async build({ block, nest, richTextToHast, colorProps }) {
307
+ if (this.blockType === block.type) {
308
+ return [
309
+ h('blockquote', mergeProps(this.props('quote'), colorProps.props(block[block.type].color)), ...(await richTextToHast.build(block[block.type].rich_text)), ...nest)
310
+ ];
311
+ }
312
+ return [];
313
+ }
314
+ isBreak(_prevType) {
315
+ return true;
316
+ }
317
+ }
318
+ export class BlockTodoToHast extends BlockToHastBuilder {
319
+ constructor(opts = {}) {
320
+ super('to_do', opts);
321
+ }
322
+ outerTag() {
323
+ return { name: null };
324
+ }
325
+ async build({ block, nest, richTextToHast, colorProps }) {
326
+ if (this.blockType === block.type) {
327
+ const todo = block[block.type];
328
+ return [
329
+ h('div', mergeProps(this.props('todo'), colorProps.props(todo.color)), h('div', this.props(todo.checked ? 'todo-checked' : 'todo-not-checked')), h('div', this.props('todo-text'), ...(await richTextToHast.build(todo.rich_text))), ...nest)
330
+ ];
331
+ }
332
+ return [];
333
+ }
334
+ isBreak(_prevType) {
335
+ return true;
336
+ }
337
+ }
338
+ export class BlockToggleToHast extends BlockToHastBuilder {
339
+ constructor(opts = {}) {
340
+ super('toggle', opts);
341
+ }
342
+ outerTag() {
343
+ return { name: null };
344
+ }
345
+ async build({ block, nest, richTextToHast, colorProps }) {
346
+ if (this.blockType === block.type) {
347
+ return [
348
+ h('details', mergeProps(this.props('toggle'), colorProps.props(block[block.type].color)), h('summary', this.props('toggle-summary'), ...(await richTextToHast.build(block[block.type].rich_text))), ...nest)
349
+ ];
350
+ }
351
+ return [];
352
+ }
353
+ isBreak(_prevType) {
354
+ return true;
355
+ }
356
+ }
357
+ export class BlockTableToHast extends BlockToHastBuilder {
358
+ constructor(opts = {}) {
359
+ super('table', opts);
360
+ }
361
+ outerTag() {
362
+ return { name: null };
363
+ }
364
+ async build({ block, nest, richTextToHast }) {
365
+ if (this.blockType === block.type) {
366
+ return [h('table', this.props('table'), ...nest)];
367
+ }
368
+ return [];
369
+ }
370
+ isBreak(_prevType) {
371
+ return true;
372
+ }
373
+ }
374
+ export class BlockTableRowToHast extends BlockToHastBuilder {
375
+ constructor(opts = {}) {
376
+ super('table_row', opts);
377
+ }
378
+ outerTag() {
379
+ return { name: null };
380
+ }
381
+ async build({ block, nest, parent, index, richTextToHast }) {
382
+ if (this.blockType === block.type) {
383
+ let has_column_header = false;
384
+ let has_row_header = false;
385
+ if (parent && parent.type === 'table') {
386
+ has_column_header = parent.table.has_column_header;
387
+ has_row_header = parent.table.has_row_header;
388
+ }
389
+ const cells = [];
390
+ let colIdx = 0;
391
+ for (const cell of block[block.type].cells) {
392
+ let tagName = 'td';
393
+ let properties = this.props('table-row-cell');
394
+ if ((has_column_header && index === 0) ||
395
+ (has_row_header && colIdx === 0)) {
396
+ // index がテーブル行と一致している前提
397
+ tagName = 'th';
398
+ }
399
+ if (tagName === 'th') {
400
+ properties = this.props('table-row-header');
401
+ if (index === 0 && colIdx === 0) {
402
+ properties = Object.assign({}, properties, this.props('table-row-header-top-left'));
403
+ }
404
+ else if (index === 0) {
405
+ properties = Object.assign({}, properties, this.props('table-row-header-top'));
406
+ }
407
+ else if (colIdx === 0) {
408
+ properties = Object.assign({}, properties, this.props('table-row-header-left'));
409
+ }
410
+ }
411
+ cells.push(h(tagName, properties, ...(await richTextToHast.build(cell))));
412
+ colIdx++;
413
+ }
414
+ return [h('tr', this.props('table-row'), ...cells, ...nest)];
415
+ }
416
+ return [];
417
+ }
418
+ isBreak(_prevType) {
419
+ return true;
420
+ }
421
+ }
422
+ export class BlockBookmarkToHast extends BlockToHastBuilder {
423
+ constructor(opts = {}) {
424
+ super('bookmark', opts);
425
+ }
426
+ outerTag() {
427
+ return { name: null };
428
+ }
429
+ async build({ block, nest, richTextToHast }) {
430
+ if (this.blockType === block.type) {
431
+ const caption = await richTextToHast.build(block[block.type].caption);
432
+ const bookmarkCaption = caption.length > 0
433
+ ? h('figcaption', this.props('bookmark-caption'), ...caption)
434
+ : null;
435
+ return [
436
+ h('figure', this.props('bookmark'), h('a', Object.assign({}, this.props('bookmark-link'), {
437
+ href: block[block.type].url
438
+ }), block[block.type].url), bookmarkCaption, ...nest)
439
+ ];
440
+ }
441
+ return [];
442
+ }
443
+ isBreak(_prevType) {
444
+ return true;
445
+ }
446
+ }
447
+ export class BlockImageToHast extends BlockToHastBuilder {
448
+ constructor(opts = {}) {
449
+ super('image', opts);
450
+ }
451
+ outerTag() {
452
+ return { name: null };
453
+ }
454
+ async build({ block, nest, richTextToHast }) {
455
+ if (this.blockType === block.type) {
456
+ const image = block[block.type];
457
+ let src = image.type === 'external' ? image.external.url : image.file.url;
458
+ const children = [
459
+ h('img', Object.assign({}, this.props('image-img'), { src }))
460
+ ];
461
+ const caption = await richTextToHast.build(image.caption);
462
+ if (caption.length > 0) {
463
+ children.push(h('figcaption', this.props('image-caption'), ...caption));
464
+ }
465
+ return [h('figure', this.props('image'), ...children, ...nest)];
466
+ }
467
+ return [];
468
+ }
469
+ isBreak(_prevType) {
470
+ return true;
471
+ }
472
+ }
473
+ export class SurroundElement {
474
+ constructor(initType, opts = {}) {
475
+ this.prevType = '';
476
+ this.children = [];
477
+ this.blockToHastBuilders = {};
478
+ this.prevType = initType;
479
+ const buildersOpts = opts.blockToHastBuilderOpts || {};
480
+ if (typeof buildersOpts.defaultClassname === 'undefined') {
481
+ buildersOpts.defaultClassname = opts.defaultClassName;
482
+ }
483
+ this.blockToHastBuilders = Object.assign({}, this.defaultBlockToHastBuilders(buildersOpts), opts.blockToHastBuilders || {});
484
+ }
485
+ defaultBlockToHastBuilders(opts) {
486
+ return {
487
+ paragraph: new BlockParagraphToHast(opts),
488
+ heading_1: new BlockHeading1ToHast(opts),
489
+ heading_2: new BlockHeading2ToHast(opts),
490
+ heading_3: new BlockHeading3ToHast(opts),
491
+ code: new BlockCodeToHast(opts),
492
+ callout: new BlockCalloutToHast(opts),
493
+ divider: new BlockDividerToHast(opts),
494
+ column_list: new BlockColumnListToHast(opts),
495
+ column: new BlockColumnToHast(opts),
496
+ bulleted_list_item: new BlockBulletedListItemToHast(opts),
497
+ numbered_list_item: new BlockNumberedListItemToHast(opts),
498
+ quote: new BlockQuoteToHast(opts),
499
+ to_do: new BlockTodoToHast(opts),
500
+ toggle: new BlockToggleToHast(opts),
501
+ table: new BlockTableToHast(opts),
502
+ table_row: new BlockTableRowToHast(opts),
503
+ bookmark: new BlockBookmarkToHast(opts),
504
+ image: new BlockImageToHast(opts)
505
+ };
506
+ }
507
+ builder(blockType) {
508
+ if (blockType) {
509
+ return this.blockToHastBuilders[blockType];
510
+ }
511
+ return undefined;
512
+ }
513
+ async append({ block, nest, parent, index, richTextToHast, colorProps }) {
514
+ const builder = this.builder(block.type);
515
+ if (builder) {
516
+ this.children.push(...(await builder.build({
517
+ block,
518
+ nest,
519
+ parent,
520
+ index,
521
+ richTextToHast,
522
+ colorProps
523
+ })));
524
+ }
525
+ this.prevType = block.type;
526
+ return;
527
+ }
528
+ nest(contet) {
529
+ this.children.push(contet);
530
+ }
531
+ outerTag() {
532
+ const builder = this.builder(this.prevType);
533
+ if (builder) {
534
+ return builder.outerTag();
535
+ }
536
+ return null;
537
+ }
538
+ content() {
539
+ return this.children;
540
+ }
541
+ isBreak(cur) {
542
+ if (this.prevType === '') {
543
+ return false;
544
+ }
545
+ const builder = this.builder(this.prevType);
546
+ if (builder) {
547
+ return builder.isBreak(cur);
548
+ }
549
+ return true;
550
+ }
551
+ reset() {
552
+ this.prevType = '';
553
+ this.children = [];
554
+ }
555
+ }
@@ -0,0 +1,4 @@
1
+ import { Client as NotionClient } from '@notionhq/client';
2
+ export declare abstract class Client {
3
+ abstract listBlockChildren(...args: Parameters<NotionClient['blocks']['children']['list']>): Promise<ReturnType<NotionClient['blocks']['children']['list']>>;
4
+ }
@@ -0,0 +1,2 @@
1
+ export class Client {
2
+ }
@@ -0,0 +1,8 @@
1
+ import { HProperties } from 'hastscript/lib/core';
2
+ import { ColorPropsOpts } from './types';
3
+ export declare class ColorProps {
4
+ private defaultColorPropertiesMap;
5
+ private colorPropertiesMap;
6
+ constructor(opts: ColorPropsOpts);
7
+ props(color: string): HProperties;
8
+ }
@@ -0,0 +1,33 @@
1
+ // https://optemization.com/notion-color-guide
2
+ const colorPropertiesMap = {
3
+ gray: { style: 'color:#9B9A97' },
4
+ brown: { style: 'color:#64473A' },
5
+ orange: { style: 'color:#D9730D' },
6
+ yellow: { style: 'color:#DFAB01' },
7
+ green: { style: 'color:#0F7B6C' },
8
+ blue: { style: 'color:#0B6E99' },
9
+ purple: { style: 'color:#6940A5' },
10
+ pink: { style: 'color:#AD1A72' },
11
+ red: { style: 'color:#E03E3E' },
12
+ gray_background: { style: 'background-color:#EBECED' },
13
+ brown_background: { style: 'background-color:#E9E5E3' },
14
+ orange_background: { style: 'background-color:#FAEBDD' },
15
+ yellow_background: { style: 'background-color:#FBF3DB' },
16
+ green_background: { style: 'background-color:#DDEDEA' },
17
+ blue_background: { style: 'background-color:#DDEBF1' },
18
+ purple_background: { style: 'background-color:#EAE4F2' },
19
+ pink_background: { style: 'background-color:#F4DFEB' },
20
+ red_background: { style: 'background-color:#FBE4E4' }
21
+ };
22
+ export class ColorProps {
23
+ constructor(opts) {
24
+ this.colorPropertiesMap = {};
25
+ Object.assign(this.colorPropertiesMap, this.defaultColorPropertiesMap(), opts.colorPropertiesMap || {});
26
+ }
27
+ defaultColorPropertiesMap() {
28
+ return colorPropertiesMap;
29
+ }
30
+ props(color) {
31
+ return { ...(this.colorPropertiesMap[color] || {}) };
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ import { Node } from 'hastscript/lib/core';
2
+ import { ToHastOpts } from './types.js';
3
+ import { Client } from './client.js';
4
+ export declare function blockToHast(client: Client, opts: ToHastOpts, depth?: number): Promise<Node>;
@@ -0,0 +1,49 @@
1
+ import { h } from 'hastscript';
2
+ import { BlockItem, SurroundElement } from './block.js';
3
+ import { RichTextToHast } from './richtext.js';
4
+ import { ColorProps } from './color.js';
5
+ export async function blockToHast(client, opts, depth = 0) {
6
+ const colorProps = new ColorProps({
7
+ ...opts.colorPropsOpts
8
+ });
9
+ const richTextToHast = new RichTextToHast(opts.richTexttoHastOpts || {}, colorProps);
10
+ const children = [];
11
+ //const ite = blockItem(client, opts)
12
+ const ite = new BlockItem(client, opts);
13
+ await ite.init();
14
+ let index = 0;
15
+ let i = await ite.block();
16
+ const surround = new SurroundElement('', opts.blocktoHastOpts || {});
17
+ while (i !== null) {
18
+ while (i !== null && !surround.isBreak(i.type)) {
19
+ const nest = [];
20
+ if (i.has_children) {
21
+ const a = await blockToHast(client, Object.assign({}, opts, { block_id: i.id, parent: i }), depth + 1);
22
+ // surround.nest(a)
23
+ nest.push(a);
24
+ }
25
+ await surround.append({
26
+ block: i,
27
+ nest,
28
+ parent: opts.parent,
29
+ index,
30
+ richTextToHast,
31
+ colorProps
32
+ });
33
+ index++;
34
+ i = await ite.block();
35
+ }
36
+ const tag = surround.outerTag();
37
+ if (tag && tag.name) {
38
+ children.push(h(tag.name, tag.properties || {}, ...surround.content()));
39
+ }
40
+ else {
41
+ children.push(h(null, ...surround.content()));
42
+ }
43
+ surround.reset();
44
+ }
45
+ if (depth === 0) {
46
+ return h(null, ...children);
47
+ }
48
+ return children;
49
+ }
@@ -0,0 +1,2 @@
1
+ import { HProperties } from 'hastscript/lib/core';
2
+ export declare function mergeProps(p: HProperties, { className, style, ...others }: HProperties): HProperties;
@@ -0,0 +1,30 @@
1
+ import { classnames } from 'hast-util-classnames';
2
+ export function mergeProps(p, { className, style, ...others }) {
3
+ const ret = { ...p };
4
+ // className(class) をマージ.
5
+ Object.assign(ret, others);
6
+ if (typeof className === 'string' || Array.isArray(className)) {
7
+ if (typeof p.className === 'string' || Array.isArray(p.className)) {
8
+ const c = classnames(p.className, className);
9
+ if (Array.isArray(c)) {
10
+ ret.className = c;
11
+ }
12
+ }
13
+ else {
14
+ ret.className = className;
15
+ }
16
+ }
17
+ // style をマージ、単純な文字列の連結.
18
+ // ダメそうだったら以下を検討.
19
+ // https://www.npmjs.com/package/style-to-object
20
+ // https://www.npmjs.com/package/to-style
21
+ if (typeof style === 'string') {
22
+ let ps = `${p.style || ''}`.trimEnd();
23
+ let dlm = '';
24
+ if (ps && !ps.endsWith(';')) {
25
+ dlm = ';';
26
+ }
27
+ ret.style = `${ps}${dlm}${style}`;
28
+ }
29
+ return ret;
30
+ }