React-Code surfer: Rad code slides

Code Surfer

Help to keep this project alive with your support ❤️

Code Surfer adds code highlighting, code zooming, code scrolling, code focusing, code morphing, and fun to MDX Deck slides.

To create a new project run:

npm init code-surfer-deck my-deck
cd my-deck
npm start

Examples

How to use Code Surfer

It may help to know how MDX Deck works first

To use Code Surfer you need to import it and wrap the code you want to show inside <CodeSurfer> tags (the empty lines before and after the codeblock are required):

import { CodeSurfer } from "code-surfer"

# Deck Title

---

<CodeSurfer>

```js
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

Features:

Here is a live deck using all the features (and its mdx source) just in case you prefer to read code instead of docs.

Focus

Add a focus string after the language in the first line of a codeblock to tell Code Surfer what lines and columns you want to focus.

Code Surfer will fade out all the code that isn't focused and, if necessary, zoom it out to fit it in the slide.

<CodeSurfer>

```js 1:2,3[8:10]
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

In the example above 1:2,3[8:10] means: "focus from the line 1 to line 2 and the columns 8 to 10 from line 3". More examples:

  • 5:10 focus lines 5,6,7,8,9 and 10
  • 1,3:5,7 focus lines 1,3,4,5 and 7
  • 2[5] focus column 5 in line 2
  • 2[5:8] focus columns 5, 6, 7 and 8 in line 2
  • 1,2[1,3:5,7],3 focus line 1, columns 1, 3, 4, 5 and 7 in line 2 and line 3

Note: In previous versions of CodeSurfer we used tokens instead of columns.

Steps

Add more codeblocks to add steps to a Code Surfer slide.

<CodeSurfer>

```js
console.log(1);
console.log(2);
console.log(3);
```

```js 1
console.log(1);
console.log(2);
console.log(3);
```

```js
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
```

</CodeSurfer>

You can change the focus and/or the code for different steps and Code Surfer will make the transition between the steps: zooming, scrolling, fading in, fading out, adding and removing lines.

Title and Subtitle

<CodeSurfer>

```js 1 title="Title" subtitle="Look at the first line"
console.log(1);
console.log(2);
console.log(3);
```

```js 2 title="Title" subtitle="and now the second"
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

Themes

Code Surfer Themes

There are many Code Surfer themes available on the @code-surfer/themes package.

You can pass the theme as a prop <CodeSurfer theme={someTheme}>:

import { CodeSurfer } from "code-surfer"
import { nightOwl } from "@code-surfer/themes"

<CodeSurfer theme={nightOwl}>

```js
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

Or set the theme for the whole deck as any other MDX Deck theme:

import { CodeSurfer } from "code-surfer"
import { nightOwl } from "@code-surfer/themes"

export const theme = nightOwl

<CodeSurfer>

```js
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

Exporting the theme like this will also change the text and background colors for slides that aren't using Code Surfer. If you want to keep the colors from a different mdx deck theme you can compose both themes together: export const themes = [codeSurferTheme, mdxDeckTheme]

Custom Styles

You can write your own Code Surfer theme and change the style of the code, title and subtitle:

Themes use Theme UI internally

// custom-theme.js
export default {
  colors: {
    background: "#222",
    text: "#ddd",
    primary: "#a66"
  },
  styles: {
    CodeSurfer: {
      pre: {
        color: "text",
        backgroundColor: "background"
      },
      code: {
        color: "text",
        backgroundColor: "background"
      },
      tokens: {
        "comment cdata doctype": {
          fontStyle: "italic"
        },
        "builtin changed keyword punctuation operator tag deleted string attr-value char number inserted": {
          color: "primary"
        },
        "line-number": {
          opacity: 0.8
        }
      },
      title: {
        backgroundColor: "background",
        color: "text"
      },
      subtitle: {
        color: "#d6deeb",
        backgroundColor: "rgba(10,10,10,0.9)"
      },
      unfocused: {
        // only the opacity of unfocused code can be changed
        opacity: 0.1
      }
    }
  }
};

And use it in your deck like any other theme:

import { CodeSurfer } from "code-surfer"
import customTheme from "./custom-theme"

<CodeSurfer theme={customTheme}>

```js
console.log(1);
console.log(2);
console.log(3);
```

</CodeSurfer>

Languages

Code Surfer uses Prism for parsing different languages, so it supports all the languages supported by Prism.

Most popular languages are supported out of the box, for the rest you need to import them:

import { CodeSurfer } from "code-surfer"
import "prismjs/components/prism-smalltalk"

<CodeSurfer>

```smalltalk
result := a > b
    ifTrue:[ 'greater' ]
    ifFalse:[ 'less or equal' ]
