├── example ├── .gitignore ├── notes │ └── markdown.mdx ├── .env.sample ├── README.md ├── package.json ├── gatsby-config.js ├── src │ └── gatsby-theme-garden │ │ └── components │ │ └── references-block.js └── static │ └── sitemap.xml ├── .github ├── FUNDING.yml └── workflows │ ├── test-fetch-roamresearch.yml │ ├── test-react-stacked-pages-hook.yml │ ├── test-gatsby-source-roamresearch.yml │ ├── test-gatsby-remark-double-brackets-link.yml │ ├── test-gatsby-remark-double-parenthesis-link.yml │ ├── test-gatsby-transformer-markdown-references.yml │ └── example.yml ├── packages ├── gatsby-source-roamresearch │ ├── .gitignore │ ├── index.js │ ├── gatsby-node.js │ ├── src │ │ ├── on-pre-bootstrap.ts │ │ ├── make-markdown.ts │ │ ├── create-schema-customization.ts │ │ └── source-nodes.ts │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── react-stacked-pages-hook │ ├── .gitignore │ ├── src │ │ ├── index.ts │ │ ├── contexts.ts │ │ ├── Link.tsx │ │ └── hooks.tsx │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── gatsby-theme-garden │ ├── index.js │ ├── src │ │ ├── templates │ │ │ └── .gitkeep │ │ ├── components │ │ │ ├── custom.css │ │ │ ├── mdx-components │ │ │ │ ├── index.js │ │ │ │ ├── mdx-renderer.js │ │ │ │ ├── anchor-tag.css │ │ │ │ └── anchor-tag.js │ │ │ ├── graph-button.css │ │ │ ├── reference.css │ │ │ ├── reference.js │ │ │ ├── references-block.js │ │ │ ├── references-block.css │ │ │ ├── header.css │ │ │ ├── dark-mode-toggle.js │ │ │ ├── header.js │ │ │ ├── note.js │ │ │ ├── note-wrapper.js │ │ │ ├── theme.css │ │ │ ├── graph-visualisation.css │ │ │ ├── seo.js │ │ │ ├── graph-button.js │ │ │ ├── dark-mode-toggle.css │ │ │ ├── stacked-layout.css │ │ │ ├── note-wrapper.css │ │ │ ├── search.css │ │ │ ├── stacked-layout.js │ │ │ ├── search.js │ │ │ └── graph-visualisation.js │ │ ├── use-site-metadata.js │ │ ├── use-window-size.js │ │ ├── utils │ │ │ ├── gradient.js │ │ │ └── data-to-note.js │ │ └── use-search.js │ ├── .gitignore │ ├── should-handle-file.js │ ├── templates │ │ ├── local-file.template │ │ ├── roam-page.template │ │ └── roam-block.template │ ├── fragments │ │ ├── file.fragment │ │ ├── roam.fragment │ │ ├── file-and-roam.fragment │ │ ├── file-graph.fragment │ │ ├── roam-graph.fragment │ │ └── file-and-roam-graph.fragment │ ├── package.json │ ├── gatsby-config.js │ ├── README.md │ ├── search-indexes.js │ └── gatsby-node.js ├── gatsby-transformer-markdown-references │ ├── index.d.ts │ ├── index.js │ ├── src │ │ ├── non-nullable.ts │ │ ├── options.ts │ │ ├── get-references.ts │ │ ├── markdown-utils.ts │ │ ├── on-create-node.ts │ │ ├── create-schema-customization.ts │ │ ├── cache.ts │ │ └── compute-inbounds.ts │ ├── gatsby-node.js │ ├── tsconfig.json │ ├── package.json │ └── README.md ├── fetch-roamresearch │ ├── src │ │ ├── roam-schema.ts │ │ └── index.ts │ ├── README.md │ ├── tsconfig.json │ ├── package.json │ └── package-lock.json ├── gatsby-remark-double-brackets-link │ ├── tsconfig.json │ ├── package.json │ ├── README.md │ ├── package-lock.json │ └── src │ │ └── index.ts └── gatsby-remark-double-parenthesis-link │ ├── tsconfig.json │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ └── package-lock.json ├── .gitignore ├── package.json ├── LICENSE └── README.md /example/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [mathieudutour] 2 | -------------------------------------------------------------------------------- /packages/gatsby-source-roamresearch/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react-stacked-pages-hook/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/index.js: -------------------------------------------------------------------------------- 1 | // noop 2 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/templates/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/gatsby-source-roamresearch/index.js: -------------------------------------------------------------------------------- 1 | // no op 2 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/.gitignore: -------------------------------------------------------------------------------- 1 | /src/use-graph-data.js 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | example/.cache 4 | example/public 5 | example/.env 6 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/custom.css: -------------------------------------------------------------------------------- 1 | /** Add any custom CSS you want here **/ 2 | -------------------------------------------------------------------------------- /packages/gatsby-transformer-markdown-references/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./lib/markdown-utils"; 2 | -------------------------------------------------------------------------------- /packages/gatsby-transformer-markdown-references/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./lib/markdown-utils"); 2 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/mdx-components/index.js: -------------------------------------------------------------------------------- 1 | export { AnchorTag as a } from "./anchor-tag"; 2 | -------------------------------------------------------------------------------- /packages/react-stacked-pages-hook/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./contexts"; 2 | export * from "./hooks"; 3 | export * from "./Link"; 4 | -------------------------------------------------------------------------------- /example/notes/markdown.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Markdown" 3 | --- 4 | 5 | # Markdown 6 | 7 | Markdown is nice 😁 8 | 9 | It can even reference pages from [[Roam Research]]! 10 | -------------------------------------------------------------------------------- /packages/gatsby-transformer-markdown-references/src/non-nullable.ts: -------------------------------------------------------------------------------- 1 | export function nonNullable(value: T): value is NonNullable { 2 | return value !== null && value !== undefined; 3 | } 4 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/graph-button.css: -------------------------------------------------------------------------------- 1 | .graph-button { 2 | border: 0; 3 | background: none; 4 | cursor: pointer; 5 | } 6 | 7 | .graph-button svg g { 8 | stroke: var(--link); 9 | } 10 | -------------------------------------------------------------------------------- /example/.env.sample: -------------------------------------------------------------------------------- 1 | # Replace the variables with your own and rename this file to `.env` 2 | 3 | ROAM_URL="https://roamresearch.com/#/app/YOUR_ROAM_DATABASE" 4 | ROAM_EMAIL="YOUR_ROAM_EMAIL" 5 | ROAM_PASSWORD="YOUR_ROAM_PASSWORD" 6 | -------------------------------------------------------------------------------- /packages/gatsby-source-roamresearch/gatsby-node.js: -------------------------------------------------------------------------------- 1 | exports.onPreBootstrap = require("./lib/on-pre-bootstrap").onPreBoostrap; 2 | exports.sourceNodes = require("./lib/source-nodes").sourceNodes; 3 | // exports.createSchemaCustomization = require("./lib/create-schema-customization").createSchemaCustomization; 4 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Digital Garden Using Roam Research 2 | 3 | [https://mathieudutour.github.io/gatsby-digital-garden/](https://mathieudutour.github.io/gatsby-digital-garden/) 4 | 5 | Example site that demonstrates how to build a Gatsby digital garden that pull data from 6 | [Roam Research](https://roamresearch.com/). 7 | -------------------------------------------------------------------------------- /packages/gatsby-transformer-markdown-references/src/options.ts: -------------------------------------------------------------------------------- 1 | export type PluginOptions = { 2 | types?: string[]; 3 | }; 4 | 5 | const defaultOptions = { 6 | types: ["Mdx"], 7 | }; 8 | 9 | export const resolveOptions = (options?: PluginOptions) => { 10 | return { ...defaultOptions, ...options }; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/gatsby-transformer-markdown-references/gatsby-node.js: -------------------------------------------------------------------------------- 1 | exports.onCreateNode = require("./lib/on-create-node.js").onCreateNode; 2 | exports.createSchemaCustomization = require("./lib/create-schema-customization").createSchemaCustomization; 3 | exports.setFieldsOnGraphQLNodeType = require("./lib/create-schema-customization").setFieldsOnGraphQLNodeType; 4 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/use-site-metadata.js: -------------------------------------------------------------------------------- 1 | import { graphql, useStaticQuery } from "gatsby"; 2 | 3 | export default () => { 4 | const data = useStaticQuery(graphql` 5 | { 6 | site { 7 | siteMetadata { 8 | title 9 | description 10 | } 11 | } 12 | } 13 | `); 14 | 15 | return data.site.siteMetadata; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/should-handle-file.js: -------------------------------------------------------------------------------- 1 | module.exports = function shouldHandleFile(node, options = {}) { 2 | return ( 3 | ((options.extensions || [".md", ".mdx"]).includes(node.ext) || 4 | (options.mediaTypes || ["text/markdown", "text/x-markdown"]).includes( 5 | node.internal.mediaType 6 | )) && 7 | node.sourceInstanceName === options.contentPath 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/reference.css: -------------------------------------------------------------------------------- 1 | .reference { 2 | text-decoration: none; 3 | } 4 | 5 | .reference:hover { 6 | color: var(--references-highlight); 7 | } 8 | 9 | .reference > div { 10 | padding-top: 0.5rem; 11 | padding-bottom: 0.5rem; 12 | } 13 | 14 | .reference > div > p { 15 | margin: 0; 16 | font-size: 0.875rem; 17 | } 18 | 19 | .reference > div > ul { 20 | margin: 0; 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-digital-garden", 3 | "private": true, 4 | "scripts": { 5 | "test": "jest" 6 | }, 7 | "author": "Mathieu Dutour ", 8 | "license": "MIT", 9 | "devDependencies": { 10 | "@types/jest": "^25.2.2", 11 | "@types/node": "^14.0.1", 12 | "jest": "^26.0.1", 13 | "jest-cli": "^26.0.1", 14 | "prettier": "^2.0.5", 15 | "ts-node": "^8.10.1", 16 | "typescript": "^3.9.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/templates/local-file.template: -------------------------------------------------------------------------------- 1 | import { graphql } from "gatsby"; 2 | 3 | import StackedLayout from "../components/stacked-layout"; 4 | 5 | export default StackedLayout; 6 | 7 | export const pageQuery = graphql` 8 | query($id: String!) { 9 | file(id: { eq: $id }) { 10 | childMdx { 11 | body 12 | ...GatsbyGardenReferences 13 | } 14 | fields { 15 | slug 16 | title 17 | } 18 | } 19 | } 20 | `; 21 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/templates/roam-page.template: -------------------------------------------------------------------------------- 1 | import { graphql } from "gatsby"; 2 | 3 | import StackedLayout from "../components/stacked-layout"; 4 | 5 | export default StackedLayout; 6 | 7 | export const pageQuery = graphql` 8 | query($id: String!) { 9 | roamPage(id: { eq: $id }) { 10 | title 11 | childMdx { 12 | body 13 | ...GatsbyGardenReferences 14 | } 15 | fields { 16 | slug 17 | } 18 | } 19 | } 20 | `; 21 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/reference.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { LinkToStacked } from "react-stacked-pages-hook"; 3 | 4 | import "./reference.css"; 5 | 6 | const Reference = ({ node }) => { 7 | return ( 8 |
9 | 10 |
11 |
{node.title}
12 | {node.content} 13 |
14 |
15 |
16 | ); 17 | }; 18 | 19 | export default Reference; 20 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/mdx-components/mdx-renderer.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { mdx } from "@mdx-js/react"; 3 | 4 | export default function MDXRenderer({ children, ...props }) { 5 | // Memoize the compiled component 6 | const End = React.useMemo(() => { 7 | if (!children) { 8 | return null; 9 | } 10 | 11 | const fn = new Function(`_fn`, "React", "mdx", `${children}`); 12 | 13 | return fn({}, React, mdx); 14 | }, [children]); 15 | 16 | return React.createElement(End, { ...props }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/fetch-roamresearch/src/roam-schema.ts: -------------------------------------------------------------------------------- 1 | export type RoamPage = { 2 | title: string; 3 | children?: RoamBlock[]; 4 | "create-time"?: number; 5 | "create-email"?: string; 6 | "edit-time"?: number; 7 | "edit-email"?: string; 8 | }; 9 | 10 | export type RoamBlock = { 11 | string: string; 12 | uid?: string; 13 | children?: RoamBlock[]; 14 | "create-time"?: number; 15 | "create-email"?: string; 16 | "edit-time"?: number; 17 | "edit-email"?: string; 18 | heading?: 0 | 1 | 2 | 3; 19 | "text-align": "left" | "center" | "right" | "justify"; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/templates/roam-block.template: -------------------------------------------------------------------------------- 1 | import { graphql } from "gatsby"; 2 | 3 | import StackedLayout from "../components/stacked-layout"; 4 | 5 | export default StackedLayout; 6 | 7 | export const pageQuery = graphql` 8 | query($id: String!) { 9 | roamBlock(id: { eq: $id }) { 10 | childMdx { 11 | body 12 | ...GatsbyGardenReferences 13 | } 14 | fields { 15 | slug 16 | parentPage { 17 | title 18 | fields { 19 | slug 20 | } 21 | } 22 | } 23 | } 24 | } 25 | `; 26 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/references-block.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Reference from "./reference"; 3 | 4 | import "./references-block.css"; 5 | 6 | const ReferencesBlock = ({ references }) => { 7 | if (!references.length) { 8 | return null; 9 | } 10 | 11 | return ( 12 |
13 |

Referred in

14 |
15 | {references.map((ref) => ( 16 | 17 | ))} 18 |
19 |
20 | ); 21 | }; 22 | 23 | export default ReferencesBlock; 24 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-example-using-roamresearch", 3 | "private": true, 4 | "description": "Gatsby example site using the Roam Research source plugin", 5 | "version": "1.0.0", 6 | "author": "Mathieu Dutour ", 7 | "dependencies": { 8 | "gatsby": "^2.21.22", 9 | "gatsby-theme-garden": "^0.1.54", 10 | "react": "^16.3.1", 11 | "react-dom": "^16.3.1" 12 | }, 13 | "keywords": [ 14 | "gatsby" 15 | ], 16 | "license": "MIT", 17 | "main": "n/a", 18 | "scripts": { 19 | "develop": "gatsby develop", 20 | "build": "gatsby build", 21 | "start": "gatsby serve" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/fetch-roamresearch/README.md: -------------------------------------------------------------------------------- 1 | # fetch-roamresearch 2 | 3 | Export a Roam Research database 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install fetch-roamresearch 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```ts 14 | import fetchRoamResearch from "fetch-roamresearch"; 15 | 16 | const ROAM_URL = "https://roamresearch.com/#/app/YOUR_ROAM_DATABASE"; 17 | const ROAM_EMAIL = "YOUR_ROAM_EMAIL"; 18 | const ROAM_PASSWORD = "YOUR_ROAM_PASSWORD"; 19 | 20 | const pages = await fetchRoamResearch(ROAM_URL, { 21 | email: ROAM_EMAIL, 22 | password: ROAM_PASSWORD, 23 | }); 24 | ``` 25 | 26 | > Note that it only works with an email/password login. Google login is not supported. 27 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/references-block.css: -------------------------------------------------------------------------------- 1 | .references-block { 2 | color: var(--references-text); 3 | padding: 1rem; 4 | margin: 1rem 0; 5 | border-radius: 0.5rem; 6 | background-color: var(--references-bg); 7 | transition: background-color 0.3s ease, color 0.3s ease; 8 | } 9 | 10 | .references-block > div { 11 | margin-bottom: 1rem; 12 | } 13 | 14 | .references-block > hr { 15 | margin-left: auto; 16 | margin-right: auto; 17 | width: 8rem; 18 | } 19 | 20 | .references-block a { 21 | color: var(--references-text); 22 | transition: color 0.3s ease; 23 | } 24 | 25 | .references-block > p:last-child { 26 | margin-bottom: 0; 27 | } 28 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/header.css: -------------------------------------------------------------------------------- 1 | header { 2 | padding-left: 32px; 3 | padding-right: 32px; 4 | width: 100%; 5 | min-height: 57px; 6 | z-index: 5; 7 | background-color: var(--note-bg); 8 | border-bottom: 1px solid var(--separator); 9 | display: flex; 10 | justify-content: space-between; 11 | align-items: center; 12 | padding-top: 10px; 13 | padding-bottom: 10px; 14 | flex-wrap: wrap; 15 | transition: background-color 0.3s ease; 16 | } 17 | 18 | header > a { 19 | font-weight: 700; 20 | color: var(--text); 21 | text-decoration: none; 22 | transition: color 0.3s ease; 23 | } 24 | 25 | header .controls { 26 | display: flex; 27 | } 28 | -------------------------------------------------------------------------------- /packages/gatsby-theme-garden/src/components/dark-mode-toggle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import useDarkMode from "use-dark-mode"; 3 | 4 | import "./dark-mode-toggle.css"; 5 | 6 | const DarkModeToggle = () => { 7 | const { value: isDark, toggle: toggleDarkMode } = useDarkMode(false); 8 | 9 | return ( 10 |