├── .eslintrc
├── .github
└── dependabot.yml
├── .gitignore
├── .prettierrc
├── .vscode
└── settings.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── assets
├── logo.png
└── opengraph.png
├── example
├── README.md
├── code-notes
│ ├── annotations.mdx
│ ├── deeply
│ │ └── nested
│ │ │ └── note.md
│ ├── logo.png
│ ├── markdown-features.md
│ ├── mdx.mdx
│ ├── note-frontmatter.md
│ ├── opengraph.png
│ ├── syntax-highlighting.md
│ ├── untagged.md
│ └── wikilinks.md
├── gatsby-config.js
├── package.json
├── src
│ └── __generated__
│ │ └── gatsby-types.ts
└── tsconfig.json
├── gatsby-theme-code-notes
├── .gitignore
├── .release-it.json
├── README.md
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── index.js
├── package.json
├── src
│ ├── components
│ │ ├── BackLinks
│ │ │ ├── BackLinks.tsx
│ │ │ └── index.ts
│ │ ├── Contents
│ │ │ ├── Contents.tsx
│ │ │ └── index.ts
│ │ ├── Layout
│ │ │ ├── Layout.tsx
│ │ │ └── index.ts
│ │ ├── NavItem
│ │ │ ├── NavItem.tsx
│ │ │ └── index.ts
│ │ ├── NoteList
│ │ │ ├── NoteList.tsx
│ │ │ ├── SortButton.tsx
│ │ │ ├── index.ts
│ │ │ └── useSortableData.ts
│ │ ├── NoteListItem
│ │ │ ├── NoteListItem.tsx
│ │ │ └── index.ts
│ │ ├── NotePage
│ │ │ ├── NotePage.tsx
│ │ │ └── index.ts
│ │ ├── NotesPage
│ │ │ ├── NotesPage.tsx
│ │ │ └── index.ts
│ │ ├── Rough
│ │ │ ├── Rough.tsx
│ │ │ └── index.ts
│ │ ├── Search
│ │ │ ├── SearchInput.tsx
│ │ │ ├── SearchProvider.tsx
│ │ │ ├── SearchResults.tsx
│ │ │ └── index.ts
│ │ ├── Sidebar
│ │ │ ├── Sidebar.tsx
│ │ │ └── index.ts
│ │ ├── TagDot
│ │ │ ├── TagDot.tsx
│ │ │ └── index.ts
│ │ ├── TagList
│ │ │ ├── TagList.tsx
│ │ │ └── index.ts
│ │ └── TagNav
│ │ │ ├── TagNav.tsx
│ │ │ └── index.ts
│ ├── gatsby-plugin-theme-ui
│ │ ├── badges.js
│ │ ├── borderWidths.js
│ │ ├── breakpoints.js
│ │ ├── buttons.js
│ │ ├── colors.js
│ │ ├── components.js
│ │ ├── fonts.js
│ │ ├── forms.js
│ │ ├── images.js
│ │ ├── index.js
│ │ ├── links.js
│ │ ├── radii.js
│ │ ├── shadows.js
│ │ ├── sizes.js
│ │ ├── space.js
│ │ ├── styles.js
│ │ ├── text.js
│ │ ├── utils.js
│ │ └── zIndices.js
│ ├── gatsby
│ │ └── wrapRootElement.js
│ ├── templates
│ │ ├── 404.js
│ │ ├── Note.js
│ │ ├── Notes.js
│ │ ├── TagPage.js
│ │ └── UntaggedTagPage.js
│ ├── use-all-tags.ts
│ ├── use-site-metadata.ts
│ └── utils
│ │ ├── createOpenSearch.js
│ │ ├── getColourFromString.ts
│ │ └── resolve-url.js
└── tsconfig.json
├── package.json
└── yarn.lock
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["eslint:recommended", "prettier", "plugin:react/recommended"],
3 | "plugins": ["react", "react-hooks", "prettier"],
4 | "settings": {
5 | "react": {
6 | "version": "detect"
7 | }
8 | },
9 | "parserOptions": {
10 | "ecmaVersion": 2018,
11 | "sourceType": "module"
12 | },
13 | "rules": {
14 | "react/display-name": 0,
15 | "react/prop-types": 0
16 | },
17 | "env": {
18 | "browser": true,
19 | "node": true,
20 | "commonjs": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm"
9 | directory: "/"
10 | schedule:
11 | interval: "weekly"
12 | - package-ecosystem: "npm"
13 | directory: "/gatsby-theme-code-notes"
14 | schedule:
15 | interval: "weekly"
16 | - package-ecosystem: "npm"
17 | directory: "/example"
18 | schedule:
19 | interval: "weekly"
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache
2 | public
3 | node_modules
4 | /mtc-vectors.txt
5 | .env
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "trailingComma": "es5"
6 | }
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "workbench.colorCustomizations": {
3 | "activityBar.background": "#7295b1",
4 | "activityBar.activeBackground": "#7295b1",
5 | "activityBar.activeBorder": "#e8d6e0",
6 | "activityBar.foreground": "#15202b",
7 | "activityBar.inactiveForeground": "#15202b99",
8 | "activityBarBadge.background": "#e8d6e0",
9 | "activityBarBadge.foreground": "#15202b",
10 | "titleBar.activeBackground": "#557c9b",
11 | "titleBar.inactiveBackground": "#557c9b99",
12 | "titleBar.activeForeground": "#e7e7e7",
13 | "titleBar.inactiveForeground": "#e7e7e799",
14 | "statusBar.background": "#557c9b",
15 | "statusBarItem.hoverBackground": "#7295b1",
16 | "statusBar.foreground": "#e7e7e7"
17 | },
18 | "peacock.color": "#557c9b",
19 | "typescript.tsdk": "node_modules/typescript/lib",
20 | "deno.enable": false
21 | }
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at hi@zander.wtf. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Zander Martineau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
33 |
34 | > **Warning**
35 | > This work on this project is now archived. I have created an up-to-date version of this using [Eleventy](https://www.11ty.dev/) and the source code for it can be found [here](https://github.com/mrmartineau/notes.zander.wtf). If anyone would like to continue work on this theme, please let me know.
36 |
37 | ## Features
38 |
39 | - Notes can:
40 | - be written using Markdown (`.md`) or [MDX](https://mdxjs.com/) (`.mdx`)
41 | - have zero, one or many tags. See an example [here](https://code-notes-example.netlify.app/syntax-highlighting)
42 | - have associated emojis 👏
43 | - be nested in subfolders so you can organise them how you like
44 | - sketchy annotations (highlights, strike-thoughs etc). Find out more [here](https://code-notes-example.netlify.app/annotations)
45 | - Extra markdown features have also been added. Find out more [here](https://code-notes-example.netlify.app/markdown-features)
46 | - Note search powered by the super-fast [Flexsearch](https://github.com/nextapps-de/flexsearch)
47 |
48 | ## Installation
49 |
50 | ```sh
51 | mkdir my-site
52 | cd my-site
53 | yarn init
54 |
55 | # install gatsby-theme-code-notes and it's dependencies
56 | yarn add gatsby-theme-code-notes gatsby react react-dom
57 |
58 | # or
59 |
60 | npm install gatsby-theme-code-notes gatsby react react-dom
61 | ```
62 |
63 | ### Using the Gatsby starter
64 |
65 | #### Step 1: Starter installation
66 |
67 | Source code for the starter can be found at: https://github.com/MrMartineau/gatsby-starter-code-notes
68 |
69 | ##### With `gatsby-cli`:
70 |
71 | ```sh
72 | gatsby new code-notes https://github.com/MrMartineau/gatsby-starter-code-notes
73 | ```
74 |
75 | ##### With `git clone`:
76 |
77 | ```sh
78 | git clone git@github.com:MrMartineau/gatsby-starter-code-notes.git
79 |
80 | cd code-notes
81 |
82 | yarn
83 | ```
84 |
85 | #### Step 2: Develop & Build
86 |
87 | Once installed or cloned locally and all packages are installed you can begin developing your site.
88 |
89 | ```sh
90 | # Run localhost
91 | yarn dev
92 |
93 | # Build your Gatsby site
94 | yarn build
95 | ```
96 |
97 | ## Usage
98 |
99 | ### Theme Options
100 |
101 | | Key | Default value | Description |
102 | | -------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
103 | | `basePath` | `/` | Root url for all notes pages |
104 | | `contentPath` | `/content/notes` | Location of notes content |
105 | | `logo` | `''` (empty string) | Path to your site's logo. Will be used as the `src` attribute for an image |
106 | | `showDescriptionInSidebar` | `true` | Show `config.site.description` in the sidebar |
107 | | `showDate` | `false` | Show the note's modified date |
108 | | `gitRepoContentPath` | `''` | Set the location for your notes if they're hosted online, e.g. your git repo. This will show a "Edit this page" link underneath each note |
109 | | `showThemeInfo` | `true` | Show info about this Gatsby theme |
110 | | `mdxOtherwiseConfigured` | `true` | Configure `gatsby-plugin-mdx`. Note that most sites will not need to use this flag. If your site has already configured `gatsby-plugin-mdx` separately, set this flag `false`. |
111 | | `flexSearchEngineOptions` | `{ encode: 'icase', tokenize: 'forward', resolution: 9 }` | Configure FlexSearch's index method. The default value uses FlexSearch's `default` preset. Find out your other options [here](https://github.com/nextapps-de/flexsearch#presets). |
112 | | `openSearch` | `{ }` | Configure the `opensearch.xml` file contents. This file is generated during the build process. If you want to add opensearch support, ensure you set a `siteUrl` in the config. See [below](#example-usage) for more information. |
113 |
114 | ### Example usage
115 |
116 | This example overrides some of the theme defaults and shows the various options for the opensearch config.
117 |
118 | ```js
119 | // gatsby-config.js
120 | module.exports = {
121 | plugins: [
122 | {
123 | resolve: `gatsby-theme-code-notes`,
124 | options: {
125 | basePath: '/',
126 | contentPath: '/content/notes',
127 | gitRepoContentPath:
128 | 'https://github.com/mrmartineau/gatsby-theme-code-notes/tree/master/example/code-notes/',
129 | showDescriptionInSidebar: true,
130 | showThemeInfo: false,
131 | logo: 'https://brand.zander.wtf/Avatar.png',
132 | showDate: true,
133 |
134 | // Opensearch is used to enhance the search on your site.
135 | // If you want to add it, ensure you set a `siteUrl`
136 | openSearch: {
137 | siteUrl: 'https://code-notes-example.netlify.app', // required if you want opensearch
138 | siteShortName: 'Gatsby Theme Code Notes Example', // override the default value of 'Search`
139 | siteTags: 'front-end', // optional
140 | siteContact: 'https://twitter.com/MrMartineau', // optional
141 | siteDescription: 'A Gatsby theme for storing your code-related notes', // optional
142 | },
143 | },
144 | },
145 | ],
146 | }
147 | ```
148 |
149 | Add notes to your site by creating `md` or `mdx` files inside `/content/notes`.
150 |
151 | > Note that if you've changed the default `contentPath` in the configuration, you'll want to add your markdown files in the directory specified by that path.
152 |
153 | ### Note frontmatter
154 |
155 | Frontmatter information (written in YAML) can be used to add metadata and extra information for your notes
156 |
157 | Only the `title` field is required, the rest are optional.
158 |
159 | ```yaml
160 | ---
161 | title: Note metadata
162 | emoji: 😃
163 | tags:
164 | - metadata
165 | - info
166 | link: https://zander.wtf
167 | ---
168 |
169 | ```
170 |
171 | #### Link
172 |
173 | The `link` item is used to display a link that is related to the note itself. It will appear below the title if.
174 |
175 | #### Emoji
176 |
177 | The `emoji` frontmatter item will add an emoji beside the title on listing views and above the title on individual note pages
178 |
179 | #### Tags
180 |
181 | The `tags` array frontmatter item allows you to add as many tags to a note as you'd like.
182 |
183 | #### Dates
184 |
185 | The `modified` frontmatter item allows you set a date for your note. This means they can then be sorted (ascending & descending) when viewed in the note list pages. This was introduced in v2.0.0.
186 |
187 | The `created` frontmatter item works in a similar way, but it is not being used at the moment so it can be ommitted.
188 |
189 | ##### 1. Add new `modified` key to your YAML frontmatter
190 |
191 | This will mean that you have to update all your notes with a timestamp.
192 |
193 | ```yaml
194 | ---
195 | title: Storybook
196 | tags:
197 | - testing
198 | emoji: 📖
199 | link: 'https://storybook.js.org'
200 | created: 2020-02-27T23:02:00.000Z # this is not used by the theme at the moment
201 | modified: 2021-01-16T10:31:32.000Z
202 |
203 | # any valid ISO timestamp should work, like this:
204 | # modified: 2021-01-16
205 | ---
206 |
207 | ```
208 |
209 | If you have many notes and want to speed up adding all those timestamps, I created an npm package ([`frontmatter-date-setter`](https://github.com/mrmartineau/frontmatter-date-setter)) to automate it based on your last git or file modification dates.
210 |
211 | Use the `frontmatter-date-setter` (or `fds`) CLI like so: (where `notes` is the directory of all your notes)
212 |
213 | ```sh
214 | fds --directory=notes --debug
215 | ```
216 |
217 | The package does have a few issues that I'd like to improve. For example, it will convert most emojis to unicode strings, and will format other parts of your frontmatter. So take care when you run it.
218 |
219 | ##### 2. Set `showDate: true` in `gatsby-config.js`
220 |
221 | Setting this value in this plugin's config renders the interface to switch to date sorting as well as showing the date in other parts of the interface.
222 |
223 | ### Advanced usage
224 |
225 | #### PWA
226 |
227 | Turn your code notes into a PWA using [this extra config](https://github.com/mrmartineau/notes.zander.wtf/blob/master/gatsby-config.js#L20-L38). This requires `gatsby-plugin-manifest` and `gatsby-plugin-offline`.
228 |
229 | ```js
230 | // gatsby-config.js
231 | {
232 | resolve: `gatsby-plugin-manifest`,
233 | options: {
234 | name: `Zander's Code Notes`,
235 | short_name: `CodeNotes`,
236 | description: `Notes on code. My memory bank.`,
237 | start_url: `/`,
238 | background_color: `hsl(210, 38%, 95%)`,
239 | theme_color: `hsl(345, 100%, 69%)`,
240 | display: `standalone`,
241 | icon: `static/logo.png`,
242 | showDate: true,
243 | },
244 | },
245 | {
246 | resolve: `gatsby-plugin-offline`,
247 | options: {
248 | precachePages: [`/*`, `/tag/*`],
249 | },
250 | },
251 | ```
252 |
253 | ---
254 |
255 | ## License
256 |
257 | [MIT](https://choosealicense.com/licenses/mit/) © [Zander Martineau](https://zander.wtf)
258 |
259 | > Made by Zander • [zander.wtf](https://zander.wtf) • [GitHub](https://github.com/mrmartineau/) • [Twitter](https://twitter.com/mrmartineau/)
260 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrmartineau/gatsby-theme-code-notes/40dfa0e379e23a536608447879aed685ecac6b68/assets/logo.png
--------------------------------------------------------------------------------
/assets/opengraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrmartineau/gatsby-theme-code-notes/40dfa0e379e23a536608447879aed685ecac6b68/assets/opengraph.png
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Gatsby Theme Minimal Example
2 |
3 | A usage of
4 | [gatsby-theme-minimal](https://github.com/ChristopherBiscardi/gatsby-theme-minimal)
5 | that does nothing but use the theme. As a result you will see `Error: Missing resources for /` when navigating to `localhost:8000`. To get
6 | rid of that, create a page in `src/pages/index.js`.
7 |
--------------------------------------------------------------------------------
/example/code-notes/annotations.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Annotations
3 | created: 2020-07-15T11:36:18.000Z
4 | modified: 2020-07-15T12:12:28.000Z
5 | ---
6 |
7 | Note annotations are made possible using a React port of [Rough Notation](https://roughnotation.com). Annotations can be added by wrapping your text with one of the components provided in your notes.
8 |
9 | Annotation defaults have been defined, but you can ovverride them if you want. See all the options [here](https://github.com/linkstrifer/react-rough-notation#props).
10 |
11 | ```mdx
12 | I want to highlight some text
13 | ```
14 |
15 | ## Highlight
16 |
17 | Himenaeos in a ante pretium cubilia ut nisl dictumst ultrices massa, elementum iaculis varius ad cursus vehicula torquent eros penatibus , rhoncus porttitor senectus est consequat vitae tempus mollis mus. Posuere sociis morbi suspendisse aliquam arcu convallis ac montes himenaeos, quisque iaculis eget lobortis auctor tempus feugiat fames integer, platea lacinia dignissim egestas nunc orci ad ipsum .
18 |
19 | ```mdx
20 | I want to highlight some text
21 | ```
22 |
23 | ## Underline
24 |
25 | Habitant ipsum lorem penatibus condimentum orci curabitur ligula tempus aenean dignissim adipiscing interdum mi, quis sapien convallis nisl vel dolor lacus pharetra montes taciti, nibh venenatis consectetur dictumst maecenas cum morbi senectus curae imperdiet massa platea.
26 |
27 | ```mdx
28 | I want to underline some text
29 | ```
30 |
31 | ## Box
32 |
33 | Eros scelerisque erat mauris euismod tincidunt euismod sit cubilia ornare fringilla, congue risus mauris nostra lobortis consequat torquent suscipit, montes in non himenaeos adipiscing aliquam.
34 |
35 | ```mdx
36 | I want to put a box around some text
37 | ```
38 |
39 | ## Circle
40 |
41 | Ante et dis platea fusce sapien faucibus nullam , eget dictum dui mus nunc purus integer facilisis, facilisi pellentesque cubilia iaculis augue arcu.
42 |
43 | ```mdx
44 | I want to put a circle around some text
45 | ```
46 |
47 | ## StrikeThrough
48 |
49 | Netus dolor aliquam mauris sociis imperdiet commodo taciti, odio nullam vitae vulputate ullamcorper phasellus cubilia fringilla, adipiscing in pharetra per tincidunt consectetur.
50 |
51 | ```mdx
52 | I want to strike-through some text
53 | ```
54 |
55 | ## CrossedOff
56 |
57 | Habitant ligula pharetra elementum pellentesque lacus ante id ipsum imperdiet, fermentum rhoncus integer erat egestas blandit risus odio dictum, dui mattis nullam nisl arcu ridiculus a penatibus.
58 |
59 | ```mdx
60 | I want to cross-off some text
61 | ```
62 |
--------------------------------------------------------------------------------
/example/code-notes/deeply/nested/note.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Notes in subfolders
3 | created: 2020-06-16T11:30:46.000Z
4 | modified: 2020-06-16T11:30:46.000Z
5 | ---
6 |
7 | Notes can reside anywhere in the content directory's tree. This note is located at `/deeply/nested/note.md`
8 |
--------------------------------------------------------------------------------
/example/code-notes/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrmartineau/gatsby-theme-code-notes/40dfa0e379e23a536608447879aed685ecac6b68/example/code-notes/logo.png
--------------------------------------------------------------------------------
/example/code-notes/markdown-features.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown features
3 | tags:
4 | - markdown
5 | created: 2020-03-20T11:04:49.000Z
6 | modified: 2020-06-22T11:55:48.000Z
7 | ---
8 |
9 | > This theme adds a few additional features to standard markdown.
10 |
11 | ## Images
12 |
13 | 
14 | 
15 |
16 | Embed images using the usual markdown syntax.
17 |
18 | ```md
19 | 
20 | ```
21 |
22 | ## Fenced code blocks
23 |
24 | Like you use with GitHub, e.g.
25 |
26 | ```js
27 | const variable = 42
28 | ```
29 |
30 | ### Highlighting lines in code blocks
31 |
32 | To highlight lines, wrap line with this comment before: `// highlight-start` and this after `// highlight-end`. **Ensure that these comments are not indented.**
33 |
34 | ```css
35 | .grid {
36 | // highlight-start
37 | display: grid;
38 | grid-gap: 30px;
39 | // highlight-end
40 | grid-template-columns: repeat(auto-fill, 112px);
41 | /* or this */
42 | grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
43 | }
44 | ```
45 |
46 | ```css
47 | .grid {
48 | // highlight-start
49 | display: grid;
50 | grid-gap: 30px;
51 | // highlight-end
52 | grid-template-columns: repeat(auto-fill, 112px);
53 | /* or this */
54 | grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
55 | }
56 | ```
57 |
58 | ## Emoji short codes
59 |
60 | Like this: :joy: :eggplant:
61 |
62 | ```md
63 | Like this: :joy: :eggplant:
64 | ```
65 |
66 | ## Details/Summary
67 |
68 |
69 | Open example
70 |
71 | Tada! :tada:
72 |
73 | ```html
74 |
75 | Open example
76 |
77 | Tada! :tada:
78 |
79 | ```
80 |
81 |
82 |
83 | ## Tables
84 |
85 | Tables are responsive by default. If you need to limit line length for a cell, add a ` ` tag to break the lines.
86 |
87 | | Tables | Are | Cool |
88 | | ------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------- |
89 | | This is a row | with some | content |
90 | | This is another row | with a lot more content. Nullam netus eu fringilla turpis parturient dignissim | Velit ut mauris penatibus turpis commodo consectetur |
91 |
92 | ## Link truncation
93 |
94 | This uses [remark-truncate-links](https://github.com/GaiAma/Coding4GaiAma/tree/master/packages/remark-truncate-links) to truncate links. e.g. https://github.com/mrmartineau/gatsby-theme-code-notes
95 |
--------------------------------------------------------------------------------
/example/code-notes/mdx.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: MDX example
3 | tags:
4 | - mdx
5 | emoji: 👩🚀
6 | created: 2020-03-13T14:16:50.000Z
7 | modified: 2020-03-20T11:04:49.000Z
8 | ---
9 |
10 | import { Button } from 'theme-ui'
11 |
12 | This example uses MDX..
13 |
14 | ## React component
15 |
16 | alert('You clicked me')}>Click me
17 |
18 | ```jsx
19 | import { Button } from 'theme-ui'
20 |
21 | ; alert('You clicked me')}>Click me
22 | ```
23 |
24 | ### JSX
25 |
26 |
27 | This is JSX
28 |
29 |
30 | ```jsx
31 |
32 | This is JSX
33 |
34 | ```
35 |
36 | ## `iframe`
37 |
38 |
54 |
--------------------------------------------------------------------------------
/example/code-notes/note-frontmatter.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Note frontmatter
3 | emoji: 😃
4 | tags:
5 | - metadata
6 | link: 'https://zander.wtf'
7 | created: 2020-05-11T09:59:36.000Z
8 | modified: 2020-06-11T10:08:56.000Z
9 | ---
10 |
11 | Frontmatter information (written in YAML) can be used to add metadata and extra information for your notes
12 |
13 | This is the frontmatter for this note:
14 |
15 | ```yaml
16 | ---
17 | title: Note metadata
18 | emoji: 😃
19 | tags:
20 | - metadata
21 | link: https://zander.wtf
22 | ---
23 |
24 | ```
25 |
26 | ## Link
27 |
28 | The `link` item is used to display a link that is related to the note itself. It will appear below the title if.
29 |
30 | ## Emoji
31 |
32 | The `emoji` frontmatter item will add an emoji beside the title on listing views and above the title on individual note pages
33 |
34 | ## Tags
35 |
36 | The `tags` array frontmatter item allows you to add as many tags to a note as you'd like.
37 |
--------------------------------------------------------------------------------
/example/code-notes/opengraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrmartineau/gatsby-theme-code-notes/40dfa0e379e23a536608447879aed685ecac6b68/example/code-notes/opengraph.png
--------------------------------------------------------------------------------
/example/code-notes/syntax-highlighting.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Syntax highlighting examples
3 | tags:
4 | - html
5 | - css
6 | - javascript
7 | - Javascript
8 | - JavaScript
9 | - yaml
10 | emoji: 🌭
11 | created: 2020-03-13T14:16:50.000Z
12 | modified: 2020-06-11
13 | ---
14 |
15 | Here is some `inline code`..
16 |
17 | ## CSS
18 |
19 | ```css
20 | .grid {
21 | display: grid;
22 | grid-gap: 30px;
23 | grid-template-columns: repeat(auto-fill, 112px);
24 | /* or this */
25 | grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
26 | }
27 |
28 | /* To select modern Grid browsers and IE 11 */
29 | @supports (display: grid) {
30 | grid-gap: 20px;
31 | }
32 | ```
33 |
34 | ### Another CSS item
35 |
36 | ```css
37 | @font-face {
38 | font-family: 'MyWebFont';
39 | src: url('myfont.woff2') format('woff2'), url('myfont.woff') format('woff');
40 | font-display: 'swap';
41 | }
42 | ```
43 |
44 | ### Another item
45 |
46 | blah blah blah
47 | blah blah blah
48 | blah blah blah
49 |
50 | #### Even more nested item
51 |
52 | blah blah blah
53 | blah blah blah
54 | blah blah blah
55 |
56 | ## JavaScript
57 |
58 | ```js
59 | import { graphql, useStaticQuery } from 'gatsby'
60 |
61 | const testVar = '22'
62 |
63 | export const useAllTags = () => {
64 | const data = useStaticQuery(graphql`
65 | {
66 | allMdx {
67 | tags: group(field: frontmatter___tags) {
68 | tag: fieldValue
69 | totalCount
70 | }
71 | }
72 | }
73 | `)
74 |
75 | return data
76 | }
77 |
78 | const three = [1, 2, 3]
79 | const doubled = three.map((item) => {
80 | return item * 2
81 | })
82 | console.log(three === doubled, doubled) // false, [2, 4, 6]
83 | ```
84 |
85 | ## TypeScript
86 |
87 | ```ts
88 | // Convert specified properties of T to be optional
89 | type WithOptional = Omit & Partial>
90 |
91 | type NewType = WithOptional
92 | ```
93 |
94 | ## JSX
95 |
96 | ```jsx
97 | import React from 'react'
98 |
99 | // We again use a simple, functional component.
100 | const OurComponent = ({ query, results, clearQuery }) => (
101 |
102 | query: {query}
103 |
Clear
104 |
105 | {results.map((result) => (
106 |
107 |
108 | {result.title}
109 |
110 | ))}
111 |
112 |
113 | )
114 | ```
115 |
116 | ## HTML
117 |
118 | ```html
119 |
120 |
121 |
122 |
126 |
130 |
131 |
132 | ```
133 |
134 | ## Shell
135 |
136 | ```sh
137 | git branch --merged | egrep -v "(^\*|master|develop)"
138 | ```
139 |
140 | ## YAML
141 |
142 | ```yml
143 | version: 2
144 |
145 | references:
146 | npm_auth: &npm_auth
147 | run:
148 | name: Authenticate with registry
149 | command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
150 |
151 | jobs:
152 | build:
153 | docker:
154 | - image: circleci/node:13.1.0-stretch
155 | steps:
156 | - checkout
157 | - *npm_auth
158 | - run:
159 | name: install
160 | command: yarn install
161 | - run:
162 | name: build
163 | command: yarn build
164 | - run:
165 | name: test
166 | command: yarn test
167 |
168 | workflows:
169 | version: 2
170 | build-test:
171 | jobs:
172 | - build
173 | ```
174 |
--------------------------------------------------------------------------------
/example/code-notes/untagged.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Untagged
3 | created: 2020-02-09T21:18:32.000Z
4 | modified: 2020-03-24T20:49:43.000Z
5 | ---
6 |
7 | This is an untagged note. If there are any notes that are untagged, a new navigation item ('Untagged') will be added.
8 |
--------------------------------------------------------------------------------
/example/code-notes/wikilinks.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Wiki Links
3 | emoji: ⛓
4 | tags:
5 | - markdown
6 | created: 2021-04-02T11:04:49.000Z
7 | modified: 2021-04-02T11:55:48.000Z
8 | ---
9 |
10 | ## Link your notes
11 |
12 | Make connections between your notes by using `[[note-name]]`. This allows you to easily surf between your connected notes!
13 |
14 | ## Back Links
15 |
16 | Links all the notes that references the current note
17 |
18 | ### Check out other notes
19 |
20 | - [[markdown-features]]
21 | - [[note-frontmatter]]
22 |
--------------------------------------------------------------------------------
/example/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: 'Code notes',
4 | description: 'A Gatsby theme for storing your code-related notes',
5 | keywords: [],
6 | },
7 | plugins: [
8 | {
9 | resolve: 'gatsby-theme-code-notes',
10 | options: {
11 | contentPath: 'code-notes',
12 | basePath: '/',
13 | gitRepoContentPath:
14 | 'https://github.com/mrmartineau/gatsby-theme-code-notes/tree/master/example/code-notes/',
15 | showDescriptionInSidebar: true,
16 | showThemeInfo: true,
17 | logo:
18 | 'https://raw.githubusercontent.com/mrmartineau/gatsby-theme-code-notes/master/assets/logo.png',
19 | openSearch: {
20 | siteShortName: `Gatsby Theme Code Notes Example`,
21 | siteUrl: 'https://code-notes-example.netlify.app',
22 | siteTags: 'front-end',
23 | siteContact: 'https://twitter.com/MrMartineau',
24 | siteDescription: 'A Gatsby theme for storing your code-related notes',
25 | },
26 | showDate: true,
27 | },
28 | },
29 | ],
30 | }
31 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "example",
4 | "version": "1.0.0",
5 | "main": "index.js",
6 | "author": {
7 | "name": "Zander Martineau",
8 | "url": "https://zander.wtf"
9 | },
10 | "license": "MIT",
11 | "scripts": {
12 | "build": "gatsby build",
13 | "clean": "gatsby clean",
14 | "dev": "gatsby develop",
15 | "start": "gatsby serve"
16 | },
17 | "dependencies": {
18 | "gatsby": "^3.3.1",
19 | "gatsby-theme-code-notes": "*",
20 | "react": "^17.0.2",
21 | "react-dom": "^17.0.2"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "esModuleInterop": true,
5 | "forceConsistentCasingInFileNames": true,
6 | "isolatedModules": true,
7 | "jsx": "preserve",
8 | "lib": ["dom", "dom.iterable", "esnext"],
9 | "module": "esnext",
10 | "moduleResolution": "node",
11 | "noEmit": true,
12 | "resolveJsonModule": true,
13 | "skipLibCheck": true,
14 | "strict": false,
15 | "target": "es5"
16 | },
17 | "exclude": [
18 | "node_modules",
19 | "./.storybook/**/*",
20 | "./cypress/**/*",
21 | "./static/scripts/**/*"
22 | ],
23 | "include": ["src/**/*.ts", "src/**/*.tsx", "global.d.ts"]
24 | }
25 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/.release-it.json:
--------------------------------------------------------------------------------
1 | {
2 | "git": {
3 | "commitMessage": "chore: release v${version}"
4 | },
5 | "github": {
6 | "release": true
7 | },
8 | "npm": {
9 | "publish": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/README.md:
--------------------------------------------------------------------------------
1 |
33 |
34 | ## Features
35 |
36 | - Notes can:
37 | - be written using Markdown (`.md`) or [MDX](https://mdxjs.com/) (`.mdx`)
38 | - have zero, one or many tags. See an example [here](https://code-notes-example.netlify.app/syntax-highlighting)
39 | - have associated emojis 👏
40 | - be nested in subfolders so you can organise them how you like
41 | - sketchy annotations (highlights, strike-thoughs etc). Find out more [here](https://code-notes-example.netlify.app/annotations)
42 | - Extra markdown features have also been added. Find out more [here](https://code-notes-example.netlify.app/markdown-features)
43 | - Note search powered by the super-fast [Flexsearch](https://github.com/nextapps-de/flexsearch)
44 |
45 | ## Installation
46 |
47 | ```sh
48 | mkdir my-site
49 | cd my-site
50 | yarn init
51 |
52 | # install gatsby-theme-code-notes and it's dependencies
53 | yarn add gatsby-theme-code-notes gatsby react react-dom
54 |
55 | # or
56 |
57 | npm install gatsby-theme-code-notes gatsby react react-dom
58 | ```
59 |
60 | ### Using the Gatsby starter
61 |
62 | #### Step 1: Starter installation
63 |
64 | Source code for the starter can be found at: https://github.com/MrMartineau/gatsby-starter-code-notes
65 |
66 | ##### With `gatsby-cli`:
67 |
68 | ```sh
69 | gatsby new code-notes https://github.com/MrMartineau/gatsby-starter-code-notes
70 | ```
71 |
72 | ##### With `git clone`:
73 |
74 | ```sh
75 | git clone git@github.com:MrMartineau/gatsby-starter-code-notes.git
76 |
77 | cd code-notes
78 |
79 | yarn
80 | ```
81 |
82 | #### Step 2: Develop & Build
83 |
84 | Once installed or cloned locally and all packages are installed you can begin developing your site.
85 |
86 | ```sh
87 | # Run localhost
88 | yarn dev
89 |
90 | # Build your Gatsby site
91 | yarn build
92 | ```
93 |
94 | ## Usage
95 |
96 | ### Theme Options
97 |
98 | | Key | Default value | Description |
99 | | -------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100 | | `basePath` | `/` | Root url for all notes pages |
101 | | `contentPath` | `/content/notes` | Location of notes content |
102 | | `logo` | `''` (empty string) | Path to your site's logo. Will be used as the `src` attribute for an image |
103 | | `showDescriptionInSidebar` | `true` | Show `config.site.description` in the sidebar |
104 | | `showDate` | `false` | Show the note's modified date |
105 | | `gitRepoContentPath` | `''` | Set the location for your notes if they're hosted online, e.g. your git repo. This will show a "Edit this page" link underneath each note |
106 | | `showThemeInfo` | `true` | Show info about this Gatsby theme |
107 | | `mdxOtherwiseConfigured` | `true` | Configure `gatsby-plugin-mdx`. Note that most sites will not need to use this flag. If your site has already configured `gatsby-plugin-mdx` separately, set this flag `false`. |
108 | | `flexSearchEngineOptions` | `{ encode: 'icase', tokenize: 'forward', resolution: 9 }` | Configure FlexSearch's index method. The default value uses FlexSearch's `default` preset. Find out your other options [here](https://github.com/nextapps-de/flexsearch#presets). |
109 | | `openSearch` | `{ }` | Configure the `opensearch.xml` file contents. This file is generated during the build process. If you want to add opensearch support, ensure you set a `siteUrl` in the config. See [below](#example-usage) for more information. |
110 |
111 | ### Example usage
112 |
113 | This example overrides some of the theme defaults and shows the various options for the opensearch config.
114 |
115 | ```js
116 | // gatsby-config.js
117 | module.exports = {
118 | plugins: [
119 | {
120 | resolve: `gatsby-theme-code-notes`,
121 | options: {
122 | basePath: '/',
123 | contentPath: '/content/notes',
124 | gitRepoContentPath:
125 | 'https://github.com/mrmartineau/gatsby-theme-code-notes/tree/master/example/code-notes/',
126 | showDescriptionInSidebar: true,
127 | showThemeInfo: false,
128 | logo: 'https://brand.zander.wtf/Avatar.png',
129 | showDate: true,
130 |
131 | // Opensearch is used to enhance the search on your site.
132 | // If you want to add it, ensure you set a `siteUrl`
133 | openSearch: {
134 | siteUrl: 'https://code-notes-example.netlify.app', // required if you want opensearch
135 | siteShortName: 'Gatsby Theme Code Notes Example', // override the default value of 'Search`
136 | siteTags: 'front-end', // optional
137 | siteContact: 'https://twitter.com/MrMartineau', // optional
138 | siteDescription: 'A Gatsby theme for storing your code-related notes', // optional
139 | },
140 | },
141 | },
142 | ],
143 | }
144 | ```
145 |
146 | Add notes to your site by creating `md` or `mdx` files inside `/content/notes`.
147 |
148 | > Note that if you've changed the default `contentPath` in the configuration, you'll want to add your markdown files in the directory specified by that path.
149 |
150 | ### Note frontmatter
151 |
152 | Frontmatter information (written in YAML) can be used to add metadata and extra information for your notes
153 |
154 | Only the `title` field is required, the rest are optional.
155 |
156 | ```yaml
157 | ---
158 | title: Note metadata
159 | emoji: 😃
160 | tags:
161 | - metadata
162 | - info
163 | link: https://zander.wtf
164 | ---
165 |
166 | ```
167 |
168 | #### Link
169 |
170 | The `link` item is used to display a link that is related to the note itself. It will appear below the title if.
171 |
172 | #### Emoji
173 |
174 | The `emoji` frontmatter item will add an emoji beside the title on listing views and above the title on individual note pages
175 |
176 | #### Tags
177 |
178 | The `tags` array frontmatter item allows you to add as many tags to a note as you'd like.
179 |
180 | #### Dates
181 |
182 | The `modified` frontmatter item allows you set a date for your note. This means they can then be sorted (ascending & descending) when viewed in the note list pages. This was introduced in v2.0.0.
183 |
184 | The `created` frontmatter item works in a similar way, but it is not being used at the moment so it can be ommitted.
185 |
186 | ##### 1. Add new `modified` key to your YAML frontmatter
187 |
188 | This will mean that you have to update all your notes with a timestamp.
189 |
190 | ```yaml
191 | ---
192 | title: Storybook
193 | tags:
194 | - testing
195 | emoji: 📖
196 | link: 'https://storybook.js.org'
197 | created: 2020-02-27T23:02:00.000Z # this is not used by the theme at the moment
198 | modified: 2021-01-16T10:31:32.000Z
199 |
200 | # any valid ISO timestamp should work, like this:
201 | # modified: 2021-01-16
202 | ---
203 |
204 | ```
205 |
206 | If you have many notes and want to speed up adding all those timestamps, I created an npm package ([`frontmatter-date-setter`](https://github.com/mrmartineau/frontmatter-date-setter)) to automate it based on your last git or file modification dates.
207 |
208 | Use the `frontmatter-date-setter` (or `fds`) CLI like so: (where `notes` is the directory of all your notes)
209 |
210 | ```sh
211 | fds --directory=notes --debug
212 | ```
213 |
214 | The package does have a few issues that I'd like to improve. For example, it will convert most emojis to unicode strings, and will format other parts of your frontmatter. So take care when you run it.
215 |
216 | ##### 2. Set `showDate: true` in `gatsby-config.js`
217 |
218 | Setting this value in this plugin's config renders the interface to switch to date sorting as well as showing the date in other parts of the interface.
219 |
220 | ### Advanced usage
221 |
222 | #### PWA
223 |
224 | Turn your code notes into a PWA using [this extra config](https://github.com/mrmartineau/notes.zander.wtf/blob/master/gatsby-config.js#L20-L38). This requires `gatsby-plugin-manifest` and `gatsby-plugin-offline`.
225 |
226 | ```js
227 | // gatsby-config.js
228 | {
229 | resolve: `gatsby-plugin-manifest`,
230 | options: {
231 | name: `Zander's Code Notes`,
232 | short_name: `CodeNotes`,
233 | description: `Notes on code. My memory bank.`,
234 | start_url: `/`,
235 | background_color: `hsl(210, 38%, 95%)`,
236 | theme_color: `hsl(345, 100%, 69%)`,
237 | display: `standalone`,
238 | icon: `static/logo.png`,
239 | showDate: true,
240 | },
241 | },
242 | {
243 | resolve: `gatsby-plugin-offline`,
244 | options: {
245 | precachePages: [`/*`, `/tag/*`],
246 | },
247 | },
248 | ```
249 |
250 | ---
251 |
252 | ## License
253 |
254 | [MIT](https://choosealicense.com/licenses/mit/) © [Zander Martineau](https://zander.wtf)
255 |
256 | > Made by Zander • [zander.wtf](https://zander.wtf) • [GitHub](https://github.com/mrmartineau/) • [Twitter](https://twitter.com/mrmartineau/)
257 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/gatsby-browser.js:
--------------------------------------------------------------------------------
1 | import { wrapRootElementComponent } from './src/gatsby/wrapRootElement'
2 |
3 | export const wrapRootElement = wrapRootElementComponent
4 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/gatsby-config.js:
--------------------------------------------------------------------------------
1 | const remarkSlug = require('remark-slug')
2 | const remarkEmoji = require('remark-emoji')
3 | const squeezeParagraphs = require('remark-squeeze-paragraphs')
4 | const remarkTruncateLinks = require('remark-truncate-links').remarkTruncateLinks
5 | const TextCleaner = require('text-cleaner')
6 | const unwrapImages = require('remark-unwrap-images')
7 |
8 | const clean = (string) => {
9 | return TextCleaner(string)
10 | .removeChars({ exclude: '/', replaceWith: ' ' })
11 | .removeStopWords()
12 | .stripHtml()
13 | .condense()
14 | .toLowerCase()
15 | .valueOf()
16 | }
17 |
18 | module.exports = (options) => {
19 | const {
20 | mdxOtherwiseConfigured = true,
21 | gitRepoContentPath = '',
22 | showThemeInfo = true,
23 | showDescriptionInSidebar = true,
24 | logo = '',
25 | flexSearchEngineOptions = {
26 | encode: 'icase',
27 | tokenize: 'forward',
28 | resolution: 9,
29 | },
30 | openSearch = {},
31 | showDate = false,
32 | basePath = '/',
33 | } = options
34 |
35 | return {
36 | siteMetadata: {
37 | title: `Code Notes`,
38 | description: `A Gatsby theme for your code-related notes`,
39 | gitRepoContentPath,
40 | showThemeInfo,
41 | showDescriptionInSidebar,
42 | logo,
43 | openSearch,
44 | showDate,
45 | basePath,
46 | },
47 | plugins: [
48 | 'gatsby-plugin-typescript',
49 | `gatsby-plugin-sharp`,
50 | `gatsby-transformer-sharp`,
51 | `gatsby-plugin-catch-links`,
52 | {
53 | resolve: `gatsby-source-filesystem`,
54 | options: {
55 | path: options.contentPath || `content/notes`,
56 | name: options.contentPath || `content/notes`,
57 | },
58 | },
59 | mdxOtherwiseConfigured && {
60 | resolve: `gatsby-plugin-mdx`,
61 | options: {
62 | extensions: [`.md`, `.mdx`],
63 | gatsbyRemarkPlugins: [
64 | {
65 | resolve: 'gatsby-remark-images',
66 | options: {
67 | backgroundColor: 'none',
68 | maxWidth: 900,
69 | linkImagesToOriginal: false,
70 | disableBgImage: true,
71 | wrapperStyle: `margin: 1.5rem 0;`,
72 | },
73 | },
74 | {
75 | resolve: 'gatsby-remark-double-brackets-link',
76 | options: {
77 | titleToURLPath: `${__dirname}/src/utils/resolve-url.js`,
78 | stripBrackets: true,
79 | },
80 | },
81 | ],
82 | remarkPlugins: [
83 | remarkSlug,
84 | remarkEmoji,
85 | squeezeParagraphs,
86 | [remarkTruncateLinks, { style: 'smart' }],
87 | unwrapImages,
88 | ],
89 | },
90 | },
91 | `gatsby-plugin-redirects`,
92 | `gatsby-plugin-react-helmet`,
93 | `gatsby-plugin-theme-ui`,
94 | {
95 | resolve: 'gatsby-plugin-local-search',
96 | options: {
97 | name: 'notes',
98 | engine: 'flexsearch',
99 | engineOptions: flexSearchEngineOptions,
100 | query: `{
101 | allNotes: allMdx {
102 | edges {
103 | node {
104 | id
105 | frontmatter {
106 | title
107 | emoji
108 | tags
109 | }
110 | fields {
111 | slug
112 | }
113 | rawBody
114 | }
115 | }
116 | }
117 | }`,
118 | ref: 'id',
119 | index: ['title', 'body', 'tagsJoint'],
120 | store: ['id', 'slug', 'title', 'body', 'tags', 'emoji'],
121 | normalizer: ({ data }) =>
122 | data.allNotes.edges.map(({ node }) => {
123 | return {
124 | id: node.id,
125 | slug: node.fields.slug,
126 | title: node.frontmatter.title,
127 | body: clean(node.rawBody),
128 | emoji: node.frontmatter.emoji,
129 | tags: node.frontmatter.tags,
130 | tagsJoint:
131 | node.frontmatter.tags &&
132 | node.frontmatter.tags.join().replace(/,/gi, ' '),
133 | }
134 | }),
135 | },
136 | },
137 | {
138 | resolve: `gatsby-transformer-markdown-references`,
139 | options: {
140 | types: ['Mdx'],
141 | },
142 | },
143 | ].filter(Boolean),
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/gatsby-node.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 | const mkdirp = require('mkdirp')
4 | const slugify = require('@alexcarpenter/slugify')
5 | const { createFilePath } = require(`gatsby-source-filesystem`)
6 | const createOpenSearchFile = require('./src/utils/createOpenSearch')
7 |
8 | const DEFAULT_BASE_PATH = '/'
9 |
10 | const getBasePath = (bp = DEFAULT_BASE_PATH) => {
11 | if (bp === '' || bp === '.' || bp === './') {
12 | return DEFAULT_BASE_PATH
13 | } else {
14 | return bp
15 | }
16 | }
17 |
18 | exports.onPreBootstrap = ({ store, reporter }, themeOptions) => {
19 | const { program } = store.getState()
20 | const contentPath = themeOptions.contentPath || `content/notes`
21 | const dirs = [path.join(program.directory, contentPath)]
22 | dirs.forEach((dir) => {
23 | if (!fs.existsSync(dir)) {
24 | reporter.log(`Initializing ${dir} directory`)
25 | mkdirp.sync(dir)
26 | }
27 | })
28 | }
29 |
30 | exports.onPreExtractQueries = ({ reporter }, themeOptions) => {
31 | if (themeOptions.openSearch && themeOptions.openSearch.siteUrl) {
32 | const filePath = path.join('public', 'opensearch.xml')
33 | fs.writeFile(
34 | filePath,
35 | createOpenSearchFile(themeOptions.openSearch),
36 | (err) => {
37 | if (err) throw err
38 | reporter.log('The opensearch.xml file has been created')
39 | }
40 | )
41 | }
42 | }
43 |
44 | exports.createPages = async ({ graphql, actions }, options) => {
45 | const { createPage } = actions
46 | const basePath = getBasePath(options.basePath)
47 |
48 | const mdxDocs = await graphql(
49 | `
50 | {
51 | allNotes: allMdx {
52 | edges {
53 | node {
54 | id
55 | frontmatter {
56 | title
57 | tags
58 | }
59 | fields {
60 | slug
61 | }
62 | }
63 | }
64 |
65 | tags: group(field: frontmatter___tags) {
66 | tag: fieldValue
67 | totalCount
68 | }
69 | }
70 |
71 | untagged: allMdx(filter: { frontmatter: { tags: { eq: null } } }) {
72 | edges {
73 | node {
74 | id
75 | }
76 | }
77 | }
78 | }
79 | `
80 | )
81 |
82 | if (mdxDocs.errors) {
83 | throw mdxDocs.errors
84 | }
85 |
86 | const { allNotes, untagged } = mdxDocs.data
87 |
88 | const globalTagsList = allNotes.tags
89 | const notesData = allNotes.edges
90 | const hasUntagged = !!untagged.edges.length
91 | const slugifiedTags = globalTagsList.map((item) => {
92 | return {
93 | ...item,
94 | slug: `/${slugify(item.tag)}`,
95 | path: path.join(basePath, 'tag', slugify(item.tag)),
96 | }
97 | })
98 |
99 | // Create notes pages
100 | notesData.forEach((note, index) => {
101 | const previous =
102 | index === notesData.length - 1 ? null : notesData[index + 1].node
103 | const next = index === 0 ? null : notesData[index - 1].node
104 | const slug = slugify(note.node.fields.slug)
105 | createPage({
106 | path: slug,
107 | component: path.join(__dirname, './src/templates', 'Note.js'),
108 | context: {
109 | id: note.node.id,
110 | previous,
111 | next,
112 | hasUntagged,
113 | basePath,
114 | tags: slugifiedTags,
115 | },
116 | })
117 | })
118 |
119 | // Create the notes landing page
120 | createPage({
121 | path: basePath,
122 | component: path.join(__dirname, './src/templates', 'Notes.js'),
123 | context: {
124 | tags: slugifiedTags,
125 | basePath,
126 | hasUntagged,
127 | },
128 | })
129 |
130 | // Create tag pages
131 | slugifiedTags.forEach((item) => {
132 | createPage({
133 | path: item.path,
134 | component: path.join(__dirname, './src/templates', 'TagPage.js'),
135 | context: {
136 | tag: item.tag,
137 | tags: slugifiedTags,
138 | hasUntagged,
139 | basePath,
140 | },
141 | })
142 | })
143 |
144 | if (hasUntagged) {
145 | createPage({
146 | path: path.join(basePath, 'tag', 'untagged'),
147 | component: path.join(__dirname, './src/templates', 'UntaggedTagPage.js'),
148 | context: {
149 | tag: 'untagged',
150 | tags: slugifiedTags,
151 | hasUntagged,
152 | basePath,
153 | },
154 | })
155 | }
156 |
157 | createPage({
158 | path: path.join('404'),
159 | component: path.join(__dirname, './src/templates', '404.js'),
160 | context: {
161 | tags: slugifiedTags,
162 | hasUntagged,
163 | basePath,
164 | },
165 | })
166 | }
167 |
168 | exports.onCreateNode = async ({ node, actions, getNode }, options) => {
169 | const { createNodeField } = actions
170 |
171 | if (node.internal.type === `Mdx`) {
172 | const slug = createFilePath({
173 | node,
174 | getNode,
175 | trailingSlash: false,
176 | })
177 | const pathSlug = path.join(getBasePath(options.basePath), slug)
178 | createNodeField({
179 | name: `slug`,
180 | node,
181 | value: pathSlug,
182 | })
183 | }
184 | }
185 |
186 | exports.createSchemaCustomization = ({ actions }) => {
187 | const { createTypes } = actions
188 | const typeDefs = `
189 | type OpenSearch {
190 | siteShortName: String
191 | siteUrl: String
192 | siteTags: String
193 | siteContact: String
194 | siteDescription: String
195 | }
196 | type SiteSiteMetadata {
197 | title: String!
198 | description: String!
199 | gitRepoContentPath: String
200 | showThemeInfo: Boolean
201 | showDescriptionInSidebar: Boolean
202 | logo: String
203 | openSearch: OpenSearch
204 | showDate: Boolean
205 | }
206 | `
207 | createTypes(typeDefs)
208 | }
209 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/gatsby-ssr.js:
--------------------------------------------------------------------------------
1 | import { wrapRootElementComponent } from './src/gatsby/wrapRootElement'
2 |
3 | export const wrapRootElement = wrapRootElementComponent
4 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/index.js:
--------------------------------------------------------------------------------
1 | // noop
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-theme-code-notes",
3 | "description": "A Gatsby theme for publishing code-related notes and snippets",
4 | "version": "2.3.0",
5 | "main": "index.js",
6 | "author": {
7 | "name": "Zander Martineau",
8 | "url": "https://zander.wtf"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/mrmartineau/gatsby-theme-code-notes"
13 | },
14 | "bugs": {
15 | "url": "https://github.com/mrmartineau/gatsby-theme-code-notes/issues"
16 | },
17 | "scripts": {
18 | "build": "gatsby build",
19 | "clean": "gatsby clean",
20 | "dev": "gatsby develop",
21 | "release": "dotenv release-it"
22 | },
23 | "license": "MIT",
24 | "keywords": [
25 | "gatsby",
26 | "gatsby-plugin",
27 | "gatsby-theme",
28 | "markdown",
29 | "mdx"
30 | ],
31 | "peerDependencies": {
32 | "gatsby": "^2.28.0 || ^3.0.0",
33 | "react": "^16.13.0 || ^17.0.0",
34 | "react-dom": "^16.13.0 || ^17.0.0"
35 | },
36 | "files": [
37 | "src",
38 | "gatsby-*.js",
39 | "tsconfig.json"
40 | ],
41 | "dependencies": {
42 | "@alexcarpenter/slugify": "^1.0.6",
43 | "@hookit/local-storage": "^0.1.0",
44 | "@mdx-js/mdx": "^1.6.5",
45 | "@mdx-js/react": "^1.6.5",
46 | "@theme-ui/presets": "0.7.3",
47 | "@theme-ui/prism": "0.7.3",
48 | "color-hash": "^2.0.0",
49 | "copee": "^1.0.6",
50 | "gatsby-core-utils": "^2.3.0",
51 | "gatsby-plugin-catch-links": "^3.3.0",
52 | "gatsby-plugin-local-search": "^2.0.1",
53 | "gatsby-plugin-mdx": "^2.3.0",
54 | "gatsby-plugin-meta-redirect": "^1.1.1",
55 | "gatsby-plugin-og-image": "^0.0.1",
56 | "gatsby-plugin-react-helmet": "^4.3.0",
57 | "gatsby-plugin-redirects": "^1.0.0",
58 | "gatsby-plugin-sharp": "^3.3.1",
59 | "gatsby-plugin-theme-ui": "0.7.3",
60 | "gatsby-plugin-typescript": "^3.3.0",
61 | "gatsby-remark-double-brackets-link": "^0.1.8",
62 | "gatsby-remark-images": "^5.0.0",
63 | "gatsby-source-filesystem": "^3.3.0",
64 | "gatsby-transformer-markdown-references": "^0.1.5",
65 | "gatsby-transformer-sharp": "^3.3.0",
66 | "lodash": "^4.17.21",
67 | "mkdirp": "^1.0.3",
68 | "querystring": "^0.2.1",
69 | "react-helmet": "^6.1.0",
70 | "react-icons": "^4.2.0",
71 | "react-rough-notation": "^1.0.0",
72 | "react-use-flexsearch": "^0.1.1",
73 | "remark-emoji": "^2.2.0",
74 | "remark-github": "^10.0.1",
75 | "remark-slug": "^6.0.0",
76 | "remark-squeeze-paragraphs": "^4.0.0",
77 | "remark-truncate-links": "^1.0.3",
78 | "remark-unwrap-images": "^2.0.0",
79 | "text-cleaner": "^1.2.1",
80 | "theme-ui": "0.7.3",
81 | "typescript": "^4.2.4"
82 | },
83 | "devDependencies": {
84 | "@types/node": "^14.14.41",
85 | "@types/react": "^17.0.3",
86 | "@types/react-dom": "^17.0.3",
87 | "@types/react-helmet": "^6.1.1",
88 | "dotenv-cli": "^4.0.0",
89 | "eslint-plugin-react-hooks": "^4.2.0",
90 | "gatsby": "^3.3.1",
91 | "husky": "^6.0.0",
92 | "lint-staged": "^10.5.4",
93 | "prettier": "^2.2.1",
94 | "react": "^17.0.2",
95 | "react-dom": "^17.0.2",
96 | "release-it": "^14.6.1"
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/BackLinks/BackLinks.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Box, Link } from 'theme-ui'
3 |
4 | interface IProps {
5 | references: {
6 | frontmatter: {
7 | title: string
8 | }
9 | slug: string
10 | }[]
11 | }
12 |
13 | export const BackLinks: React.FC = ({ references }) => (
14 |
15 |
19 | Back Links ({references.length})
20 |
21 |
22 | {references.map((ref) => {
23 | return (
24 |
25 |
26 | {ref.frontmatter.title}
27 |
28 |
29 | )
30 | })}
31 |
32 |
33 | )
34 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/BackLinks/index.ts:
--------------------------------------------------------------------------------
1 | export { BackLinks } from './BackLinks'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Contents/Contents.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link, Box } from 'theme-ui'
3 |
4 | const ContentsList = ({ items }) => {
5 | return (
6 |
7 | {items.map((item) => {
8 | return
9 | })}
10 |
11 | )
12 | }
13 |
14 | const ContentsItem = ({ item }) => (
15 |
16 | {item.title}
17 | {item.items && item.items.length && (
18 |
19 | )}
20 |
21 | )
22 |
23 | export const Contents = ({ toc }) => {
24 | if (!toc.items) {
25 | return null
26 | }
27 |
28 | return (
29 |
30 |
34 | On this page
35 |
36 |
37 |
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Contents/index.ts:
--------------------------------------------------------------------------------
1 | export { Contents } from './Contents'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Layout/Layout.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { Fragment, FunctionComponent, useState, useContext } from 'react'
3 | import { Global } from '@emotion/react'
4 | import {
5 | jsx,
6 | css,
7 | Box,
8 | useThemeUI,
9 | MenuButton,
10 | Link,
11 | Text,
12 | Image,
13 | useColorMode,
14 | IconButton,
15 | Container,
16 | Flex,
17 | } from 'theme-ui'
18 | import { Helmet } from 'react-helmet'
19 | import { TagNav } from '../TagNav'
20 | import { useSiteMetadata } from '../../use-site-metadata'
21 | import { SearchContext, SearchInput, SearchResults } from '../Search'
22 |
23 | interface LayoutProps {
24 | activeTag?: string
25 | path?: string
26 | basePath?: string
27 | title?: string
28 | hasUntagged?: boolean
29 | tags: any
30 | }
31 |
32 | export const Layout: FunctionComponent = ({
33 | activeTag,
34 | path,
35 | basePath,
36 | hasUntagged,
37 | title,
38 | tags,
39 | children,
40 | }) => {
41 | const { theme } = useThemeUI()
42 | const {
43 | showThemeInfo,
44 | showDescriptionInSidebar,
45 | description,
46 | logo,
47 | openSearch,
48 | } = useSiteMetadata()
49 | const [navOpen, setNavOpen] = useState(false)
50 | const [colorMode, setColorMode] = useColorMode()
51 | const { query } = useContext(SearchContext)
52 |
53 | return (
54 |
55 |
60 |
61 |
62 | {title}
63 |
64 | {openSearch && openSearch.siteUrl && (
65 |
71 | )}
72 |
73 |
101 |
102 |
125 |
132 |
133 | setNavOpen(!navOpen)}
136 | sx={{
137 | display: ['block', 'none'],
138 | mr: 3,
139 | }}
140 | />
141 |
142 |
147 |
148 |
149 |
150 |
151 | {query ? : children}
152 |
153 | {showThemeInfo && (
154 |
155 | Want to make your own site like this?
156 |
157 | Try{' '}
158 |
159 | gatsby-theme-code-notes
160 | {' '}
161 | by Zander Martineau.
162 |
163 | )}
164 |
165 |
166 |
167 |
181 |
182 | {!!logo && (
183 |
184 |
185 |
186 | )}
187 | {showDescriptionInSidebar && description && (
188 |
189 |
196 | {description}
197 |
198 |
199 | )}
200 |
201 |
202 |
209 |
219 | {
221 | setColorMode(colorMode === 'light' ? 'dark' : 'light')
222 | }}
223 | aria-label="Toggle dark mode"
224 | sx={{
225 | color: 'text',
226 | zIndex: 11,
227 | p: 0,
228 | display: 'block',
229 | mx: 'auto',
230 | transition: 'all 200ms ease-in-out ',
231 | cursor: 'pointer',
232 | '&:hover': {
233 | color: 'primary',
234 | },
235 | }}
236 | >
237 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | )
253 | }
254 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Layout/index.ts:
--------------------------------------------------------------------------------
1 | export { Layout } from './Layout'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NavItem/NavItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react'
2 | import { NavLink, Link } from 'theme-ui'
3 | import { Link as GatsbyLink } from 'gatsby'
4 |
5 | interface NavItemProps {
6 | active?: boolean
7 | to: string
8 | }
9 |
10 | export const NavItem: FunctionComponent = ({
11 | active,
12 | to,
13 | children,
14 | }) => (
15 |
23 | {children}
24 |
25 | )
26 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NavItem/index.ts:
--------------------------------------------------------------------------------
1 | export { NavItem } from './NavItem'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteList/NoteList.tsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment, FunctionComponent } from 'react'
2 | import { Flex } from 'theme-ui'
3 | import { NoteListItem } from '../NoteListItem'
4 | import { SortButton } from './SortButton'
5 | import { useSortableData } from './useSortableData'
6 | import slugify from '@alexcarpenter/slugify'
7 |
8 | interface NoteListProps {
9 | notes: any[]
10 | }
11 |
12 | export const NoteList: FunctionComponent = ({ notes }) => {
13 | const { items, requestSort, sortConfig } = useSortableData(notes, {
14 | key: 'title',
15 | direction: 'ascending',
16 | })
17 |
18 | return (
19 |
20 |
27 |
32 | A-Z
33 |
34 |
39 | Date
40 |
41 |
42 |
43 | {items.map(({ node }) => {
44 | const {
45 | title,
46 | tags,
47 | emoji,
48 | modified,
49 | modifiedTimestamp,
50 | } = node.frontmatter
51 | const slug = `/${slugify(node.fields.slug)}`
52 | return (
53 |
62 | )
63 | })}
64 |
65 | )
66 | }
67 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteList/SortButton.tsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from 'react'
2 | import { Button } from 'theme-ui'
3 | import { BiSortDown, BiSortUp } from 'react-icons/bi'
4 |
5 | const getClassNamesFor = (name, sortConfig) => {
6 | if (!sortConfig) {
7 | return
8 | }
9 | return sortConfig.key === name ? `active ${sortConfig.direction}` : undefined
10 | }
11 |
12 | export const SortButton = ({ requestSort, sortKey, sortConfig, children }) => (
13 | requestSort(sortKey)}
17 | className={getClassNamesFor(sortKey, sortConfig)}
18 | >
19 | {children}
20 | {sortConfig.key === sortKey && (
21 |
22 | {sortConfig.direction === 'descending' ? (
23 |
30 | ) : (
31 |
38 | )}
39 |
40 | )}
41 |
42 | )
43 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteList/index.ts:
--------------------------------------------------------------------------------
1 | export { NoteList } from './NoteList'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteList/useSortableData.ts:
--------------------------------------------------------------------------------
1 | import { useLocalStorage } from '@hookit/local-storage'
2 | import { useMemo } from 'react'
3 |
4 | export const useSortableData = (items, config = null) => {
5 | const [sortConfig, setSortConfig] = useLocalStorage(
6 | 'codeNotesSortConfig',
7 | config
8 | )
9 |
10 | const sortedItems = useMemo(() => {
11 | let sortableItems = [...items]
12 | if (sortConfig !== null) {
13 | sortableItems.sort((a, b) => {
14 | if (
15 | a.node.frontmatter[sortConfig.key]?.toLowerCase() <
16 | b.node.frontmatter[sortConfig.key]?.toLowerCase()
17 | ) {
18 | return sortConfig.direction === 'ascending' ? -1 : 1
19 | }
20 | if (
21 | a.node.frontmatter[sortConfig.key]?.toLowerCase() >
22 | b.node.frontmatter[sortConfig.key]?.toLowerCase()
23 | ) {
24 | return sortConfig.direction === 'ascending' ? 1 : -1
25 | }
26 | return 0
27 | })
28 | }
29 | return sortableItems
30 | }, [items, sortConfig])
31 |
32 | const requestSort = (key) => {
33 | let direction = 'ascending'
34 | if (
35 | sortConfig &&
36 | sortConfig.key === key &&
37 | sortConfig.direction === 'ascending'
38 | ) {
39 | direction = 'descending'
40 | }
41 | setSortConfig({ key, direction })
42 | }
43 |
44 | return { items: sortedItems, requestSort, sortConfig }
45 | }
46 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteListItem/NoteListItem.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { FunctionComponent } from 'react'
3 | import { TagList } from '../TagList'
4 | import { Link as GatsbyLink } from 'gatsby'
5 | import { jsx, Heading, Flex, Box, Link, Text } from 'theme-ui'
6 | import { useSiteMetadata } from '../../use-site-metadata'
7 |
8 | interface NoteListItemProps {
9 | slug: string
10 | title: string
11 | emoji?: string
12 | tags: string[]
13 | onClick?: () => void
14 | dateModified: string
15 | modifiedTimestamp: string
16 | }
17 |
18 | export const NoteListItem: FunctionComponent = ({
19 | slug,
20 | title,
21 | tags,
22 | emoji,
23 | onClick,
24 | dateModified,
25 | modifiedTimestamp,
26 | }) => {
27 | const { showDate } = useSiteMetadata()
28 | const noteEmoji = emoji ?? '🗒'
29 | return (
30 |
31 |
42 |
47 |
48 | {noteEmoji}
49 |
50 | {title}
51 |
52 |
57 | {tags && (
58 |
67 | )}
68 | {showDate && dateModified && modifiedTimestamp && (
69 |
80 | {dateModified}
81 |
82 | )}
83 |
84 |
85 |
86 | )
87 | }
88 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NoteListItem/index.ts:
--------------------------------------------------------------------------------
1 | export { NoteListItem } from './NoteListItem'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NotePage/NotePage.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { FunctionComponent, Fragment, useEffect, useState } from 'react'
3 | import { jsx, Box, Flex, Heading, Link, Text } from 'theme-ui'
4 | import { MDXRenderer } from 'gatsby-plugin-mdx'
5 | import { GoCalendar, GoLink, GoTag } from 'react-icons/go'
6 | import { useSiteMetadata } from '../../use-site-metadata'
7 | import { Contents } from '../Contents'
8 | import { Layout } from '../Layout'
9 | import { TagList } from '../TagList'
10 | import { BackLinks } from '../BackLinks'
11 |
12 | interface NotePageProps {
13 | data: {
14 | mdx: {
15 | frontmatter: {
16 | tags: string[]
17 | title: string
18 | emoji: string
19 | link: string
20 | modified: string
21 | modifiedTimestamp: string
22 | }
23 | references: {
24 | frontmatter: {
25 | title: string
26 | }
27 | slug: string
28 | }[]
29 | body: any
30 | parent: {
31 | relativePath: string
32 | }
33 | tableOfContents: any
34 | }
35 | }
36 | pageContext: {
37 | id: string
38 | previous: boolean
39 | next: boolean
40 | hasUntagged: boolean
41 | basePath?: string
42 | tags: any
43 | }
44 | location: {
45 | pathname: string
46 | }
47 | }
48 |
49 | export const NotePage: FunctionComponent = ({
50 | data,
51 | pageContext,
52 | location,
53 | }) => {
54 | if (!data) {
55 | return null
56 | }
57 | const { showDate } = useSiteMetadata()
58 | const {
59 | frontmatter: { title, tags, emoji, link, modified, modifiedTimestamp },
60 | body,
61 | parent: { relativePath },
62 | tableOfContents,
63 | } = data.mdx
64 |
65 | const { gitRepoContentPath } = useSiteMetadata()
66 | const showMetadata = !!(link || showDate)
67 | const [shortenedLink, setShortenedLink] = useState(link)
68 |
69 | useEffect(() => {
70 | if (link) {
71 | if ('URL' in window) {
72 | const { hostname, pathname } = new URL(link)
73 | setShortenedLink(`${hostname}${pathname}`)
74 | }
75 | }
76 | }, [link])
77 |
78 | return (
79 |
86 |
87 |
96 | {emoji && (
97 |
104 | {emoji}
105 |
106 | )}
107 |
108 |
109 | {title}
110 |
111 |
112 | {showMetadata && (
113 |
119 | {link && (
120 |
121 |
129 |
139 | {shortenedLink}
140 |
141 |
142 | )}
143 | {modifiedTimestamp && modified && (
144 |
148 |
156 | {modified}
157 |
158 | )}
159 |
160 | )}
161 |
162 | {tags && (
163 |
164 |
172 |
173 |
174 | )}
175 |
176 |
177 | {!!data.mdx.references.length && (
178 |
179 | )}
180 |
181 |
182 |
183 | {body}
184 |
185 |
193 | {gitRepoContentPath && (
194 |
198 | Edit this page
199 |
200 | )}
201 |
202 |
203 |
204 | )
205 | }
206 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NotePage/index.ts:
--------------------------------------------------------------------------------
1 | export { NotePage } from './NotePage'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NotesPage/NotesPage.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { jsx, Heading } from 'theme-ui'
3 | import { Fragment } from 'react'
4 | import { NoteList } from '../NoteList'
5 | import { Layout } from '../Layout'
6 | import { useSiteMetadata } from '../../use-site-metadata'
7 | import { TagDot } from '../TagDot'
8 |
9 | export const NotesPage = ({ data, pageContext, location }) => {
10 | const notes = data.allMdx.edges
11 | const { title } = useSiteMetadata()
12 | const siteTitle = title
13 |
14 | return (
15 |
23 | {pageContext.tag && (
24 |
25 | {pageContext.tag !== 'untagged' ? (
26 |
27 | {pageContext.tag}
28 |
29 | ) : (
30 | Untagged Notes
31 | )}
32 |
33 | )}
34 |
35 |
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/NotesPage/index.ts:
--------------------------------------------------------------------------------
1 | export { NotesPage } from './NotesPage'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Rough/Rough.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { RoughNotation } from 'react-rough-notation'
3 | import { useThemeUI } from 'theme-ui'
4 |
5 | export const Underline = (props) => (
6 |
7 | )
8 | export const Box = (props) => {
9 | const { theme } = useThemeUI()
10 | return (
11 |
18 | )
19 | }
20 | export const Circle = (props) => {
21 | const { theme } = useThemeUI()
22 | return (
23 |
30 | )
31 | }
32 | export const Highlight = (props) => {
33 | const { theme } = useThemeUI()
34 | return (
35 |
42 | )
43 | }
44 | export const StrikeThrough = (props) => {
45 | const { theme } = useThemeUI()
46 | return (
47 |
54 | )
55 | }
56 | export const CrossedOff = (props) => {
57 | const { theme } = useThemeUI()
58 | return (
59 |
66 | )
67 | }
68 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Rough/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | Underline,
3 | Box,
4 | Circle,
5 | Highlight,
6 | StrikeThrough,
7 | CrossedOff,
8 | } from './Rough'
9 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Search/SearchInput.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { useContext, useEffect, useRef } from 'react'
3 | import { jsx, Input, Box } from 'theme-ui'
4 | import querystring from 'querystring'
5 | import { SearchContext } from './SearchProvider'
6 | import { GoSearch } from 'react-icons/go'
7 |
8 | export const SearchInput = () => {
9 | const { query, setQuery } = useContext(SearchContext)
10 | const inputEl = useRef(null)
11 |
12 | useEffect(() => {
13 | const searchParts = location.search.split('?')
14 | const searchParams = querystring.parse(searchParts[1])
15 | if (searchParams.search) {
16 | setQuery(searchParams.search)
17 | }
18 | }, [])
19 |
20 | useEffect(() => {
21 | window.addEventListener('keydown', (event) => {
22 | if (event.isComposing || event.keyCode === 191) {
23 | if (inputEl && inputEl.current) {
24 | event.preventDefault()
25 | inputEl.current.focus()
26 | }
27 | }
28 | })
29 |
30 | return () => {
31 | window.removeEventListener('keydown', () => {})
32 | }
33 | }, [])
34 |
35 | return (
36 |
41 |
51 | {
54 | setQuery(event.target.value)
55 | window.history.pushState({}, '', `?search=${event.target.value}`)
56 | }}
57 | aria-label="Search"
58 | placeholder="Search notes"
59 | ref={inputEl}
60 | />
61 |
82 | /
83 |
84 |
85 | )
86 | }
87 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Search/SearchProvider.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState } from 'react'
2 |
3 | interface SearchContextInterface {
4 | query: string
5 | setQuery: (value: string) => void
6 | }
7 |
8 | export const SearchContext = createContext(
9 | {} as SearchContextInterface
10 | )
11 |
12 | export const SearchProvider = ({ children }) => {
13 | const [query, setQuery] = useState('')
14 | return (
15 |
16 | {children}
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Search/SearchResults.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react'
2 | import { useStaticQuery, graphql } from 'gatsby'
3 | import { useFlexSearch } from 'react-use-flexsearch'
4 | import { Box } from 'theme-ui'
5 | import { NoteListItem } from '../NoteListItem'
6 | import { SearchContext } from './SearchProvider'
7 |
8 | export const SearchResults = () => {
9 | const { query, setQuery } = useContext(SearchContext)
10 | const { localSearchNotes } = useStaticQuery(graphql`
11 | query {
12 | localSearchNotes {
13 | index
14 | store
15 | }
16 | }
17 | `)
18 |
19 | const results = useFlexSearch(
20 | query,
21 | localSearchNotes.index,
22 | localSearchNotes.store
23 | )
24 |
25 | return (
26 |
27 | {results.length > 0 ? (
28 | results.map((result) => {
29 | return (
30 | setQuery('')}
37 | dateModified={result.modified}
38 | />
39 | )
40 | })
41 | ) : (
42 |
43 | Zero search results
44 |
45 | )}
46 |
47 | )
48 | }
49 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Search/index.ts:
--------------------------------------------------------------------------------
1 | export { SearchInput } from './SearchInput'
2 | export { SearchResults } from './SearchResults'
3 | export { SearchProvider, SearchContext } from './SearchProvider'
4 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Sidebar/Sidebar.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react'
2 | import { Box, useThemeUI } from 'theme-ui'
3 |
4 | export const Sidebar: FunctionComponent = ({ children }) => {
5 | const { theme } = useThemeUI()
6 | return (
7 |
21 | {children}
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/Sidebar/index.ts:
--------------------------------------------------------------------------------
1 | export { Sidebar } from './Sidebar'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagDot/TagDot.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react'
2 | import { Box } from 'theme-ui'
3 | import slugify from '@alexcarpenter/slugify'
4 | import { getColourFromString } from '../../utils/getColourFromString'
5 |
6 | export const TagDot: FunctionComponent<{ tag?: string; size?: string }> = ({
7 | tag,
8 | size = '10px',
9 | }) => {
10 | let tagColor
11 | if (tag) {
12 | const tagName = slugify(tag)
13 | tagColor = getColourFromString(tagName)
14 | } else {
15 | tagColor = '#aaa'
16 | }
17 | return (
18 |
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagDot/index.ts:
--------------------------------------------------------------------------------
1 | export { TagDot } from './TagDot'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagList/TagList.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { FunctionComponent } from 'react'
3 | import { Link as GatsbyLink } from 'gatsby'
4 | import { jsx, Box, Badge, Link, SxStyleProp } from 'theme-ui'
5 | import slugify from '@alexcarpenter/slugify'
6 | import { getColourFromString } from '../../utils/getColourFromString'
7 | import { useSiteMetadata } from '../../use-site-metadata'
8 |
9 | interface TagListProps {
10 | tags: string[]
11 | asLinks?: boolean
12 | sx?: SxStyleProp
13 | }
14 |
15 | export const TagList: FunctionComponent = ({
16 | tags,
17 | asLinks = true,
18 | sx,
19 | }) => {
20 | const { basePath } = useSiteMetadata()
21 | if (!tags) {
22 | return null
23 | }
24 |
25 | return (
26 |
34 | {tags.map((item, index) => {
35 | if (item === 'untagged') {
36 | return null
37 | }
38 | const tagName = slugify(item)
39 | const tagColor = getColourFromString(tagName)
40 | const tagLink =
41 | basePath === '/' ? `/tag/${tagName}` : `${basePath}/tag/${tagName}`
42 | if (asLinks) {
43 | return (
44 |
55 | {item}
56 |
57 | )
58 | }
59 |
60 | return (
61 |
62 | {item}
63 |
64 | )
65 | })}
66 |
67 | )
68 | }
69 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagList/index.ts:
--------------------------------------------------------------------------------
1 | export { TagList } from './TagList'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagNav/TagNav.tsx:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { FunctionComponent, useContext, Fragment } from 'react'
3 | import { Link as GatsbyLink } from 'gatsby'
4 | import { jsx, Box, NavLink } from 'theme-ui'
5 | import { SearchContext } from '../Search'
6 | import { TagDot } from '../TagDot'
7 |
8 | export interface TagItemInterface {
9 | tag: string
10 | totalCount: number
11 | slug: string
12 | path: string
13 | }
14 |
15 | interface TagNavProps {
16 | tags: TagItemInterface[]
17 | activeTag?: string
18 | rootPath?: boolean
19 | basePath: string
20 | hasUntagged?: boolean
21 | }
22 |
23 | export const TagNav: FunctionComponent = ({
24 | tags,
25 | activeTag,
26 | rootPath,
27 | basePath,
28 | hasUntagged,
29 | }) => {
30 | const { setQuery } = useContext(SearchContext)
31 | return (
32 |
33 | setQuery('')}
43 | >
44 | All Notes
45 |
46 | {tags.length > 0 && (
47 |
48 |
59 | Tags
60 |
61 |
62 | {tags
63 | .sort((one, two) => one.tag.localeCompare(two.tag))
64 | .map((item, index) => {
65 | return (
66 | setQuery('')}
74 | >
75 |
76 | {item.tag}
77 |
78 | )
79 | })}
80 |
81 | )}
82 | {hasUntagged && (
83 | setQuery('')}
91 | >
92 |
93 | Untagged Notes
94 |
95 | )}
96 |
97 | )
98 | }
99 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/components/TagNav/index.ts:
--------------------------------------------------------------------------------
1 | export { TagNav } from './TagNav'
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/badges.js:
--------------------------------------------------------------------------------
1 | export const badgePrimary = {
2 | borderRadius: '50px',
3 | color: 'textStrong',
4 | bg: 'badgeBg',
5 | textDecoration: 'none',
6 | px: 2,
7 | fontWeight: 'normal',
8 | fontSize: 0,
9 | }
10 | export const badges = {
11 | primary: badgePrimary,
12 | }
13 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/borderWidths.js:
--------------------------------------------------------------------------------
1 | export const borderWidths = {
2 | px: '1px',
3 | '0': '0',
4 | '2': '2px',
5 | '4': '4px',
6 | '8': '8px',
7 | }
8 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/breakpoints.js:
--------------------------------------------------------------------------------
1 | export const breakpoints = ['800px', '1200px']
2 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/buttons.js:
--------------------------------------------------------------------------------
1 | export const buttons = {
2 | copyCode: {
3 | px: 2,
4 | py: 1,
5 | fontSize: 0,
6 | bg: 'badgeBg',
7 | userSelect: 'none',
8 | color: 'text',
9 | border: (theme) => `1px solid ${theme.colors.badgeBorder}`,
10 | borderRadius: 'large',
11 | ml: 'auto',
12 | fontFamily: 'inherit',
13 | textTransform: 'uppercase',
14 | cursor: 'pointer',
15 | '&:hover': {
16 | bg: 'badgeBgHover',
17 | },
18 | variant: 'utils.focusVisibleOutset',
19 | },
20 |
21 | icon: {
22 | cursor: 'pointer',
23 | borderRadius: '50%',
24 | variant: 'utils.focusVisibleOutset',
25 | },
26 |
27 | menu: {
28 | cursor: 'pointer',
29 | borderRadius: '50%',
30 | variant: 'utils.focusVisibleOutset',
31 | },
32 |
33 | sort: {
34 | cursor: 'pointer',
35 | variant: 'utils.focusVisibleOutset',
36 | display: 'inline-flex',
37 | alignItems: 'center',
38 | px: 2,
39 | py: 0,
40 | fontSize: 0,
41 | bg: 'badgeBg',
42 | userSelect: 'none',
43 | color: 'text',
44 | border: '1px solid',
45 | borderColor: 'badgeBorder',
46 | borderRadius: 0,
47 | fontFamily: 'inherit',
48 | textTransform: 'uppercase',
49 | '&:hover': {
50 | bg: 'badgeBgHover',
51 | },
52 | '&.active': {
53 | bg: 'badgeBgHover',
54 | color: 'textStrong',
55 | },
56 | svg: {
57 | ml: 1,
58 | },
59 | '&:first-child': {
60 | borderTopLeftRadius: '0.25rem',
61 | borderBottomLeftRadius: '0.25rem',
62 | borderRight: 0,
63 | },
64 | '&:last-child': {
65 | borderTopRightRadius: '0.25rem',
66 | borderBottomRightRadius: '0.25rem',
67 | borderRight: '1px solid',
68 | borderColor: 'badgeBorder',
69 | },
70 | },
71 | }
72 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/colors.js:
--------------------------------------------------------------------------------
1 | export const baseColors = {
2 | grayDark: '#2d3748',
3 | white: '#fff',
4 | light: '#FBFDFE',
5 | dark: '#1a202c',
6 | }
7 |
8 | const lightTheme = {
9 | text: '#4a5568',
10 | textStrong: baseColors.dark,
11 | background: 'hsl(210, 38%, 95%)',
12 | scrollbar: 'hsl(210, 20%, 85%)',
13 | backgroundTransparent: 'hsla(210, 38%, 95%, 0.72)',
14 | contentBg: baseColors.light,
15 | primary: 'hsl(334, 86%, 48%)',
16 | primarySemiTransparent: 'hsla(334, 86%, 48%, 0.3)',
17 | secondary: '#718096',
18 | muted: '#e2e8f0',
19 | success: '#9ae6b4',
20 | info: '#63b3ed',
21 | warning: '#faf089',
22 | danger: '#feb2b2',
23 | navHover: '#cbd5e0',
24 | codeBackground: 'hsl(210,38%,95%)',
25 | codeHighlight: 'hsl(210,38%,90%)',
26 | codeHighlightBorder: 'hsl(210,38%,85%)',
27 | badgeBg: 'hsl(210, 25%, 97%)',
28 | badgeBgHover: 'hsl(210, 25%, 89%)',
29 | badgeBorder: 'hsl(207, 24%, 83%)',
30 | input: '#92A2B9',
31 | code1: '#d03592',
32 | code2: '#fc9867',
33 | code3: '#f66a0a',
34 | code4: '#0366d6',
35 | code5: '#6f42c1',
36 | code6: '#0366d6',
37 | code7: '#999988',
38 | highlight: '#fff176',
39 | around: '#1aa6e9',
40 | crossed: '#e9522c',
41 | }
42 |
43 | export const colors = {
44 | ...baseColors,
45 | ...lightTheme,
46 | modes: {
47 | dark: {
48 | text: 'hsl(210, 17%, 85%)',
49 | textStrong: 'hsl(210, 38%, 98%)',
50 | background: 'hsl(285, 5%, 17%)',
51 | scrollbar: 'hsl(285, 5%, 12%)',
52 | backgroundTransparent: 'hsla(285, 5%, 17%, 0.72)',
53 | contentBg: '#383539',
54 | primary: 'hsl(345, 100%, 69%)',
55 | primarySemiTransparent: 'hsl(345, 100%, 79%, 0.3)',
56 | secondary: '#718096',
57 | muted: 'hsl(210, 5%, 40%)',
58 | success: '#9ae6b4',
59 | info: '#63b3ed',
60 | warning: '#faf089',
61 | danger: '#feb2b2',
62 | navHover: 'hsl(285, 5%, 13%)',
63 | codeBackground: 'hsl(285,5%,17%)',
64 | codeHighlight: 'hsl(285,5%,25%)',
65 | codeHighlightBorder: 'hsl(285,5%,20%)',
66 | badgeBg: 'hsl(285, 5%, 17%)',
67 | badgeBgHover: 'hsl(285, 5%, 14%)',
68 | badgeBorder: 'hsl(285, 5%, 12%)',
69 | input: 'hsl(215, 5%, 65%)',
70 | code1: 'hsl(345, 100%, 69%)',
71 | code2: '#fc9867',
72 | code3: '#ffd866',
73 | code4: '#a9dc76',
74 | code5: '#78dce8',
75 | code6: '#ab9df2',
76 | code7: '#999988',
77 |
78 | highlight: 'hsl(50, 80%, 35%)',
79 | around: '#1aa6e9',
80 | crossed: '#e9522c',
81 | },
82 | light: lightTheme,
83 | },
84 | }
85 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/components.js:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { jsx, Box as TUIBox, Button } from 'theme-ui'
3 | import Prism from '@theme-ui/prism'
4 | import { FaAnchor } from 'react-icons/fa'
5 | import { toClipboard } from 'copee'
6 | import { useState } from 'react'
7 | import { getColourFromString } from '../utils/getColourFromString'
8 | import {
9 | Underline,
10 | Box,
11 | Circle,
12 | Highlight,
13 | StrikeThrough,
14 | CrossedOff,
15 | } from '../components/Rough'
16 |
17 | const heading = (Tag) => (props) => {
18 | if (!props.id) return
19 |
20 | return (
21 |
29 | {props.children}
30 |
52 |
53 |
54 |
55 | )
56 | }
57 |
58 | const ResponsiveTable = ({ children }) => {
59 | return (
60 |
70 |
71 |
72 | )
73 | }
74 |
75 | const CopyCode = ({ code }) => {
76 | const [notificationActive, setNotificationActive] = useState(false)
77 |
78 | const handleCopy = () => {
79 | toClipboard(code)
80 | setNotificationActive(true)
81 |
82 | setTimeout(() => {
83 | setNotificationActive(false)
84 | }, 3000)
85 | }
86 |
87 | return (
88 | handleCopy()} variant="copyCode">
89 | {notificationActive ? 'Copied' : 'Copy'}
90 |
91 | )
92 | }
93 |
94 | const CodeLabel = ({ label }) => {
95 | if (!label.includes('language')) {
96 | return null
97 | }
98 |
99 | const classes = label.split(' ')
100 | const langIndex = classes.findIndex((item) => {
101 | return item.includes('language')
102 | })
103 | const language = classes[langIndex].replace('language-', '')
104 |
105 | return (
106 |
123 | {language}
124 |
125 | )
126 | }
127 |
128 | const Code = ({ children, classes, code }) => {
129 | return (
130 |
131 |
142 |
143 |
144 |
145 | {children}
146 |
147 | )
148 | }
149 |
150 | const components = {
151 | h1: heading('h1'),
152 | h2: heading('h2'),
153 | h3: heading('h3'),
154 | h4: heading('h4'),
155 | h5: heading('h5'),
156 | h6: heading('h6'),
157 | pre: (props) => props.children,
158 | code: (props) => (
159 |
160 |
161 |
162 | ),
163 | table: (props) => {props.children} ,
164 | Underline,
165 | Box,
166 | Circle,
167 | Highlight,
168 | StrikeThrough,
169 | CrossedOff,
170 | }
171 |
172 | export default components
173 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/fonts.js:
--------------------------------------------------------------------------------
1 | export const baseFonts = {
2 | sans:
3 | 'Inter,-apple-system, BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"',
4 | serif: 'Georgia, Cambria, "Times New Roman", Times, serif',
5 | mono:
6 | '"JetBrains Mono", "IBM Plex Mono", "Fira Code", "Input Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
7 | }
8 |
9 | export const fonts = {
10 | ...baseFonts,
11 | body: baseFonts.sans,
12 | heading: 'inherit',
13 | monospace: baseFonts.mono,
14 | }
15 |
16 | // https://www.modularscale.com/?1&em&1.125
17 | export const fontSizes = [
18 | '0.7rem',
19 | '0.875rem',
20 | '1rem',
21 | '1.125rem',
22 | '1.266em',
23 | '1.424em',
24 | '1.602em',
25 | '1.802em',
26 | '2.027em',
27 | '2.281em',
28 | '3rem',
29 | '4rem',
30 | '4.5rem',
31 | ]
32 |
33 | export const baseFontWeights = {
34 | hairline: '100',
35 | thin: '200',
36 | light: '300',
37 | normal: '400',
38 | medium: '500',
39 | semibold: '600',
40 | bold: '700',
41 | extrabold: '800',
42 | black: '900',
43 | }
44 |
45 | export const fontWeights = {
46 | ...baseFontWeights,
47 | body: baseFontWeights.normal,
48 | heading: baseFontWeights.bold,
49 | }
50 |
51 | export const letterSpacings = {
52 | tighter: '-0.05em',
53 | tight: '-0.025em',
54 | normal: '0',
55 | wide: '0.025em',
56 | wider: '0.05em',
57 | widest: '0.1em',
58 | }
59 |
60 | export const baseLineHeights = {
61 | none: '1',
62 | tight: '1.25',
63 | snug: '1.375',
64 | normal: '1.5',
65 | relaxed: '1.625',
66 | loose: '2',
67 | }
68 |
69 | export const lineHeights = {
70 | ...baseLineHeights,
71 | body: baseLineHeights.relaxed,
72 | heading: baseLineHeights.tight,
73 | }
74 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/forms.js:
--------------------------------------------------------------------------------
1 | export const forms = {
2 | input: {
3 | border: 0,
4 | borderBottom: (theme) => `1px solid ${theme.colors.input}`,
5 | pl: 5,
6 | borderRadius: 0,
7 | fontFamily: 'sans',
8 | transition: 'all 200ms ease-in-out ',
9 | lineHeight: '1.4rem',
10 | '&:focus': {
11 | boxShadow: (theme) => `0 2px 0 ${theme.colors.primary}`,
12 | outline: 'none',
13 | borderColor: 'primary',
14 | },
15 | },
16 |
17 | radio: {
18 | width: 18,
19 | height: 18,
20 | mr: 1,
21 | 'input:focus ~ &': {
22 | bg: 'primarySemiTransparent',
23 | },
24 | },
25 |
26 | label: {
27 | width: 'auto',
28 | ml: 2,
29 | fontSize: 0,
30 | textTransform: 'uppercase',
31 | display: 'inline-flex',
32 | alignItems: 'center',
33 | },
34 | }
35 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/images.js:
--------------------------------------------------------------------------------
1 | export const images = {
2 | logo: {
3 | maxWidth: '100%',
4 | display: 'block',
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/index.js:
--------------------------------------------------------------------------------
1 | import { buttons } from './buttons'
2 | import { colors } from './colors'
3 | import { shadows } from './shadows'
4 | import { space } from './space'
5 | import { radii } from './radii'
6 | import {
7 | letterSpacings,
8 | lineHeights,
9 | fonts,
10 | fontSizes,
11 | fontWeights,
12 | } from './fonts'
13 | import { styles } from './styles'
14 | import { text } from './text'
15 | import { links } from './links'
16 | import { sizes } from './sizes'
17 | import { forms } from './forms'
18 | import { zIndices } from './zIndices'
19 | import { images } from './images'
20 | import { badges } from './badges'
21 | import { borderWidths } from './borderWidths'
22 | import { utils } from './utils'
23 | import { breakpoints } from './breakpoints'
24 |
25 | export default {
26 | useColorSchemeMediaQuery: true,
27 | buttons,
28 | colors,
29 | shadows,
30 | space,
31 | radii,
32 | letterSpacings,
33 | lineHeights,
34 | fonts,
35 | fontSizes,
36 | fontWeights,
37 | borderWidths,
38 | breakpoints,
39 | styles,
40 | text,
41 | links,
42 | sizes,
43 | forms,
44 | zIndices,
45 | images,
46 | badges,
47 | utils,
48 | }
49 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/links.js:
--------------------------------------------------------------------------------
1 | import { badgePrimary } from './badges'
2 |
3 | export const links = {
4 | noteListItem: {
5 | mx: (theme) => `-${theme.space[2]}`,
6 | p: 2,
7 | borderRadius: 'default',
8 | display: 'block',
9 | transition: 'all 200ms ease-in-out ',
10 | color: 'text',
11 | variant: 'utils.focusVisibleOutset',
12 | '&:link, &:visited': {
13 | color: 'primary',
14 | textDecoration: 'none',
15 | },
16 | '&:hover': {
17 | bg: 'codeBackground',
18 | },
19 | },
20 |
21 | nav: {
22 | px: 3,
23 | py: 1,
24 | display: 'flex',
25 | alignItems: 'center',
26 | fontWeight: 'normal',
27 | fontSize: '14px',
28 | transition: 'all 200ms ease-in-out ',
29 | color: 'textStrong',
30 | '&:hover': {
31 | bg: 'navHover',
32 | color: 'textStrong',
33 | },
34 | variant: 'utils.focusVisibleOutset',
35 | },
36 |
37 | badge: {
38 | ...badgePrimary,
39 | transition: 'all 200ms ease-in-out ',
40 | flexShrink: 0,
41 | '&:hover': {
42 | textDecoration: 'none',
43 | opacity: '0.7',
44 | },
45 | variant: 'utils.focusVisibleOutset',
46 | },
47 | }
48 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/radii.js:
--------------------------------------------------------------------------------
1 | export const radii = {
2 | none: '0',
3 | sm: '0.125rem',
4 | default: '0.25rem',
5 | lg: '0.5rem',
6 | full: '9999px',
7 | }
8 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/shadows.js:
--------------------------------------------------------------------------------
1 | export const shadows = {
2 | default: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
3 | md: '0 0 6px -1px rgba(0, 0, 0, 0.1), 0 0 4px -1px rgba(0, 0, 0, 0.06)',
4 | lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
5 | xl:
6 | '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
7 | '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
8 | inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
9 | outline: '0 0 0 3px rgba(66, 153, 225, 0.5)',
10 | none: 'none',
11 | }
12 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/sizes.js:
--------------------------------------------------------------------------------
1 | export const sizes = {
2 | container: 900,
3 | sidebar: '250px',
4 | sidebarSkinny: '50%',
5 | contentMaxWidth: '900px',
6 | }
7 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/space.js:
--------------------------------------------------------------------------------
1 | export const space = [
2 | 0,
3 | '0.25rem',
4 | '0.5rem',
5 | '1rem',
6 | '1.5rem',
7 | '2rem',
8 | '2.5rem',
9 | '3rem',
10 | '3.5rem',
11 | '4rem',
12 | '8rem',
13 | '16rem',
14 | '32rem',
15 | ]
16 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/styles.js:
--------------------------------------------------------------------------------
1 | export const heading = {
2 | fontFamily: 'heading',
3 | fontWeight: 'heading',
4 | lineHeight: 'heading',
5 | mt: 5,
6 | mb: 3,
7 | color: 'textStrong',
8 | }
9 |
10 | export const styles = {
11 | root: {
12 | fontFamily: 'body',
13 | lineHeight: 'body',
14 | fontWeight: 'body',
15 | fontSize: 2,
16 | },
17 | a: {
18 | transition: 'all 200ms ease-in-out ',
19 | '&:link, &:visited': {
20 | fontWeight: 'semibold',
21 | color: 'textStrong',
22 | textDecorationStyle: 'solid',
23 | textDecorationSkipInk: 'auto',
24 | textDecorationThickness: 'from-font',
25 | },
26 | '&:hover': {
27 | color: 'primary',
28 | // textDecorationSkipInk: 'none',
29 | // textDecorationStyle: 'dashed',
30 | },
31 | variant: 'utils.focusVisibleOutset',
32 | },
33 | p: {
34 | fontFamily: 'body',
35 | lineHeight: 'body',
36 | fontWeight: 'body',
37 | color: 'text',
38 | mt: 0,
39 | mb: '1.25rem',
40 | },
41 | h1: {
42 | ...heading,
43 | fontSize: 7,
44 | },
45 | h2: {
46 | ...heading,
47 | fontSize: 6,
48 | },
49 | h3: {
50 | ...heading,
51 | fontSize: 5,
52 | mb: 1,
53 | },
54 | h4: {
55 | ...heading,
56 | fontSize: 4,
57 | mb: 1,
58 | },
59 | h5: {
60 | ...heading,
61 | fontSize: 3,
62 | mb: 1,
63 | },
64 | h6: {
65 | ...heading,
66 | fontSize: 2,
67 | mb: 1,
68 | },
69 | inlineCode: {
70 | // backgroundColor: 'background',
71 | // p: '0.1em 0.2em',
72 | // borderRadius: 'default',
73 | fontSize: '80%',
74 | fontFamily: 'mono',
75 | color: 'textStrong',
76 | fontWeight: 'semibold',
77 | '&::before, &::after': {
78 | content: "'`'",
79 | },
80 | },
81 | pre: {
82 | py: 2,
83 | mt: 0,
84 | fontSize: 1,
85 | color: 'textStrong',
86 | bg: 'background',
87 | overflowX: 'auto',
88 | borderRadius: (theme) =>
89 | `0 0 ${theme.radii.default} ${theme.radii.default}`,
90 | fontFamily: 'mono',
91 | '.comment,.prolog,.doctype,.cdata': {
92 | color: 'code7',
93 | fontStyle: 'italic',
94 | },
95 | '.namespace': {
96 | opacity: 0.7,
97 | },
98 | '.string,.attr-value,.punctuation,.tag.script-punctuation,.tag.attr-value.punctuation': {
99 | color: 'code3',
100 | },
101 | '.entity,.url,.symbol,.number,.boolean,.constant,.property,.regex,.inserted,.attr-value,.tag.attr-value': {
102 | color: 'text',
103 | },
104 | '.function,.tag.function,.deleted,.variable,.unit': {
105 | color: 'code3',
106 | },
107 | '.function-variable': {
108 | color: 'code6',
109 | },
110 | '.tag,.keyword,.selector,.attr-name,.tag.attr-name': {
111 | color: 'code5',
112 | },
113 | '.symbol,.tag.punctuation': {
114 | color: 'code7',
115 | },
116 | '.property,.number': {
117 | color: 'code6',
118 | },
119 | '.rule,.class-name,.keyword.module,.operator,.tag': {
120 | color: 'code1',
121 | },
122 | '.function,.tag.function': {
123 | color: 'code4',
124 | },
125 | '&::-webkit-scrollbar': {
126 | width: '0.5rem',
127 | height: '0.5rem',
128 | '&:hover': {
129 | width: '1rem',
130 | height: '1rem',
131 | },
132 | },
133 | '&::-webkit-scrollbar-track': {
134 | backgroundColor: 'scrollbar',
135 | },
136 | '&::-webkit-scrollbar-thumb': {
137 | backgroundColor: 'muted',
138 | },
139 | '.highlight': {
140 | bg: 'codeHighlight',
141 | position: 'relative',
142 | '&::before': {
143 | content: "''",
144 | position: 'absolute',
145 | top: 0,
146 | left: 0,
147 | bottom: 0,
148 | display: 'block',
149 | width: '4px',
150 | bg: 'codeHighlightBorder',
151 | },
152 | },
153 | '.token-line': {
154 | px: 3,
155 | },
156 | },
157 | blockquote: {
158 | borderLeft: '4px solid',
159 | borderColor: 'muted',
160 | fontFamily: 'mono',
161 | textStyle: 'italic',
162 | pl: 3,
163 | my: 4,
164 | mx: 0,
165 | },
166 | hr: {
167 | bg: 'muted',
168 | border: 0,
169 | height: '1px',
170 | m: 3,
171 | },
172 | table: {
173 | width: '100%',
174 | borderCollapse: 'separate',
175 | borderSpacing: 0,
176 | tableLayout: 'fixed',
177 | my: 2,
178 | },
179 | th: {
180 | textAlign: 'left',
181 | borderBottomStyle: 'solid',
182 | borderBottomColor: 'background',
183 | p: 2,
184 | fontWeight: 'bold',
185 | fontSize: 3,
186 | lineHeight: 1,
187 | },
188 | td: {
189 | textAlign: 'left',
190 | borderBottomStyle: 'solid',
191 | borderBottomColor: 'background',
192 | p: 2,
193 | },
194 | img: {
195 | my: 4,
196 | p: 3,
197 | border: (theme) => `1px solid ${theme.colors.muted}`,
198 | display: 'block',
199 | borderRadius: 'default',
200 | maxWidth: '100%',
201 | },
202 | summary: {
203 | color: 'textStrong',
204 | },
205 | }
206 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/text.js:
--------------------------------------------------------------------------------
1 | export const text = {
2 | noteTitle: {
3 | fontWeight: 'extrabold',
4 | fontSize: 9,
5 | mb: 3,
6 | lineHeight: 'none',
7 | display: 'flex',
8 | alignItems: 'center',
9 | color: 'textStrong',
10 | },
11 |
12 | noteListItem: {
13 | position: 'relative',
14 | fontSize: 2,
15 | m: 0,
16 | fontFamily: 'body',
17 | fontWeight: 'bold',
18 | color: 'textStrong',
19 | pl: 5,
20 | },
21 |
22 | dateModified: {
23 | fontSize: 0,
24 | color: 'text',
25 | whiteSpace: 'nowrap',
26 | overflow: 'hidden',
27 | textOverflow: 'ellipsis',
28 | },
29 | }
30 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/utils.js:
--------------------------------------------------------------------------------
1 | export const utils = {
2 | focusVisibleOutset: {
3 | '&:focus': {
4 | outline: 0,
5 | boxShadow: (theme) =>
6 | `0px 0px 0px 3px ${theme.colors.primarySemiTransparent}`,
7 | },
8 | '&:focus-visible': {
9 | boxShadow: (theme) =>
10 | `0px 0px 0px 3px ${theme.colors.primarySemiTransparent}`,
11 | },
12 | '&:focus:not(:focus-visible)': {
13 | boxShadow: 'none',
14 | },
15 | },
16 |
17 | focusVisibleInset: {
18 | '&:focus': {
19 | outline: 0,
20 | boxShadow: (theme) =>
21 | `inset 0px 0px 0px 3px ${theme.colors.primarySemiTransparent}`,
22 | },
23 | '&:focus-visible': {
24 | outline: 0,
25 | boxShadow: (theme) =>
26 | `inset 0px 0px 0px 3px ${theme.colors.primarySemiTransparent}`,
27 | },
28 | '&:focus:not(:focus-visible)': {
29 | boxShadow: 'none',
30 | },
31 | },
32 | }
33 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby-plugin-theme-ui/zIndices.js:
--------------------------------------------------------------------------------
1 | export const zIndices = {
2 | low: 10,
3 | mid: 20,
4 | high: 30,
5 | }
6 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/gatsby/wrapRootElement.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { SearchProvider } from '../components/Search'
3 |
4 | export const wrapRootElementComponent = ({ element }) => {
5 | return {element}
6 | }
7 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/templates/404.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Layout } from '../components/Layout'
3 | import { Heading, Box, Styled } from 'theme-ui'
4 |
5 | const ErrorPage = ({ pageContext, location }) => {
6 | return (
7 |
14 |
15 |
16 |
17 | Page not found
18 |
19 |
20 |
21 |
22 | Oops! This page you are looking for has been removed or relocated.
23 |
24 |
25 |
26 | )
27 | }
28 |
29 | export default ErrorPage
30 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/templates/Note.js:
--------------------------------------------------------------------------------
1 | import { graphql } from 'gatsby'
2 | import { NotePage } from '../components/NotePage'
3 |
4 | export default NotePage
5 |
6 | export const pageQuery = graphql`
7 | query NoteById($id: String!) {
8 | mdx(id: { eq: $id }) {
9 | body
10 | frontmatter {
11 | title
12 | tags
13 | emoji
14 | link
15 | modified(formatString: "LL")
16 | modifiedTimestamp: modified
17 | }
18 | references: inboundReferences {
19 | ... on Mdx {
20 | frontmatter {
21 | title
22 | }
23 | slug
24 | }
25 | }
26 | fields {
27 | slug
28 | }
29 | tableOfContents(maxDepth: 3)
30 | parent {
31 | ... on File {
32 | relativePath
33 | }
34 | }
35 | }
36 | }
37 | `
38 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/templates/Notes.js:
--------------------------------------------------------------------------------
1 | import { graphql } from 'gatsby'
2 | import { NotesPage } from '../components/NotesPage'
3 |
4 | export default NotesPage
5 |
6 | export const pageQuery = graphql`
7 | fragment AllPages on Mdx {
8 | id
9 | frontmatter {
10 | title
11 | tags
12 | emoji
13 | modified(formatString: "LL")
14 | modifiedTimestamp: modified
15 | }
16 | fields {
17 | slug
18 | }
19 | }
20 |
21 | query {
22 | allMdx {
23 | edges {
24 | node {
25 | ...AllPages
26 | }
27 | }
28 | }
29 | }
30 | `
31 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/templates/TagPage.js:
--------------------------------------------------------------------------------
1 | import { graphql } from 'gatsby'
2 | import { NotesPage } from '../components/NotesPage'
3 |
4 | export default NotesPage
5 |
6 | export const pageQuery = graphql`
7 | query($tag: String!) {
8 | allMdx(
9 | sort: { fields: frontmatter___title, order: ASC }
10 | filter: { frontmatter: { tags: { eq: $tag } } }
11 | ) {
12 | edges {
13 | node {
14 | id
15 | ...AllPages
16 | }
17 | }
18 | }
19 | }
20 | `
21 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/templates/UntaggedTagPage.js:
--------------------------------------------------------------------------------
1 | import { graphql } from 'gatsby'
2 | import { NotesPage } from '../components/NotesPage'
3 |
4 | export default NotesPage
5 |
6 | export const pageQuery = graphql`
7 | query {
8 | allMdx(
9 | sort: { fields: frontmatter___title, order: ASC }
10 | filter: { frontmatter: { tags: { eq: null } } }
11 | ) {
12 | edges {
13 | node {
14 | id
15 | ...AllPages
16 | }
17 | }
18 | }
19 | }
20 | `
21 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/use-all-tags.ts:
--------------------------------------------------------------------------------
1 | import { graphql, useStaticQuery } from 'gatsby'
2 | import slugify from '@alexcarpenter/slugify'
3 |
4 | export const useAllTags = () => {
5 | const data = useStaticQuery(graphql`
6 | {
7 | allMdx {
8 | tags: group(field: frontmatter___tags) {
9 | tag: fieldValue
10 | totalCount
11 | }
12 | }
13 | }
14 | `)
15 |
16 | return data.allMdx.tags.sort().map((item) => {
17 | return {
18 | ...item,
19 | slug: slugify(item.tag),
20 | }
21 | })
22 | }
23 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/use-site-metadata.ts:
--------------------------------------------------------------------------------
1 | import { graphql, useStaticQuery } from 'gatsby'
2 |
3 | export const useSiteMetadata = () => {
4 | const data = useStaticQuery(graphql`
5 | {
6 | site {
7 | siteMetadata {
8 | title
9 | description
10 | gitRepoContentPath
11 | showThemeInfo
12 | showDescriptionInSidebar
13 | logo
14 | openSearch {
15 | siteUrl
16 | siteShortName
17 | }
18 | showDate
19 | basePath
20 | }
21 | }
22 | }
23 | `)
24 |
25 | return data.site.siteMetadata
26 | }
27 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/utils/createOpenSearch.js:
--------------------------------------------------------------------------------
1 | module.exports = (options) => {
2 | const {
3 | siteUrl = '',
4 | siteShortName = 'Code Notes Search',
5 | siteDescription = null,
6 | siteTags = null,
7 | siteContact = null,
8 | } = options
9 |
10 | let data = `
11 |
12 | ${siteShortName}
13 |
14 | `
15 |
16 | if (siteDescription !== null) {
17 | data += ` ${siteDescription}
18 | `
19 | }
20 | if (siteTags !== null) {
21 | data += ` ${siteTags}
22 | `
23 | }
24 | if (siteContact !== null) {
25 | data += ` ${siteContact}
26 | `
27 | }
28 |
29 | data += ` `
30 |
31 | return data
32 | }
33 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/utils/getColourFromString.ts:
--------------------------------------------------------------------------------
1 | import ColorHash from 'color-hash'
2 |
3 | const colorHash = new ColorHash({
4 | lightness: 0.6,
5 | saturation: 0.4,
6 | })
7 |
8 | export const getColourFromString = (item: string): string => {
9 | const tagHsl: number[] = colorHash.hsl(item)
10 | const tagColor = `hsla(${tagHsl[0]},${tagHsl[1] * 100}%,${
11 | tagHsl[2] * 100
12 | }%,0.5)`
13 | return tagColor
14 | }
15 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/src/utils/resolve-url.js:
--------------------------------------------------------------------------------
1 | const slugify = require('@alexcarpenter/slugify')
2 |
3 | module.exports = (title) => slugify(`/${title}`)
4 |
--------------------------------------------------------------------------------
/gatsby-theme-code-notes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "esModuleInterop": true,
5 | "forceConsistentCasingInFileNames": true,
6 | "isolatedModules": true,
7 | "jsx": "preserve",
8 | "lib": ["dom", "dom.iterable", "esnext"],
9 | "module": "esnext",
10 | "moduleResolution": "node",
11 | "noEmit": true,
12 | "resolveJsonModule": true,
13 | "skipLibCheck": true,
14 | "strict": false,
15 | "target": "es5"
16 | },
17 | "exclude": [
18 | "node_modules",
19 | "./.storybook/**/*",
20 | "./cypress/**/*",
21 | "./static/scripts/**/*"
22 | ],
23 | "include": ["src/**/*.ts", "src/**/*.tsx", "global.d.ts"]
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-theme-code-notes-workspace",
3 | "private": true,
4 | "version": "0.0.1",
5 | "main": "index.js",
6 | "license": "MIT",
7 | "scripts": {
8 | "prebuild": "yarn clean",
9 | "build": "yarn workspace example build",
10 | "predev": "yarn clean",
11 | "dev": "yarn workspace example dev",
12 | "clean": "yarn workspace example clean",
13 | "start": "yarn workspace example start",
14 | "lint": "eslint './gatsby-theme-code-notes/src/**/*'"
15 | },
16 | "workspaces": [
17 | "gatsby-theme-code-notes",
18 | "example"
19 | ],
20 | "dependencies": {
21 | "eslint": "^7.24.0",
22 | "eslint-config-prettier": "^8.2.0",
23 | "eslint-plugin-prettier": "^3.4.0",
24 | "eslint-plugin-react": "^7.23.2",
25 | "eslint-plugin-react-hooks": "^4.2.0",
26 | "husky": "^6.0.0",
27 | "jest": "^26.6.3",
28 | "jest-emotion": "^11.0.0",
29 | "lint-staged": "^10.5.4",
30 | "prettier": "^2.2.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------