\n
\n Hey ...\n
\n
\n Sunday Brain Food: a weekly newsletter full of timeless ideas and insights\n for life and business.\n
\n
\n (Was this newsletter forwarded to you?\n Sign up here.)
\n
\n
\n FS\n
\n
\n \"For the first three months, I place each student at a table with a thousand\n pieces of white paper and a trash can underneath. Every day they have to sit\n at the table for several hours and write ideas. They put the ideas they like\n on the right side of the table; the ones they don\u2019t like, they put in the\n trash. But we don\u2019t throw out the trash. After three months, I only take the\n ideas from the trash can. I don\u2019t even look at the ideas they liked. Because\n the trash can is a treasure trove of things they\u2019re afraid to do.\"
\n
\n
\n \u2014\n Life Lessons from Marina Abramovi\u0107\n
\n
\n
\n Explore Your Curiosity\n
\n
\n \u2605 \"You'd imagine you were seeing a specific red, not projected on the\n screen but as a neurophysiological response to stimulus. And if you pick\n the precise wavelength, \u201Cyou could actually cause someone to perceive a\n color that they could never otherwise see. Like, there's no natural way\n for you to have the perception of that color.\u201D That color wouldn't be\n onscreen. It wouldn't be anything a projector could cast or a computer\n could generate. It'd be a function of pure cognition, different for every\n viewer, existing only in the mind, then fading to nothingness. Which is\n true for all colors anyway, when you think about it.\"
\n
\n
\n \u2014\n How Pixar Uses Hyper-Colors\n
\n
\n \u2605 \u201CScientists who study the mechanics of curiosity are finding that it is,\n at its core, a kind of probability algorithm\u2014our brain\u2019s continuous\n calculation of which path or action is likely to gain us the most\n knowledge in the least amount of time. Like the links on a Wikipedia page,\n curiosity builds upon itself, every question leading to the next. And as\n with a journey down the Wikipedia wormhole, where you start dictates where\n you might end up. That\u2019s the funny thing about curiosity: It\u2019s less about\n what you don\u2019t know than about what you already do.\u201D
\n
\n
\n \u2014\n Curiosity Depends on What you Already Know\n
\n
\n (In many ways reading is similar. Your reading ability depends on what\n you already know. The key to reading faster or remembering more is often\n as simple as reading more. Learn more about\n reading better.)\n
\n
\n
\n Timeless Insight\n
\n
\n \u201CIt is not the amount of knowledge that makes a brain. It is not even the\n distribution of knowledge. It is the interconnectedness.\"\n
\n
\n \u2014 Howard Bloom\n
\n
\n
\n Tiny Thought\n
\n
\n Three stages of thinking:\n
\n
\n 1. Too simplistic (it's easy).\n
\n
\n 2. Too complicated (it's hard).\n
\n
\n 3. Simple (it's simple but not easy).\n
\n
\n We tend to avoid the hard work necessary to make it simple.\n
\n
\n
\n
\n \n \n \n Sponsored by Trends\n | \n
\n \n
\n
\n
\n
\n
\n Trends\n is where entrepreneurs and investors find the next big thing. Every week,\n their team of analysts send a detailed report on markets that are about to\n explode, and exactly how you can capitalize. Uncover 1,000+ emerging market\n trends by visiting\n trends.co/farnamstreet\n to try your first 7 days for free.
\n
\n
\n
\n Stay safe,\n
\n
\n Shane\n
\n
\n P.S. The\n Great Mental Models V1 hardcover\n is on sale at Amazon.com for the lowest price ever. (Please note we don't\n control pricing and have no idea how long it will last.)\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n

\n
";
2 | export default htmlExample;
3 |
--------------------------------------------------------------------------------
/dist/tests/prodExample1/rawHtml.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | const htmlExample = `
35 |
36 |
48 |
56 | Hey ...
57 |
58 |
66 | Sunday Brain Food: a weekly newsletter full of timeless ideas and insights
67 | for life and business.
68 |
69 |
77 | (Was this newsletter forwarded to you?
85 | Sign up here.)
105 |
106 |
117 | FS
118 |
119 |
127 | "For the first three months, I place each student at a table with a thousand
128 | pieces of white paper and a trash can underneath. Every day they have to sit
129 | at the table for several hours and write ideas. They put the ideas they like
130 | on the right side of the table; the ones they don’t like, they put in the
131 | trash. But we don’t throw out the trash. After three months, I only take the
132 | ideas from the trash can. I don’t even look at the ideas they liked. Because
133 | the trash can is a treasure trove of things they’re afraid to do."
141 |
142 |
150 | —
151 | Life Lessons from Marina Abramović
164 |
165 |
184 |
195 | Explore Your Curiosity
196 |
197 |
205 | ★ "You'd imagine you were seeing a specific red, not projected on the
206 | screen but as a neurophysiological response to stimulus. And if you pick
207 | the precise wavelength, “you could actually cause someone to perceive a
208 | color that they could never otherwise see. Like, there's no natural way
209 | for you to have the perception of that color.” That color wouldn't be
210 | onscreen. It wouldn't be anything a projector could cast or a computer
211 | could generate. It'd be a function of pure cognition, different for every
212 | viewer, existing only in the mind, then fading to nothingness. Which is
213 | true for all colors anyway, when you think about it."
221 |
222 |
230 | —
231 | How Pixar Uses Hyper-Colors
255 |
256 |
264 | ★ “Scientists who study the mechanics of curiosity are finding that it is,
265 | at its core, a kind of probability algorithm—our brain’s continuous
266 | calculation of which path or action is likely to gain us the most
267 | knowledge in the least amount of time. Like the links on a Wikipedia page,
268 | curiosity builds upon itself, every question leading to the next. And as
269 | with a journey down the Wikipedia wormhole, where you start dictates where
270 | you might end up. That’s the funny thing about curiosity: It’s less about
271 | what you don’t know than about what you already do.”
279 |
280 |
288 | —
289 | Curiosity Depends on What you Already Know
302 |
303 |
311 | (In many ways reading is similar. Your reading ability depends on what
319 | you already know. The key to reading faster or remembering more is often
320 | as simple as reading more. Learn more about
321 | reading better.)
336 |
337 |
338 |
349 | Timeless Insight
350 |
351 |
359 | “It is not the amount of knowledge that makes a brain. It is not even the
360 | distribution of knowledge. It is the interconnectedness."
361 |
362 |
370 | — Howard Bloom
378 |
379 |
398 |
409 | Tiny Thought
410 |
411 |
419 | Three stages of thinking:
420 |
421 |
429 | 1. Too simplistic (it's easy).
430 |
431 |
439 | 2. Too complicated (it's hard).
440 |
441 |
449 | 3. Simple (it's simple but not easy).
450 |
451 |
459 | We tend to avoid the hard work necessary to make it simple.
460 |
461 |
462 |
470 |
476 |
482 |
488 |
502 | Sponsored by Trends
503 | |
504 |
505 |
506 |
507 |
515 |
546 |
547 |
556 | Trends
569 | is where entrepreneurs and investors find the next big thing. Every week,
570 | their team of analysts send a detailed report on markets that are about to
571 | explode, and exactly how you can capitalize. Uncover 1,000+ emerging market
572 | trends by visiting
573 | trends.co/farnamstreet
586 | to try your first 7 days for free.
594 |
595 |
603 |
611 | Stay safe,
612 |
613 |
621 | Shane
622 |
623 |
631 | P.S. The
639 | Great Mental Models V1 hardcover
652 | is on sale at Amazon.com for the lowest price ever. (Please note we don't
653 | control pricing and have no idea how long it will last.)
655 |
656 |
664 |
677 |
678 |
686 |
694 |
695 |
703 |
711 |
712 |
720 |
728 |
729 |
737 |
745 |
746 |
754 |
762 |
763 |
771 |
779 |
780 |
873 |

886 |
`;
887 | exports.default = htmlExample;
888 |
--------------------------------------------------------------------------------
/dist/tests/prodExample2/expectedBlocks.d.ts:
--------------------------------------------------------------------------------
1 | declare const expectedBlocks: any;
2 | export default expectedBlocks;
3 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node',
4 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "html-to-notion",
3 | "version": "0.2.1",
4 | "description": "Convert an HTML string into Notion blocks",
5 | "main": "dist/index.js",
6 | "typings": "dist/index.d.ts",
7 | "repository": "https://github.com/baptisteArno/notionbox-parser",
8 | "license": "MIT",
9 | "keywords": [],
10 | "publishConfig": {
11 | "registry": "https://registry.npmjs.org/"
12 | },
13 | "scripts": {
14 | "start": "run-s build && node dist/examples/parseAndSendToNotion",
15 | "build": "eslint src --ext .ts && tsc -p tsconfig.json",
16 | "fix": "run-s fix:*",
17 | "fix:prettier": "prettier \"src/**/*.ts\" --write",
18 | "fix:lint": "eslint src --ext .ts --fix",
19 | "test": "run-s build test:*",
20 | "test:lint": "eslint src --ext .ts",
21 | "test:prettier": "prettier \"src/**/*.ts\" --list-different",
22 | "test:unit": "nyc --silent ava",
23 | "check-cli": "run-s test diff-integration-tests check-integration-tests",
24 | "check-integration-tests": "run-s check-integration-test:*",
25 | "diff-integration-tests": "mkdir -p diff && rm -rf diff/test && cp -r test diff/test && rm -rf diff/test/test-*/.git && cd diff && git init --quiet && git add -A && git commit --quiet --no-verify --allow-empty -m 'WIP' && echo '\\n\\nCommitted most recent integration test output in the \"diff\" directory. Review the changes with \"cd diff && git diff HEAD\" or your preferred git diff viewer.'",
26 | "watch:build": "tsc -p tsconfig.json -w",
27 | "watch:test": "nyc --silent ava --watch",
28 | "cov": "run-s build test:unit cov:html cov:lcov && open-cli coverage/index.html",
29 | "cov:html": "nyc report --reporter=html",
30 | "cov:lcov": "nyc report --reporter=lcov",
31 | "cov:send": "run-s cov:lcov && codecov",
32 | "cov:check": "nyc report && nyc check-coverage --lines 100 --functions 100 --branches 100",
33 | "doc": "run-s doc:html && open-cli build/docs/index.html",
34 | "doc:html": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --out build/docs",
35 | "doc:json": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --json build/docs/typedoc.json",
36 | "doc:publish": "gh-pages -m \"[ci skip] Updates\" -d build/docs",
37 | "version": "standard-version",
38 | "reset-hard": "git clean -dfx && git reset --hard && yarn",
39 | "prepare-release": "run-s reset-hard test cov:check doc:html version doc:publish"
40 | },
41 | "engines": {
42 | "node": ">=10"
43 | },
44 | "dependencies": {
45 | "@notionhq/client": "^0.2.2",
46 | "dotenv": "^10.0.0",
47 | "fs": "^0.0.1-security",
48 | "htmlparser2": "^6.1.0"
49 | },
50 | "devDependencies": {
51 | "@ava/typescript": "^1.1.1",
52 | "@istanbuljs/nyc-config-typescript": "^1.0.1",
53 | "@types/jest": "^26.0.24",
54 | "@typescript-eslint/eslint-plugin": "^4.28.3",
55 | "@typescript-eslint/parser": "^4.28.3",
56 | "ava": "^3.12.1",
57 | "codecov": "^3.5.0",
58 | "cspell": "^4.1.0",
59 | "cz-conventional-changelog": "^3.3.0",
60 | "eslint": "^7.31.0",
61 | "eslint-config-airbnb-typescript": "^12.3.1",
62 | "eslint-config-prettier": "^8.3.0",
63 | "eslint-plugin-eslint-comments": "^3.2.0",
64 | "eslint-plugin-import": "^2.22.0",
65 | "gh-pages": "^3.1.0",
66 | "jest": "^27.0.6",
67 | "npm-run-all": "^4.1.5",
68 | "nyc": "^15.1.0",
69 | "open-cli": "^6.0.1",
70 | "prettier": "^2.3.2",
71 | "standard-version": "^9.0.0",
72 | "ts-jest": "^27.0.3",
73 | "ts-node": "^10.1.0",
74 | "typedoc": "^0.19.0",
75 | "typescript": "^4.3.5"
76 | },
77 | "files": [
78 | "build/main",
79 | "build/module",
80 | "!**/*.spec.*",
81 | "!**/*.json",
82 | "CHANGELOG.md",
83 | "LICENSE",
84 | "README.md"
85 | ],
86 | "ava": {
87 | "failFast": true,
88 | "timeout": "60s",
89 | "typescript": {
90 | "rewritePaths": {
91 | "src/": "build/main/"
92 | }
93 | },
94 | "files": [
95 | "!build/module/**"
96 | ]
97 | },
98 | "config": {
99 | "commitizen": {
100 | "path": "cz-conventional-changelog"
101 | }
102 | },
103 | "prettier": {
104 | "singleQuote": true
105 | },
106 | "nyc": {
107 | "extends": "@istanbuljs/nyc-config-typescript",
108 | "exclude": [
109 | "**/*.spec.js"
110 | ]
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import parseHtmlToNotionBlocks from './lib/parser';
2 |
3 | export default parseHtmlToNotionBlocks;
4 |
--------------------------------------------------------------------------------
/src/lib/ContentParser/LinkParser.ts:
--------------------------------------------------------------------------------
1 | import ContentParser from '.';
2 | import { BuildingBlock } from '../models';
3 |
4 | class LinkParser extends ContentParser {
5 | parse = (buildingBlock: BuildingBlock) => {
6 | if (!buildingBlock.block) {
7 | return {
8 | ...buildingBlock,
9 | block: {
10 | object: 'block',
11 | type: 'paragraph',
12 | paragraph: {
13 | text: [
14 | {
15 | type: 'text',
16 | text: {
17 | content: this.content,
18 | link: {
19 | url: buildingBlock.src,
20 | },
21 | },
22 | },
23 | ],
24 | },
25 | },
26 | type: 'paragraph',
27 | } as BuildingBlock;
28 | }
29 | if (!buildingBlock.type) return buildingBlock;
30 | // Tricky dynamic type part. Disabling...
31 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
32 | // @ts-ignore
33 | buildingBlock.block[buildingBlock.type].text.push({
34 | type: 'text',
35 | text: {
36 | content: this.content,
37 | link: {
38 | url: buildingBlock.src,
39 | },
40 | },
41 | });
42 | return buildingBlock;
43 | };
44 | }
45 |
46 | export default LinkParser;
47 |
--------------------------------------------------------------------------------
/src/lib/ContentParser/TextParser.ts:
--------------------------------------------------------------------------------
1 | import ContentParser from '.';
2 | import { BuildingBlock } from '../models';
3 | import {
4 | HtmlTextTags,
5 | NotionTextTypes,
6 | textTagNameToNotionTypeMap,
7 | } from '../notionUtils';
8 |
9 | class TextParser extends ContentParser {
10 | private type: NotionTextTypes;
11 |
12 | constructor(content: string, tagName: HtmlTextTags) {
13 | super(content);
14 | this.type = textTagNameToNotionTypeMap.get(tagName) as NotionTextTypes;
15 | }
16 |
17 | parse = (buildingBlock: BuildingBlock) => {
18 | if (!buildingBlock.block) {
19 | return {
20 | ...buildingBlock,
21 | block: {
22 | object: 'block',
23 | type: this.type,
24 | [this.type]: {
25 | text: [
26 | {
27 | type: 'text',
28 | text: {
29 | content: this.content,
30 | },
31 | },
32 | ],
33 | },
34 | } as any,
35 | type: this.type,
36 | } as BuildingBlock;
37 | }
38 | if (buildingBlock.type) {
39 | // Tricky dynamic type part. Disabling...
40 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
41 | // @ts-ignore
42 | buildingBlock.block[buildingBlock.type].text.push({
43 | type: 'text',
44 | text: {
45 | content: this.content,
46 | },
47 | });
48 | }
49 | return buildingBlock;
50 | };
51 | }
52 |
53 | export default TextParser;
54 |
--------------------------------------------------------------------------------
/src/lib/ContentParser/index.ts:
--------------------------------------------------------------------------------
1 | import { BuildingBlock } from '../models';
2 |
3 | abstract class ContentParser {
4 | constructor(protected content: string) {}
5 |
6 | public abstract parse(buildingBlock?: BuildingBlock): BuildingBlock;
7 | }
8 |
9 | export default ContentParser;
10 |
--------------------------------------------------------------------------------
/src/lib/NotionParser.ts:
--------------------------------------------------------------------------------
1 | import { Block } from '@notionhq/client/build/src/api-types';
2 | import ContentParser from './ContentParser';
3 | import LinkParser from './ContentParser/LinkParser';
4 | import TextParser from './ContentParser/TextParser';
5 | import { BuildingBlock } from './models';
6 |
7 | class NotionParser {
8 | private buildingBlock: BuildingBlock = {};
9 |
10 | private producedBlocks: Block[] = [];
11 |
12 | private currentElementsStack: string[] = [];
13 |
14 | private isWaitingForBodyElement: boolean = false;
15 |
16 | getBlocks = (): Block[] => this.producedBlocks;
17 |
18 | onOpenTag = (tagName: string, attributes: { [s: string]: string }): void => {
19 | this.preCheckHtmlFormat(tagName);
20 | if (this.isWaitingForBodyElement) return;
21 | const isBuildingBlock =
22 | this.currentElementsStack.length > 0 && this.buildingBlock?.block;
23 | if (isBuildingBlock) {
24 | if (tagName === 'br') {
25 | this.producedBlocks.push(this.buildingBlock.block!);
26 | this.flushBuildingBlock();
27 | }
28 | this.currentElementsStack.push(tagName);
29 | } else {
30 | this.currentElementsStack = [tagName];
31 | }
32 | this.setLinkAttributesIfExists(attributes);
33 | };
34 |
35 | private preCheckHtmlFormat(tagName: string) {
36 | if (tagName === 'html') {
37 | this.isWaitingForBodyElement = true;
38 | }
39 | if (tagName === 'body') {
40 | this.isWaitingForBodyElement = false;
41 | }
42 | }
43 |
44 | private setLinkAttributesIfExists(attributes: { [s: string]: string }) {
45 | if (attributes.src) {
46 | this.buildingBlock.src = attributes.src;
47 | } else if (attributes.href) {
48 | this.buildingBlock.src = attributes.href;
49 | }
50 | }
51 |
52 | onText = (content: string): void => {
53 | if (this.isWaitingForBodyElement) return;
54 | const addSpaceBeforeContent = (val: string) => ` ${val}`;
55 | const currentBlockHasText =
56 | this.buildingBlock.block && this.currentElementsStack.length > 0;
57 |
58 | // matches tabs, newlines, more than 2 spaces and
59 | // unicode zero-width characters (https://stackoverflow.com/a/11305926/5654715)
60 | let cleanContent = content
61 | .replace(/[\t\n\r\u200B\u200C\u200D\uFEFF]/gm, '')
62 | .replace(/\s{2,}/gm, ' ')
63 | .trim();
64 |
65 | if (cleanContent) {
66 | if (currentBlockHasText) {
67 | cleanContent = addSpaceBeforeContent(cleanContent);
68 | }
69 | const contentParser = this.initContentParser(cleanContent);
70 | this.buildingBlock = contentParser.parse(this.buildingBlock);
71 | }
72 | };
73 |
74 | onCloseTag = (): void => {
75 | if (this.isWaitingForBodyElement) return;
76 | if (this.buildingBlock?.block && this.currentElementsStack.length === 1) {
77 | this.producedBlocks.push(this.buildingBlock.block);
78 | this.flushBuildingBlock();
79 | }
80 | this.currentElementsStack.splice(-1, 1);
81 | };
82 |
83 | flushBuildingBlock = (): void => {
84 | this.buildingBlock = {};
85 | };
86 |
87 | flushElementStack = () => {
88 | this.currentElementsStack = [];
89 | };
90 |
91 | initContentParser = (content: string): ContentParser => {
92 | const tagName = [...this.currentElementsStack].pop();
93 | switch (tagName) {
94 | case 'h1':
95 | case 'h2':
96 | case 'h3':
97 | case 'h4':
98 | case 'h5':
99 | case 'h6': {
100 | return new TextParser(content, tagName);
101 | }
102 | case 'a': {
103 | return new LinkParser(content);
104 | }
105 | default: {
106 | return new TextParser(content, 'p');
107 | }
108 | }
109 | };
110 | }
111 |
112 | export default NotionParser;
113 |
--------------------------------------------------------------------------------
/src/lib/models.ts:
--------------------------------------------------------------------------------
1 | import { Block } from '@notionhq/client/build/src/api-types';
2 |
3 | export type BuildingBlock = {
4 | block?: Block;
5 | type?: string;
6 | src?: string;
7 | };
8 |
--------------------------------------------------------------------------------
/src/lib/notionUtils.ts:
--------------------------------------------------------------------------------
1 | export type HtmlTextTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
2 | export type NotionTextTypes =
3 | | 'heading_1'
4 | | 'heading_2'
5 | | 'heading_3'
6 | | 'paragraph';
7 |
8 | export const textTagNameToNotionTypeMap = new Map<
9 | HtmlTextTags,
10 | NotionTextTypes
11 | >([
12 | ['h1', 'heading_1'],
13 | ['h2', 'heading_2'],
14 | ['h3', 'heading_3'],
15 | ['h4', 'heading_3'],
16 | ['h5', 'heading_3'],
17 | ['h6', 'heading_3'],
18 | ['p', 'paragraph'],
19 | ]);
20 |
--------------------------------------------------------------------------------
/src/lib/parser.ts:
--------------------------------------------------------------------------------
1 | import { Block } from '@notionhq/client/build/src/api-types';
2 | import { Parser } from 'htmlparser2';
3 | import NotionParser from './NotionParser';
4 |
5 | const initParser = (notionParser: NotionParser) =>
6 | new Parser({
7 | onopentag(tagName, attributes) {
8 | notionParser.onOpenTag(tagName, attributes);
9 | },
10 | ontext(content) {
11 | notionParser.onText(content);
12 | },
13 | onclosetag() {
14 | notionParser.onCloseTag();
15 | },
16 | });
17 |
18 | const parseHtmlToNotionBlocks = (html: string): Block[] => {
19 | const notionParser = new NotionParser();
20 | const parser = initParser(notionParser);
21 | parser.write(html);
22 | parser.end();
23 | return notionParser.getBlocks();
24 | };
25 |
26 | export default parseHtmlToNotionBlocks;
27 |
--------------------------------------------------------------------------------
/tests/parser.spec.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import parseHtmlToNotionBlocks from '../src/lib/parser';
3 | import rawHtmlOne from './prodExample1/rawHtml';
4 | import expectedBlocksOne from './prodExample1/expectedBlocks';
5 | import rawHtmlTwo from './prodExample2/rawHtml';
6 | import expectedBlocksTwo from './prodExample2/expectedBlocks';
7 |
8 | describe('NotionParser', () => {
9 | it('should parse paragraphs', () => {
10 | const testHtml = '
46 |
54 | Hey ...
55 |
56 |
64 | Sunday Brain Food: a weekly newsletter full of timeless ideas and insights
65 | for life and business.
66 |
67 |
75 | (Was this newsletter forwarded to you?
83 | Sign up here.)
103 |
104 |
115 | FS
116 |
117 |
125 | "For the first three months, I place each student at a table with a thousand
126 | pieces of white paper and a trash can underneath. Every day they have to sit
127 | at the table for several hours and write ideas. They put the ideas they like
128 | on the right side of the table; the ones they don’t like, they put in the
129 | trash. But we don’t throw out the trash. After three months, I only take the
130 | ideas from the trash can. I don’t even look at the ideas they liked. Because
131 | the trash can is a treasure trove of things they’re afraid to do."
139 |
140 |
148 | —
149 | Life Lessons from Marina Abramović
162 |
163 |
182 |
193 | Explore Your Curiosity
194 |
195 |
203 | ★ "You'd imagine you were seeing a specific red, not projected on the
204 | screen but as a neurophysiological response to stimulus. And if you pick
205 | the precise wavelength, “you could actually cause someone to perceive a
206 | color that they could never otherwise see. Like, there's no natural way
207 | for you to have the perception of that color.” That color wouldn't be
208 | onscreen. It wouldn't be anything a projector could cast or a computer
209 | could generate. It'd be a function of pure cognition, different for every
210 | viewer, existing only in the mind, then fading to nothingness. Which is
211 | true for all colors anyway, when you think about it."
219 |
220 |
228 | —
229 | How Pixar Uses Hyper-Colors
253 |
254 |
262 | ★ “Scientists who study the mechanics of curiosity are finding that it is,
263 | at its core, a kind of probability algorithm—our brain’s continuous
264 | calculation of which path or action is likely to gain us the most
265 | knowledge in the least amount of time. Like the links on a Wikipedia page,
266 | curiosity builds upon itself, every question leading to the next. And as
267 | with a journey down the Wikipedia wormhole, where you start dictates where
268 | you might end up. That’s the funny thing about curiosity: It’s less about
269 | what you don’t know than about what you already do.”
277 |
278 |
286 | —
287 | Curiosity Depends on What you Already Know
300 |
301 |
309 | (In many ways reading is similar. Your reading ability depends on what
317 | you already know. The key to reading faster or remembering more is often
318 | as simple as reading more. Learn more about
319 | reading better.)
334 |
335 |
336 |
347 | Timeless Insight
348 |
349 |
357 | “It is not the amount of knowledge that makes a brain. It is not even the
358 | distribution of knowledge. It is the interconnectedness."
359 |
360 |
368 | — Howard Bloom
376 |
377 |
396 |
407 | Tiny Thought
408 |
409 |
417 | Three stages of thinking:
418 |
419 |
427 | 1. Too simplistic (it's easy).
428 |
429 |
437 | 2. Too complicated (it's hard).
438 |
439 |
447 | 3. Simple (it's simple but not easy).
448 |
449 |
457 | We tend to avoid the hard work necessary to make it simple.
458 |
459 |
460 |
468 |
474 |
480 |
486 |
500 | Sponsored by Trends
501 | |
502 |
503 |
504 |
505 |
513 |
544 |
545 |
554 | Trends
567 | is where entrepreneurs and investors find the next big thing. Every week,
568 | their team of analysts send a detailed report on markets that are about to
569 | explode, and exactly how you can capitalize. Uncover 1,000+ emerging market
570 | trends by visiting
571 | trends.co/farnamstreet
584 | to try your first 7 days for free.
592 |
593 |
601 |
609 | Stay safe,
610 |
611 |
619 | Shane
620 |
621 |
629 | P.S. The
637 | Great Mental Models V1 hardcover
650 | is on sale at Amazon.com for the lowest price ever. (Please note we don't
651 | control pricing and have no idea how long it will last.)
653 |
654 |
662 |
675 |
676 |
684 |
692 |
693 |
701 |
709 |
710 |
718 |
726 |
727 |
735 |
743 |
744 |
752 |
760 |
761 |
769 |
777 |
778 |
871 |

884 |
`;
885 |
886 | export default htmlExample;
887 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "dist",
4 | "allowJs": true,
5 | "target": "ES6",
6 | "moduleResolution": "Node",
7 | "module": "commonjs",
8 | "declaration": true,
9 | "strict": true
10 | },
11 | "include": ["src/**/*", "tests/**/*"]
12 | }
13 |
--------------------------------------------------------------------------------