├── .gitignore ├── README.md ├── package.json ├── patches └── mdx-deck+1.10.2.patch ├── src ├── Cover.js ├── Feedback.js ├── Img.js ├── InlineImg.js ├── Intro.js ├── Thanks.js ├── code │ └── ast.js ├── deck.mdx ├── img │ ├── ast.png │ ├── compilerParsing.png │ ├── compilerPipeline.png │ ├── compilerSteps.png │ ├── entria.png │ ├── entriaLogo.png │ ├── evergreen.png │ ├── explorer.png │ ├── github.png │ ├── graphql2ts.png │ ├── lisp.png │ ├── me.png │ ├── relayCompilerRepl.png │ ├── syntatic.png │ ├── tokenizer.png │ ├── tokens.png │ ├── traversal.gif │ ├── traverse.gif │ ├── twitter.png │ ├── useState.png │ └── visitor.png └── theme.js ├── static └── images │ └── evergreen.png └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sublime-project 3 | *.sublime-workspace 4 | .idea/ 5 | 6 | lib-cov 7 | *.seed 8 | *.log 9 | *.csv 10 | *.dat 11 | *.out 12 | *.pid 13 | *.gz 14 | *.map 15 | 16 | pids 17 | logs 18 | results 19 | test-results 20 | 21 | node_modules 22 | npm-debug.log 23 | 24 | dump.rdb 25 | bundle.js 26 | 27 | build 28 | dist 29 | coverage 30 | .nyc_output 31 | .env 32 | 33 | graphql.*.json 34 | junit.xml 35 | 36 | .vs 37 | 38 | test/globalConfig.json 39 | distTs 40 | 41 | # Random things to ignore 42 | ignore/ 43 | package-lock.json 44 | /yarn-offline-cache 45 | .cache 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Practical AST 2 | 3 | Slides of my talk about Practical AST 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maringa-ast", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "gh-pages": "^2.0.1", 8 | "mdx-code": "^1.1.3", 9 | "mdx-deck": "^1.6.7", 10 | "mdx-deck-code-surfer": "^0.5.5", 11 | "mdx-deck-live-code": "^1.0.0", 12 | "qrcode.react": "^0.9.3", 13 | "raw-loader": "^3.1.0", 14 | "rebass": "^3.1.1", 15 | "styled-components": "^4.3.2", 16 | "styled-system": "^5.0.15" 17 | }, 18 | "scripts": { 19 | "build": "mdx-deck build src/deck.mdx", 20 | "help": "mdx-deck", 21 | "image": "mdx-deck screenshot src/deck.mdx", 22 | "pdf": "mdx-deck pdf src/deck.mdx", 23 | "copy:static": "cp -r src/img dist", 24 | "publish:deck": "yarn build && yarn copy:static && gh-pages -d dist", 25 | "start": "mdx-deck src/deck.mdx", 26 | "postinstall": "patch-package" 27 | }, 28 | "devDependencies": { 29 | "patch-package": "^6.1.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /patches/mdx-deck+1.10.2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/mdx-deck/lib/html.js b/node_modules/mdx-deck/lib/html.js 2 | index c4adec0..6cd8ed2 100644 3 | --- a/node_modules/mdx-deck/lib/html.js 4 | +++ b/node_modules/mdx-deck/lib/html.js 5 | @@ -28,7 +28,7 @@ const getApp = async opts => { 6 | config.target = 'node' 7 | config.externals = [ 8 | nodeExternals({ 9 | - whitelist: ['mdx-deck', 'mdx-deck/themes', 'mdx-deck/layouts'], 10 | + whitelist: ['mdx-deck', 'mdx-deck/themes', 'mdx-deck/layouts', 'mdx-deck-code-surfer'], 11 | }), 12 | ] 13 | 14 | -------------------------------------------------------------------------------- /src/Cover.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { space, width } from 'styled-system'; 4 | 5 | export const Root = styled.div([], { 6 | width: '50vw', 7 | height: '70vh', 8 | }); 9 | 10 | const Img = styled.img` 11 | ${width} 12 | `; 13 | 14 | export const Center = styled.div` 15 | display: flex; 16 | flex: 1; 17 | flex-direction: column; 18 | align-items: center; 19 | justify-content: center; 20 | `; 21 | 22 | const Title = styled.span` 23 | font-size: 50px; 24 | ${space} 25 | `; 26 | 27 | const Subtitle = styled.span` 28 | font-size: 40px; 29 | color: #FDAA4C; 30 | ${space} 31 | `; 32 | 33 | const MeName = styled.span` 34 | font-size: 30px; 35 | color: #25D7FD; 36 | ${space} 37 | `; 38 | 39 | export const Cover = () => ( 40 | 41 |
42 | 43 | Practical AST 44 | Compilers to Tooling 45 | Sibelius Seraphini 46 |
47 |
48 | ); 49 | -------------------------------------------------------------------------------- /src/Feedback.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { space, width, fontSize, color } from 'styled-system'; 4 | import QRCode from 'qrcode.react'; 5 | 6 | // Add styled-system functions to your component 7 | const Box = styled.div` 8 | ${space} 9 | ${width} 10 | ${fontSize} 11 | ${color} 12 | `; 13 | 14 | export const Root = styled.div([], { 15 | width: '50vw', 16 | height: '70vh', 17 | }); 18 | 19 | const SpaceBetween = styled.div` 20 | display: flex; 21 | flex: 1; 22 | flex-direction: row; 23 | align-items: center; 24 | justify-content: space-between; 25 | `; 26 | 27 | const FeedbackText = styled.span` 28 | font-size: 50px; 29 | color: #ffffff; 30 | `; 31 | 32 | const FeedbackLink = styled.a` 33 | font-size: 50px; 34 | color: #25D7FD; 35 | `; 36 | 37 | export const Center = styled.div` 38 | display: flex; 39 | flex: 1; 40 | flex-direction: row; 41 | align-items: center; 42 | justify-content: center; 43 | ${space} 44 | `; 45 | 46 | const EntriaLogo = styled.img` 47 | max-width: 600px; 48 | margin-top: 100px; 49 | margin-bottom: 50px; 50 | `; 51 | 52 | 53 | export const Feedback = () => ( 54 | 55 |
56 | Give me a Feedback: 57 |
58 |
59 | 65 |
66 |
67 | https://entria.feedback.house/sibelius 68 |
69 |
70 | ); 71 | -------------------------------------------------------------------------------- /src/Img.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { width } from 'styled-system'; 4 | 5 | import { Root } from './Intro'; 6 | 7 | const StyledImg = styled.img` 8 | ${width} 9 | `; 10 | 11 | export const Center = styled.div` 12 | display: flex; 13 | flex: 1; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | `; 18 | 19 | export const Img = ({ src, ...props}) => ( 20 | 21 |
22 | 23 |
24 |
25 | ); 26 | -------------------------------------------------------------------------------- /src/InlineImg.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { width } from 'styled-system'; 4 | 5 | 6 | const StyledImg = styled.img` 7 | ${width} 8 | `; 9 | 10 | export const Center = styled.div` 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | justify-content: center; 15 | `; 16 | 17 | export const InlineImg = ({ src, ...props}) => ( 18 |
19 | 20 |
21 | ); 22 | -------------------------------------------------------------------------------- /src/Intro.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { Flex } from 'rebass'; 4 | 5 | const IconImage = styled.img` 6 | max-height: 60px; 7 | max-width: 60px; 8 | `; 9 | 10 | const Link = styled.a` 11 | text-decoration: none; 12 | color: white; 13 | `; 14 | 15 | const Me = styled.img` 16 | max-width: 150px; 17 | max-height: 150px; 18 | `; 19 | 20 | const MeName = styled.span` 21 | font-size: 50px; 22 | color: #25D7FD; 23 | margin-left: 60px; 24 | `; 25 | 26 | const Row = styled.div` 27 | display: flex; 28 | flex: 1; 29 | flex-direction: row; 30 | align-items: center; 31 | margin-bottom: 40px; 32 | `; 33 | 34 | export const Center = styled.div` 35 | display: flex; 36 | flex: 1; 37 | flex-direction: row; 38 | align-items: center; 39 | justify-content: center; 40 | `; 41 | 42 | const SpaceBetween = styled.div` 43 | display: flex; 44 | flex: 1; 45 | flex-direction: row; 46 | align-items: center; 47 | justify-content: space-between; 48 | `; 49 | 50 | export const Root = styled.div([], { 51 | // width: '50vw', 52 | height: '70vh', 53 | }); 54 | 55 | const Username = styled.span` 56 | font-size: 14px; 57 | margin-left: 20px; 58 | `; 59 | 60 | const EntriaLogo = styled.img` 61 | max-width: 600px; 62 | `; 63 | 64 | const SocialMediaLink = ({ src, link, username }) => ( 65 |
66 | 67 | 68 | 69 | {username} 70 | 71 | 72 |
73 | ); 74 | 75 | export const Intro = () => ( 76 | 77 | 78 | 79 | Sibelius Seraphini 80 | 81 | 82 | 87 | 92 | 93 |
94 | 95 |
96 | 97 | Abstract Engineer 98 | 99 |
100 | ); 101 | -------------------------------------------------------------------------------- /src/Thanks.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components' 3 | import { space, width, fontSize, color } from 'styled-system'; 4 | 5 | export const Root = styled.div([], { 6 | width: '50vw', 7 | height: '70vh', 8 | }); 9 | 10 | const SpaceBetween = styled.div` 11 | display: flex; 12 | flex: 1; 13 | flex-direction: row; 14 | align-items: center; 15 | justify-content: center; 16 | ${space} 17 | `; 18 | 19 | const ThanksText = styled.span` 20 | font-size: 50px; 21 | color: #ffffff; 22 | `; 23 | 24 | const HiringText = styled.span` 25 | font-size: 100px; 26 | color: #25D7FD; 27 | `; 28 | 29 | export const Center = styled.div` 30 | display: flex; 31 | flex: 1; 32 | flex-direction: row; 33 | align-items: center; 34 | justify-content: center; 35 | `; 36 | 37 | const EntriaLogo = styled.img` 38 | max-width: 600px; 39 | margin-top: 100px; 40 | `; 41 | 42 | export const Thanks = () => ( 43 | 44 |
45 | Thanks! 46 |
47 | 48 | We are hiring! 49 | 50 | 53 | Join Us 54 |
55 | 56 |
57 |
58 | ); 59 | -------------------------------------------------------------------------------- /src/code/ast.js: -------------------------------------------------------------------------------- 1 | { 2 | type: 'Program', 3 | body: [{ 4 | type: 'CallExpression', 5 | name: 'add', 6 | params: [{ 7 | type: 'NumberLiteral', 8 | value: '2', 9 | }, { 10 | type: 'CallExpression', 11 | name: 'subtract', 12 | params: [{ 13 | type: 'NumberLiteral', 14 | value: '4', 15 | }, { 16 | type: 'NumberLiteral', 17 | value: '2', 18 | }] 19 | }] 20 | }] 21 | } 22 | -------------------------------------------------------------------------------- /src/deck.mdx: -------------------------------------------------------------------------------- 1 | import { Head, Image, Appear } from 'mdx-deck' 2 | import { Split, FullScreenCode } from 'mdx-deck/layouts' 3 | import { CodeSurfer } from "mdx-deck-code-surfer"; 4 | 5 | import { Cover } from './Cover'; 6 | import { Intro } from './Intro'; 7 | import { Img } from './Img'; 8 | import { InlineImg } from './InlineImg'; 9 | import { Thanks } from './Thanks'; 10 | import { Feedback } from './Feedback'; 11 | 12 | export { default as theme } from './theme' 13 | 14 | 15 | Practical AST 16 | 17 | 18 | 19 | 20 | --- 21 | 22 | 23 | 24 | --- 25 | 26 | # Overview 27 | 28 | 47 | 48 | --- 49 | 50 | # What is a Compiler 51 | 52 | Compilers are programs that transform code in a programming language to another language (low level or machine code) 53 | 54 | --- 55 | 56 | # Compiler Pipeline 57 | 58 | 59 | --- 60 | 61 | # Parsing 62 | 63 | 64 | --- 65 | 66 | # Lexical Analysis 67 | - It takes raw code and transform it into tokens 68 | - It is called tokenizer or lexer 69 | - Tokens are tiny objects that describe syntax 70 | 71 | --- 72 | 73 | # Tokenizer 74 | 75 | 76 | --- 77 | 78 | # Syntatic Analysis 79 | - It takes the tokens 80 | - It reformat then to a representation that describes syntax and their relation one to another 81 | - This representation is called Abstract Syntax Tree or Intermediate Representation. 82 | 83 | --- 84 | 85 | ## Syntatic Analysis 86 | 87 | 88 | --- 89 | 90 | 116 | --- 117 | 118 | ## Transformation 119 | - we can add/remove/replace properties of AST nodes 120 | - we can add/remove/replace nodes 121 | - we can create a new whole AST 122 | 123 | --- 124 | 125 | ## Traversal 126 | 127 | 128 | --- 129 | 130 | ## Visitor Pattern 131 | 132 | 133 | --- 134 | 135 | ## Code Generation 136 | - It iterate recursively on final AST to print nodes 137 | - It can print machine code 138 | - It can print another language (graphql2ts) 139 | - It can print the same language (prettier) 140 | 141 | --- 142 | 143 | ## Pratical AST 144 | 145 | 146 | --- 147 | 148 | ## [AST Explorer](https://astexplorer.net/) 149 | 150 | 151 | --- 152 | 153 | ## Where AST is used? 154 |
    155 | 156 |
  • 157 | Babel 158 |
  • 159 |
  • 160 | Eslint 161 |
  • 162 |
  • 163 | Prettier 164 |
  • 165 |
  • 166 | GraphQL 167 |
  • 168 |
  • 169 | Relay Modern 170 |
  • 171 |
  • 172 | Codemods 173 |
  • 174 |
  • 175 | IDE 176 |
  • 177 |
  • 178 | Docz 179 |
  • 180 |
  • 181 | And more 182 |
  • 183 |
    184 |
