daKmoR/rocket

[feature] mdjs plugins

bennypowers opened this issue · 0 comments

Users should be able to extends mdjs, adding their own directives which transform code.

Use Case: Copy Snippet

This simple use case would let a user define a new directive which simply wraps the code block in a custom element. It has no parameters, just does what it says on the box.

Before

​    <code-copy>
​    
    ```bash
    npm init @apollo-elements
    ```
​        
    </code-copy>

After

    ```bash copy
    npm init @apollo-elements
    ```

Use Case: Code Tabs

This more advanced use case lets a user define a directive that takes a parameter, namely the ID for a tab, which references a config object that includes tab label and icon

Before

    <code-tabs>

    <code-tab package="lit">

    ```js
    html`<p>I'm a little teapot</p>`
    ```

    </code-tab>

    <code-tab package="FAST">

    ```js
    html<MyComponent>`<p>I'm a little teapot</p>`
    ```

    </code-tab>

    </code-tabs>

After

     <code-tabs>

    ```js tab lit
    html`<p>I'm a little teapot</p>`
    ```

    ```js tab FAST
    html<MyComponent>`<p>I'm a little teapot</p>`
    ```

    </code-tabs>

Use Case: Code Demo

Similar to the above, you can imaging a graphql live directive which lets the viewer execute a graphql query in-browser, or a graphql live uri=https://api.spacex.land/graphql directive which queries from a specific endpoint.

Proposed Plugin API

Consider this a strawman proposal

interface Plugin {
  name: string;
  directive(directive: string, code: string): BlockProcessor;
}

interface Directive {
  language: string;
  command: string; // first command, non-nullable
  params: string[]; // rest, split by whitespace
}

declare class BlockProcessor {
  config: Config; // injected behind-the-scenes
  directive: Directive;
  transform(code: string): string; // returns the replaced code-block
  loadModules(): string[]; // returns any module scripts to load on the page
}