Git Product home page Git Product logo

parser's Introduction

@observablehq/parser

Node CI

To parse a cell:

import {parseCell} from "@observablehq/parser";

const cell = parseCell(`hello = "world"`);

Examples

(In these examples, the node.start and node.end indexes into the input string are not shown for brevity. If options.locations is true, node.loc will also be populated with the line and column numbers.)

An expression cell (where cell.body is a type of expression):

1 + 2
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "BinaryExpression",
    "left": {
      "type": "Literal",
      "value": 1,
      "raw": "1"
    },
    "operator": "+",
    "right": {
      "type": "Literal",
      "value": 2,
      "raw": "2"
    }
  }
}

A block cell (where cell.body is a BlockStatement):

{
  return 1 + 2;
}
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "BlockStatement",
    "body": [
      {
        "type": "ReturnStatement",
        "argument": {
          "type": "BinaryExpression",
          "left": {
            "type": "Literal",
            "value": 1,
            "raw": "1"
          },
          "operator": "+",
          "right": {
            "type": "Literal",
            "value": 2,
            "raw": "2"
          }
        }
      }
    ]
  }
}

An empty cell (where cell.body is null):

{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": null
}

A named expression cell (where cell.id is an Identifier):

foo = 42
{
  "type": "Cell",
  "id": {
    "type": "Identifier",
    "name": "foo"
  },
  "async": false,
  "generator": false,
  "body": {
    "type": "Literal",
    "value": 42,
    "raw": "42"
  }
}

A named block cell (where cell.id is an Identifier):

foo = {
  return 42;
}
{
  "type": "Cell",
  "id": {
    "type": "Identifier",
    "name": "foo"
  },
  "async": false,
  "generator": false,
  "body": {
    "type": "BlockStatement",
    "body": [
      {
        "type": "ReturnStatement",
        "argument": {
          "type": "Literal",
          "value": 42,
          "raw": "42"
        }
      }
    ]
  }
}

An asynchronous expression cell (where cell.async is true):

2 * await value
{
  "type": "Cell",
  "id": null,
  "async": true,
  "generator": false,
  "body": {
    "type": "BinaryExpression",
    "left": {
      "type": "Literal",
      "value": 2,
      "raw": "2"
    },
    "operator": "*",
    "right": {
      "type": "AwaitExpression",
      "argument": {
        "type": "Identifier",
        "name": "value"
      }
    }
  }
}

A generator expression cell (where cell.generator is true):

yield* [1, 2, 3]
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": true,
  "body": {
    "type": "YieldExpression",
    "delegate": true,
    "argument": {
      "type": "ArrayExpression",
      "elements": [
        {
          "type": "Literal",
          "value": 1,
          "raw": "1"
        },
        {
          "type": "Literal",
          "value": 2,
          "raw": "2"
        },
        {
          "type": "Literal",
          "value": 3,
          "raw": "3"
        }
      ]
    }
  }
}

A viewof expression cell (where cell.id is a ViewExpression):

viewof x = DOM.range()
{
  "type": "Cell",
  "id": {
    "type": "ViewExpression",
    "id": {
      "type": "Identifier",
      "name": "x"
    }
  },
  "async": false,
  "generator": false,
  "body": {
    "type": "CallExpression",
    "callee": {
      "type": "MemberExpression",
      "object": {
        "type": "Identifier",
        "name": "DOM"
      },
      "property": {
        "type": "Identifier",
        "name": "range"
      },
      "computed": false
    },
    "arguments": []
  }
}

A viewof reference within an expression cell (where cell.body contains a ViewExpression):

viewof x.tagName
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "MemberExpression",
    "object": {
      "type": "ViewExpression",
      "id": {
        "type": "Identifier",
        "name": "x"
      }
    },
    "property": {
      "type": "Identifier",
      "name": "tagName"
    },
    "computed": false
  }
}

An import cell (where cell.body is an ImportDeclaration):

import {foo} from "module"
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "ImportDeclaration",
    "specifiers": [
      {
        "type": "ImportSpecifier",
        "view": false,
        "imported": {
          "type": "Identifier",
          "name": "foo"
        },
        "local": {
          "type": "Identifier",
          "name": "foo"
        }
      }
    ],
    "source": {
      "type": "Literal",
      "value": "module",
      "raw": "\"module\""
    }
  }
}

Importing a view (where specifier.view is true):

import {viewof foo} from "module"
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "ImportDeclaration",
    "specifiers": [
      {
        "type": "ImportSpecifier",
        "view": true,
        "imported": {
          "type": "Identifier",
          "name": "foo"
        },
        "local": {
          "type": "Identifier",
          "name": "foo"
        }
      }
    ],
    "source": {
      "type": "Literal",
      "value": "module",
      "raw": "\"module\""
    }
  }
}

Importing a view imports both the view symbol (viewof foo) and the value symbol (foo). Likewise, if the specified view is renamed during import (e.g., viewof foo as bar), both the view symbol and the value symbol are renamed (e.g., viewof bar and bar).

Importing with injection (where declaration.injections is present):

import {chart} with {sales as data} from "@mbostock/d3-bar-chart"
{
  "type": "Cell",
  "id": null,
  "async": false,
  "generator": false,
  "body": {
    "type": "ImportDeclaration",
    "specifiers": [
      {
        "type": "ImportSpecifier",
        "view": false,
        "imported": {
          "type": "Identifier",
          "name": "chart"
        },
        "local": {
          "type": "Identifier",
          "name": "chart"
        }
      }
    ],
    "injections": [
      {
        "type": "ImportSpecifier",
        "view": false,
        "imported": {
          "type": "Identifier",
          "name": "sales"
        },
        "local": {
          "type": "Identifier",
          "name": "data"
        }
      }
    ],
    "source": {
      "type": "Literal",
      "value": "@mbostock/d3-bar-chart",
      "raw": "\"@mbostock/d3-bar-chart\""
    }
  }
}

For an injection, specifier.imported and specifier.local are reversed compared to a normal specifier: they are from the perspective of the imported module rather than the importing module. So in the example above, the importing module’s variable sales is injected into the imported module (the chart), replacing the variable data.

Injecting a view injects both the view symbol (viewof foo) and the value symbol (foo). Likewise, if the specified view is renamed during injection (e.g., viewof foo as bar), both the view symbol and the value symbol are renamed (e.g., viewof bar and bar).

API Reference

# parseCell(input[, options]) <>

Returns a cell.

# parseModule(input[, options]) <>

Returns a program.

# peekId(input) <>

Tries to find the ID of a cell given a snippet of its contents, and returns it as a string if found.

Cell

# cell.id

The name of the cell: null if the cell is anonymous; otherwise an Identifier or a ViewExpression.

# cell.body

The body of the cell: null for an empty cell; an ImportDeclaration for an import cell; otherwise a BlockStatement or an expression node.

# cell.async

A boolean indicating whether the cell body is asynchronous (i.e., whether it contains an await statement). False for import and empty cells.

# cell.generator

A boolean indicating whether the cell body is a generator (i.e., whether it contains a yield statement). False for import and empty cells.

ViewExpression

# view.id

The view identifier: an Identifier.

ImportDeclaration

# declaration.injections

An array of ImportSpecifier nodes, if the import declaration has a with clause, and otherwise null.

ImportSpecifier

# specifier.view

A boolean indicating whether the import specifies a view.

Program

# program.cells

An array of cells.

parser's People

Contributors

mbostock avatar jashkenas avatar dependabot-preview[bot] avatar tmcw avatar greenkeeper[bot] avatar mourner avatar nebrius avatar visnup avatar asg017 avatar sydneypalumbo avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.