Skip to content

Commit

Permalink
improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mcnuttandrew committed Jul 17, 2023
1 parent 3aca382 commit a0dc278
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 15 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"pickr",
"postactions",
"preactions",
"Projectional",
"retarget",
"Retargeted",
"ruleset",
Expand Down
63 changes: 53 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This is the Prong editor framework. The goal of this system is to provide a simple way to create in-situ editor extensions for in-browser editors of JSON domain specific languages.
The basic dependencies of this system are code mirror (which we wrap) and react (which we use as means to specify the extensions).

This is described in our upcoming paper "Projectional Editors for JSON DSLs". Please note that this is research grade software, so there are bugs and issues throughout.
This is described in our upcoming paper "Projectional Editors for JSON-DSLs". Please note that this is research grade software, so there are bugs and issues throughout.

## Quick start example usage

Expand Down Expand Up @@ -45,6 +45,43 @@ yarn add prong-editor

Dont forget to import our css file!

### What about authoring my own projections??

Authoring your own projections is also reasonably straightforward. We have a number of examples throughout the code base that you might look at for inspiration of how to define ad hoc projections (cf sites/docs/src/examples/) as well as more structured repeatable ones (cf packages/prong-editor/projections/). But should you want a quick start, here's an example projection that will appear in the floating tooltip menu

```tsx
import { utils, Projection } from "prong-editor";
import friendlyWords from "friendly-words";

const titleCase = (word: string) => `${word[0].toUpperCase()}${word.slice(1)}`;
const pick = (arr: any[]) => arr[Math.floor(Math.random() * arr.length)];

function generateName() {
const adj = pick(friendlyWords.predicates);
const obj = titleCase(pick(friendlyWords.objects));
return `${adj}${obj}`;
}

const RandomWordProjection: Projection = {
// where to put the projection
query: { type: "regex", query: /".*"/ },
// should it appear in the tooltip or inline?
type: "tooltip",
// what should it look like
projection: ({ keyPath, setCode, fullCode }) => {
const click = () =>
setCode(utils.setIn(keyPath, `"${generateName()}"`, fullCode));
return <button onClick={click}>Random Word</button>;
},
// what group should the projection appear in
name: "Utils",
};

export default RandomWordProjection;
```

See below for [additional details](#projections) on the semantics of defin

## Component

The library consists of a single component it has a type like
Expand Down Expand Up @@ -153,26 +190,32 @@ The projection creates the specific element that inserted into the menu, it expe

```tsx
interface ProjectionProps {
// code snippet of the current node, it is provided as a convenience as you could get it from fullCode.slice(node.from, node.to)
currentValue: any;

// a list of cursor positions, it is useful for interacting with the cursor. diagnosticErrors is an array of lint errors.
cursorPositions: any[];

// lint errors from the current position (based on the schema)
diagnosticErrors: Diagnostic[];

// the full code in the document at the current moment.
fullCode: string;

// the access path for the value in the json object, note that if trying to access the value in a property (eg if you have [{"a": "b"}] and you want b) you need to add a `___value` tailing element. So for that example we would do `[0, "a", "a___value"]`.
keyPath: (string | number)[];

// the AST node generated by code mirror (see [their docs](https://lezer.codemirror.net/docs/ref/#common.SyntaxNode) for more details).
node: SyntaxNode;

// allows you to set the code in the document, it will trigger an onUpdate event.
setCode: (code: string) => void;

// typings the inferred typings from the JSON Schema for the node.
typings: any[];
}
```

currentValue is the code snippet of the current node, it is provided as a convenience as you could get it from fullCode.slice(node.from, node.to)
cursorPositions is a list of cursor positions, it is useful for interacting with the cursor.
diagnosticErrors is an array of lint errors.
fullCode is the full code in the document at the current moment.
keyPath is the access path for the value in the json object, note that if trying to access the value in a property (eg if you have [{"a": "b"}] and you want b) you need to add a `___value` tailing element. So for that example we would do `[0, "a", "a___value"]`.
node is the AST node generated by code mirror (see [their docs](https://lezer.codemirror.net/docs/ref/#common.SyntaxNode) for more details).
setCode allows you to set the code in the document, it will trigger an onUpdate event.
typings the inferred typings from the JSON Schema for the node.

### Inline Projection

Use this projection type to place projections into the editor itself.
Expand Down
25 changes: 20 additions & 5 deletions packages/prong-editor/src/lib/projections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,29 @@ import InlineProjectWidgetFactory from "./widgets/inline-projection-widget";
import { Diagnostic } from "@codemirror/lint";

export interface ProjectionProps {
node: SyntaxNode;
keyPath: (string | number)[];
// code snippet of the current node, it is provided as a convenience as you could get it from fullCode.slice(node.from, node.to)
currentValue: any;
setCode: (code: string) => void;

// a list of cursor positions, it is useful for interacting with the cursor. diagnosticErrors is an array of lint errors.
cursorPositions: any[];

// lint errors from the current position (based on the schema)
diagnosticErrors: Diagnostic[];

// the full code in the document at the current moment.
fullCode: string;

// the access path for the value in the json object, note that if trying to access the value in a property (eg if you have [{"a": "b"}] and you want b) you need to add a `___value` tailing element. So for that example we would do `[0, "a", "a___value"]`.
keyPath: (string | number)[];

// the AST node generated by code mirror (see [their docs](https://lezer.codemirror.net/docs/ref/#common.SyntaxNode) for more details).
node: SyntaxNode;

// allows you to set the code in the document, it will trigger an onUpdate event.
setCode: (code: string) => void;

// typings the inferred typings from the JSON Schema for the node.
typings: any[];
diagnosticErrors: Diagnostic[];
cursorPositions: any[];
}

interface ProjectionBase {
Expand Down

0 comments on commit a0dc278

Please sign in to comment.