```

</CodeSurfer>

Columns

If you want to show more than one piece of code at the same time, use <CodeSurferColumns>:

import { CodeSurferColumns, Step } from "code-surfer"

<CodeSurferColumns>

<Step subtitle="First Step">

```js
console.log(1);
console.log(2);
```

```js
console.log("a");
console.log("b");
```

</Step>

<Step subtitle="Second Step">

```js 2
console.log(1);
console.log(2);
```

```js 2
console.log("a");
console.log("b");
```

</Step>

</CodeSurferColumns>

Each <Step> can have its own title and subtitle.

You can use different themes for each column: <CodeSurferColumns themes={[nightOwl, ultramin]}>. And change the relative size of the columns with <CodeSurferColumns sizes={[1,3]}>.

Columns aren't only for code, you can use them for any kind of content:

import { CodeSurferColumns, Step } from "code-surfer"
import MyComponent from "./my-component.jsx"

<CodeSurferColumns>

<Step>

```js
console.log(1);
console.log(2);
```

# Some Markdown

</Step>

<Step>

```js 2
console.log(1);
console.log(2);
```

<MyComponent/>

</Step>

</CodeSurferColumns>

Import Code

Instead of writing the code inside codeblocks you can import it from a file:

import { CodeSurfer } from "code-surfer"

<CodeSurfer>

```js 5:10 file=./my-code.js
```

```js file=./my-other-code.js
```

</CodeSurfer>

Line Numbers

To show line numbers add the showNumbers flag to the first step:

import { CodeSurfer } from "code-surfer"

<CodeSurfer>

```js showNumbers
console.log(1);
console.log(2);
console.log(3);
```

```js
console.log(1);
console.log(2);
console.log(4);
```

</CodeSurfer>

Diffs

Codeblocks can also be diffs. This is particularly useful when using empty diffs for code that doesn't change:

import { CodeSurfer } from "code-surfer"

<CodeSurfer>

```js
console.log(1);
console.log(2);
console.log(3);
```

```diff 1 subtitle="log 1"

```

```diff 2 subtitle="log 2"

```

```diff 3 subtitle="log 3"