185 | --- 186 | 187 | ## Babel 188 | - You use Visitor pattern to write babel plugins to transform new javascript to old javascript 189 | 190 | --- 191 | 192 | ## Eslint 193 | - You use AST to create custom rules for you codebase 194 | 195 | --- 196 | 197 | ## Eslint Selectors 198 | - You can "query" AST node using syntax similar to CSS selectors 199 | 200 | ```js 201 | CallExpression[callee.name='setTimeout'][arguments.length!=2] 202 | ``` 203 | --- 204 | 205 | ## Prettier 206 | - You use AST to pretty print your code 207 | 208 | --- 209 | 210 | ## GraphQL 211 | - You use AST to handle GraphQL SDL and extend your GraphQL capability 212 | 213 | --- 214 | 215 | ## GraphQL2TS 216 | 217 | 218 | - Transforms .graphql files into graphql-js typescript code 219 | 220 | --- 221 | 222 | ## Relay Modern 223 | - Relay uses GraphQL AST to compile and optimize GraphQL fragments and queries 224 | - It also polyfill GraphQL to enable fragments to have arguments, this provides a better DX without losing performance 225 | 226 | --- 227 | 228 | ## Relay Compiler Repl 229 | 230 | 231 | --- 232 | 233 | ## Codemods 234 | - Codemod is an AST-to-AST transformation to evolve codebase 235 | - Much more powerful than regex 236 | - AST has much more information than raw code 237 | 238 | --- 239 | 240 | ## Codemod Examples 241 | - [rn24-rn25](https://github.com/sibelius/codemod-RN24-to-RN25): transform imports from @reactnative v24 style to @reactnative v25 style 242 | - [ast-i18n](https://github.com/sibelius/ast-i18n): transform your raw strings to i18n keys and extract all of them to a locale file 243 | - [rn-deprecated-modules](https://github.com/lucasbento/rn-update-deprecated-modules) by @lbentosilva: transform from react-native import to new @ReactNativeComm packages 244 | 245 | --- 246 | 247 | ## Codemod Examples 248 | - [import-codemod](https://github.com/jongold/import-codemod) by @jongold: generic codemod to transform imports 249 | - [react-codemod](https://github.com/reactjs/react-codemod) by @reactjs 250 | 251 | --- 252 | 253 | ## References 254 | 255 | - [The Super Tiny Compiler](https://github.com/jamiebuilds/the-super-tiny-compiler) 256 | - [The Super Tiny Compiler Glitch](https://the-super-tiny-compiler.glitch.me/) 257 | - [Effective JavaScript Codemods](https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb) 258 | - [LALG Compiler](https://github.com/sibelius/LALG) 259 | - [Writing Javascript Codemods and Understanding AST Easily](https://dev.to/arminaskatilius/writing-javascript-codemods-and-understanding-ast-easily-48fc) 260 | 261 | --- 262 | 263 | ## References 264 | - [AST Explorer](https://astexplorer.net/) 265 | - [Babel Handbook](https://github.com/jamiebuilds/babel-handbook) 266 | - [Babel](https://babeljs.io/) 267 | - [Eslint Selectors](https://eslint.org/docs/developer-guide/selectors) 268 | - [Relay Compiler Repl](https://relay-compiler-repl.netlify.com/) 269 | 270 | --- 271 | 272 | ## References 273 | - [Unified](https://unified.js.org/) 274 | - [JSCodeshift](https://github.com/facebook/jscodeshift) 275 | - [GraphQL2TS](https://github.com/sibelius/graphql2ts) 276 | - [AST i18n](https://github.com/sibelius/ast-i18n) 277 | 278 | --- 279 | 280 | 281 | 282 | --- 283 | 284 | 285 | -------------------------------------------------------------------------------- /src/img/ast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/ast.png -------------------------------------------------------------------------------- /src/img/compilerParsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/compilerParsing.png -------------------------------------------------------------------------------- /src/img/compilerPipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/compilerPipeline.png -------------------------------------------------------------------------------- /src/img/compilerSteps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/compilerSteps.png -------------------------------------------------------------------------------- /src/img/entria.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/entria.png -------------------------------------------------------------------------------- /src/img/entriaLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/entriaLogo.png -------------------------------------------------------------------------------- /src/img/evergreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/evergreen.png -------------------------------------------------------------------------------- /src/img/explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/explorer.png -------------------------------------------------------------------------------- /src/img/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/github.png -------------------------------------------------------------------------------- /src/img/graphql2ts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/graphql2ts.png -------------------------------------------------------------------------------- /src/img/lisp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/lisp.png -------------------------------------------------------------------------------- /src/img/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/me.png -------------------------------------------------------------------------------- /src/img/relayCompilerRepl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/relayCompilerRepl.png -------------------------------------------------------------------------------- /src/img/syntatic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/syntatic.png -------------------------------------------------------------------------------- /src/img/tokenizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/tokenizer.png -------------------------------------------------------------------------------- /src/img/tokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/tokens.png -------------------------------------------------------------------------------- /src/img/traversal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/traversal.gif -------------------------------------------------------------------------------- /src/img/traverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/traverse.gif -------------------------------------------------------------------------------- /src/img/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/twitter.png -------------------------------------------------------------------------------- /src/img/useState.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/useState.png -------------------------------------------------------------------------------- /src/img/visitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/src/img/visitor.png -------------------------------------------------------------------------------- /src/theme.js: -------------------------------------------------------------------------------- 1 | import { dark as theme } from 'mdx-deck/themes' 2 | 3 | console.log('dark: ', theme); 4 | 5 | export default { 6 | ...theme, 7 | 8 | colors: { 9 | ...theme.colors, 10 | background: '#272425', 11 | }, 12 | // Customize your presentation theme here. 13 | // 14 | // Read the docs for more info: 15 | // https://github.com/jxnblk/mdx-deck/blob/master/docs/theming.md 16 | // https://github.com/jxnblk/mdx-deck/blob/master/docs/themes.md 17 | 18 | } 19 | -------------------------------------------------------------------------------- /static/images/evergreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sibelius/talk-maringa-ast/f93e14b97e463df0b36229ae8e16eedbaf13abcd/static/images/evergreen.png --------------------------------------------------------------------------------