```

</CodeSurfer>

Related

Support Code Surfer

You can help keep this project alive.

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Backers

Thank you to all our backers! ? [Become a backer]

Contributors

This project exists thanks to all the people who contribute.

Comments

  • Bump object-path from 0.11.4 to 0.11.5
    Bump object-path from 0.11.4 to 0.11.5

    Oct 19, 2020

    Bumps object-path from 0.11.4 to 0.11.5.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Web component ?
    Web component ?

    Nov 26, 2020

    Hello,

    I made a simple web-component wrapper for code-surfer. https://github.com/gilsdav/code-surfer-wc

    Do you plan to make an official one ?

    Reply
  • Import code from file not working with mdx-deck@4
    Import code from file not working with [email protected]

    Dec 1, 2020

    I can't seem to get the following to work with [email protected] It's currently just showing blank screen. I don't think it's even reading the file.

    <CodeSurfer>
        
    ```js 5:10 file=./file.js
    ```
        
    </CodeSurfer>
    
    Reply
  • Switching slides is unreliable in Firefox
    Switching slides is unreliable in Firefox

    Jan 29, 2021

    Steps to reproduce:

    1. Create a new deck:
      npm init code-surfer-deck my-deck
      cd my-deck
      npm start
      
    2. Open localhost:8000 in Firefox.
    3. Press right arrow a few times.

    What will eventually happen is that Code Surfer doesn't react to one right-arrow press, and doesn't advance the step from 1 to 2. Next time the key is pressed, the code will jump instantly to 2 and then animate between 2 and 3.

    To reproduce this more reliably, when Code Surfer doesn't respond to a right-arrow press, press the left-arrow instead. This will jump instantly to 2 and then animate back from 2 to 1 - this allows you to observe the behavior when it happens on slide 3 of the example deck, which has only two steps.

    Reply
  • Export makeTheme for external use
    Export makeTheme for external use

    May 15, 2021

    Hi @pomber ! 👋 Long time no speak.

    I would like to use the makeTheme function elsewhere in my code (to create custom themes based on other prism-react-renderer themes).

    Would it be possible to export it like this?

    Reply
  • Improve theme styles
    Improve theme styles

    May 15, 2021

    Hi @pomber ! 👋 Hope you are well!

    Here's a small PR to slightly improve the VS Code Dark (vsDark) theme.

    Before:

    Screen Shot 2021-05-15 at 15 33 42

    After:

    Screen Shot 2021-05-15 at 15 35 12

    Real VS Code:

    Screen Shot 2021-05-15 at 15 35 17
    Reply
  • Add Line Annotations
    Add Line Annotations

    May 15, 2021

    Followup to https://github.com/pomber/code-surfer/pull/51 with the new version of Code Surfer

    @pomber what are your thoughts on this?

    Simple example:

    <CodeSurfer
      steps={[
        {
          code: `This line will have an "abc" annotation here ->
    This line will have an "def" annotation here ->`,
          lang: 'jsx',
          annotations: {
            1: <span>abc</span>,
            2: <span>def</span>,
          },
        },
      ]}
      progress={0}
    />
    

    More complex example:

    <CodeSurfer
      lang="jsx"
      steps={[
        {
          code: require('!raw-loader!./packages/example-1-simple-cra/src/index.js'),
          lang: 'jsx',
          annotations: {
            1: (
              <Brace side="left" height="5em">
                JavaScript
              </Brace>
            ),
            8: (
              <Brace side="right" height="3em" style={{}}>
                JSX
              </Brace>
            ),
            13: (
              <Brace side="left" height="3em">
                JavaScript
              </Brace>
            ),
            22: (
              <Brace side="right" height="6em" style={{ marginTop: '-2.5em' }}>
                JSX
              </Brace>
            ),
            27: (
              <>
                <Brace side="top" width="5.7em" style={{ marginLeft: '-1.3em' }}>
                  JavaScript
                </Brace>
                <Brace side="top" width="2.2em" style={{ marginLeft: '5.2em' }}>
                  JSX
                </Brace>
                <Brace side="top" width="13.3em" style={{ marginLeft: '8.2em' }}>
                  JavaScript
                </Brace>
              </>
            ),
          },
        },
      ]}
      progress={0}
    />
    

    Screen Shot 2021-05-15 at 19 06 28

    Reply
  • `code-surfer-types` missing from published package
    `code-surfer-types` missing from published package

    May 16, 2021

    It seems like the code-surfer-types module is missing from the published package:

    Screen Shot 2021-05-16 at 12 29 14

    And installing it using npm / yarn doesn't work either:

    yarn add --dev code-surfer-types
    yarn add v1.22.10
    [1/4] 🔍  Resolving packages...
    error An unexpected error occurred: "https://registry.yarnpkg.com/code-surfer-types: Not found".
    info If you think this is a bug, please open a bug report with the information provided in "/Users/k/p/courses/slide-decks-new/yarn-error.log".
    info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
    
    Reply
  • Set visual line-height on `pre` or `code` elements?
    Set visual line-height on `pre` or `code` elements?

    May 16, 2021

    Hi @pomber !

    I'm trying to use the new version of code-surfer, and there is a strange behavior with line-height.

    I am trying to set line-height on the pre and code elements like this:

    export const mdxDeckTheme = {
      styles: {
        CodeSurfer: {
          pre: {
            lineHeight: 1.3,
          },
          code: {
            lineHeight: 1.3,
          },
        },
      },
    };
    

    This does apply the line-heights to those elements, but does not allow for setting the visual line-height (the height of a line of code, proportional to the font-size).

    This doesn't appear to be possible with code-surfer... or am I missing something?

    Reply
  • New maintainers?
    New maintainers?

    May 16, 2021

    Hi @pomber! 👋

    It seems like you don't have much time to devote to this project.

    Would you be open to one or more new maintainers taking over?

    I don't have a lot of time myself, but I saw that @mhartington, @vlsi and @NieDzejkob have opened some issues and shown continued engagement with the project.

    Would be really great to have some more movement on this project!

    Reply
  • mdx-deck v3 support
    mdx-deck v3 support

    Jul 21, 2019

    will code surfer v2 works with mdx-deck v3?

    Reply
  • update to mdx-deck v3
    update to mdx-deck v3

    Jul 22, 2019

                                                                                                                                                                                                           
    Reply
  • Problem with code surfer and mdx-deck-live-code
    Problem with code surfer and mdx-deck-live-code

    Jan 30, 2019

    it is rendering this:

    image

    it does not take \n new lines in consideration and it does not have syntax hightlight either


    <CodeSurfer title="Sum Type" lang="javascript" code={require('!raw-loader!./samples/sumType.js')} />

    you can reproduce here https://github.com/sibelius/functional-types-abstractions/blob/master/src/deck.mdx#L443

    yarn start

    here is the sumType file https://github.com/sibelius/functional-types-abstractions/blob/master/src/samples/sumType.js

    Reply
  • Seems to be incompatible with mdx-deck 2.0
    Seems to be incompatible with mdx-deck 2.0

    Mar 18, 2019

    First, a peer dep of styled-components is required for it to work and it's not mentioned in the readme

    Second, it fails with withDeck not being a function

    Reply
  • Document how to install
    Document how to install "raw-loader" in examples

    Aug 26, 2018

    And should it be a --save dependency, or a --save-dev devDependency?

    Reply
  • Support for other languages in syntax?
    Support for other languages in syntax?

    Aug 29, 2018

    Heey !

    This is amazing and I am in love !

    I am doing a presentation that shows some HTML code and I was just wondering if there is support for other languages or if it's something I am missing in mdx-deck ?

    Reply
  • Line Annotations
    Line Annotations

    Feb 28, 2019

    Hi! First of all, thanks for this great project! It's super useful.

    I'm creating teaching materials (course material) with this tool, and I would like to annotate certain parts of the source code with arrows, indicators, labels and other diagram elements that are not in monospace font (see examples below) - some similarities to LaTeX brackets / parentheses / braces. I tried to use the current APIs, but I didn't get very far.

    I ended up creating an MVP solution (described below) and I wanted to get feedback on it :)

    TODO

    Ideal Examples

    screen shot 2019-02-26 at 15 03 20

    what-is-an-xml-element

    images

    698932 css-selectors-lrg

    Current MVP Solution

    In order to do the very minimum of implementation work with the largest impact, I have created an MVP for only line annotations that allows for strings and React components to be passed via a new property called lineAnnotations in the step object, which is an object mapping lines to their annotation content.

    The MVP is currently published under @upleveled/[email protected] (depends on @upleveled/[email protected]).

    To try it out:

    yarn add --dev @upleveled/mdx-deck-code-surfer
    

    It allows for things like this:

    kapture 2019-02-28 at 12 51 48

    via this code:

    <CodeSurfer
      title="Example of HTML code"
      code={require('!raw-loader!./first-example.html')}
      lang="markup"
      steps={[
        {},
        {
          lineAnnotations: {
            4: (
              <span style={{ fontFamily: 'BlinkMacSystemFont' }}>
                {' '}
                <Arrow
                  angle={270}
                  length={300}
                  style={{
                    verticalAlign: '-4px',
                    width: '300px',
                  }}
                  color="white"
                /> Opening Tag
              </span>
            ),
            6: (
              <span style={{ fontFamily: 'BlinkMacSystemFont' }}>
                {' '}
                <Arrow
                  angle={270}
                  length={292}
                  style={{
                    verticalAlign: '-4px',
                    width: '292px',
                  }}
                  color="white"
                /> Closing Tag
              </span>
            ),
          },
        },
      ]}
    />
    

    What are your opinions of this API?

    More specifically:

    1. Do you have any recommendations on a better way to achieve what I'm intending here?
    2. Should I use Scroller.Element at all?
    3. Should this API be more generalized? More like:
    interface Step {
      annotations?: {
        lines?: {
          [key: number]: JSX.Element | string
        }
      }
    }
    
    1. Should I update the step-parser.js test file?
    Reply
  • `mdx-deck build` errors with
    `mdx-deck build` errors with "Cannot read property 'step' of null"

    Aug 27, 2018

    It seems mdx-deck build doesn't work if I use CodeSurfer (regardless of how raw-loader is used).. I get this:

    [mdx-deck] building
    [mdx-deck] rendering static html
    Missing HeadProvider
    [err] TypeError: Cannot read property 'step' of null
        at _class2.render (./node_modules/mdx-deck-code-surfer/dist/deck-code-surfer.js:93:30)
        at processChild (./node_modules/react-dom/cjs/react-dom-server.node.development.js:2207:18)
        at resolve (./node_modules/react-dom/cjs/react-dom-server.node.development.js:2064:5)
        at ReactDOMServerRenderer.render (./node_modules/react-dom/cjs/react-dom-server.node.development.js:2383:22)
        at ReactDOMServerRenderer.read (./node_modules/react-dom/cjs/react-dom-server.node.development.js:2357:19)
        at renderToString (./node_modules/react-dom/cjs/react-dom-server.node.development.js:2729:25)
        at renderHTML (./node_modules/mdx-deck/lib/html.js:57:16)
        at <anonymous>
        at process._tickCallback (internal/process/next_tick.js:188:7)
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    
    Reply
  • Code Surfer v3 RC
    Code Surfer v3 RC

    Oct 1, 2019

    Code Surfer v3 is almost done.

    If anyone wants to help me test it: create a new deck with npm init code-surfer-deck my-deck, work on your deck, and let me know if you have any problem.

    Here are the docs.

    Improvements to the docs are also welcome.

    Reply
  • Code Surfer v3
    Code Surfer v3

    May 11, 2019

    Rewriting Code Surfer from scratch.


    Features for v2.0.0:

    • [x] compatibility with mdx-deck v2.0 (#53 #54)
    • [x] highlight lines
    • [x] zoom in and out
    • [x] code transitions
    • [x] zoom out if code is too long (#29)
    • [x] title and subtitle
    • [x] more themes
    • [x] allow overriding styles (#52)
    • [x] create-code-surfer-deck package
    • [x] load more language syntaxes
    • [x] support diffs
    • [x] highlight tokens
    • [x] error handling
    • [x] load code from file
    • [x] split layout (#44)
    • [x] notes
    • [x] read offOpacity from theme (#63)
    • [x] logo
    • [x] readme

    After v2.0.0:

    • line annotations (#51)
    • live preview layout (tweet)

    v2 api looks like this:

    
    import { CodeSurferLayout } from "code-surfer"
    
    # My Deck
    
    ---
    
    <CodeSurferLayout>
    
    ```js
    module.exports = {
      entry: "./path/to/my/entry/file.js",
    }
    ```
    
    ```js 4,7 subtitle="Entry and Output"
    const path = require("path")
    
    module.exports = {
      entry: "./path/to/my/entry/file.js",
      output: {
        path: path.resolve(__dirname, "dist"),
        filename: "my-first-webpack.bundle.js",
      },
    }
    ```
    
    ```js 5,7:9
    const path = require("path")
    
    module.exports = {
      output: {
        filename: "my-first-webpack.bundle.js",
      },
      module: {
        rules: [{ test: /\.txt$/, use: "raw-loader" }],
      },
    }
    ```
    
    </CodeSurferLayout>
    
    Reply