Skip to content

Commit

Permalink
clean up utils (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
mcnuttandrew committed Jul 13, 2023
1 parent 78ba6ab commit 3cbd372
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 30 deletions.
39 changes: 38 additions & 1 deletion 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"
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 @@ -82,6 +82,41 @@ We include a variety of common projections that you might find useful

You dont have to include any of them or all of them, its presented as an object so you can select what you want.

## Utils

We provide a handful utilities to make the construction of these editors less painful:

```ts
// make a simple modification to a json string
function setIn(
keyPath: (string | number)[],
newValue: any,
content: string
): string;
```

```ts
// a simple prettification algorithm tuned to json specifically
function prettifier(
passedObj: any,
options?: {
indent?: string | undefined;
maxLength?: number | undefined;
replacer?: ((this: any, key: string, value: any) => any) | undefined;
}
): string;
```

```ts
// a simple wrapper around a forgiving json parser
function simpleParse(content: any, defaultVal?: {}): any;
```

```ts
// maybe remove double quotes from a string, handy for some styling tasks
const maybeTrim: (x: string) => string;
```

## Projections

The central design abstraction in Prong are projections. These are lightweight ways to modify the text within the editor to fit your goals.
Expand All @@ -102,6 +137,8 @@ Here are the types for each of the objects
}
```

(Note that `Projection` and `ProjectionProps` are both exported types)

```tsx
{
name: string;
Expand Down
1 change: 1 addition & 0 deletions packages/prong-editor/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ module.exports = {
caughtErrorsIgnorePattern: "^_",
},
],
"@typescript-eslint/restrict-template-expressions": 0,
},
};
5 changes: 3 additions & 2 deletions packages/prong-editor/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export { default as Editor } from "./components/Editor";
export { default as StandardBundle } from "./projections/standard-bundle";
export * as utils from "./lib/utils";
export { default as prettifier } from "./lib/vendored/prettifier";
import { simpleParse, setIn, maybeTrim } from "./lib/utils";
import prettifier from "./lib/vendored/prettifier";
export const utils = { simpleParse, setIn, maybeTrim, prettifier };

export { type Projection, type ProjectionProps } from "./lib/projections";

Expand Down
16 changes: 8 additions & 8 deletions packages/prong-editor/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,11 +319,14 @@ export function applyAllCmds(content: string, updates: UpdateDispatch[]) {

export function createNodeMap(schema: any, doc: string) {
return getMatchingSchemas(schema, doc).then((matches) => {
return matches.reduce((acc, { node, schema }) => {
const [from, to] = [node.offset, node.offset + node.length];
acc[`${from}-${to}`] = (acc[`${from}-${to}`] || []).concat(schema);
return acc;
}, {} as { [x: string]: any });
return matches.reduce(
(acc, { node, schema }) => {
const [from, to] = [node.offset, node.offset + node.length];
acc[`${from}-${to}`] = (acc[`${from}-${to}`] || []).concat(schema);
return acc;
},
{} as { [x: string]: any }
);
});
}

Expand Down Expand Up @@ -396,9 +399,6 @@ export function getCursorPos(state: EditorState) {
return range.anchor;
}

// const climbToRoot = (node: SyntaxNode): SyntaxNode =>
// node.parent ? climbToRoot(node.parent) : node;

export const maybeTrim = (x: string) => {
return x.at(0) === '"' && x.at(-1) === '"' ? x.slice(1, x.length - 1) : x;
};
1 change: 1 addition & 0 deletions sites/docs/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ module.exports = {
caughtErrorsIgnorePattern: "^_",
},
],
"@typescript-eslint/restrict-template-expressions": 0,
},
};
3 changes: 2 additions & 1 deletion sites/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@types/json-schema": "^7.0.12",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@vitejs/plugin-react-swc": "^3.3.2",
Expand All @@ -57,4 +58,4 @@
"vega-datasets": "^2.7.0",
"vite": "^4.4.0"
}
}
}
5 changes: 3 additions & 2 deletions sites/docs/src/examples/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useEffect, useState } from "react";
import {
ProjectionProps,
prettifier,
utils,
} from "../../../../packages/prong-editor/src/index";
import { extractFieldNames, Table } from "./example-utils";
Expand Down Expand Up @@ -203,7 +202,9 @@ export default function DataTable(props: ExtendedProjectionProps): JSX.Element {
data={parsed}
hideTable={hideTable}
updateData={(newData) => {
externalUpdate(utils.setIn(keyPath, prettifier(newData), fullCode));
externalUpdate(
utils.setIn(keyPath, utils.prettifier(newData), fullCode)
);
}}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion sites/docs/src/examples/StyledMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function StyledMarkdown(props: { content: string }) {
return (
<ReactMarkdown
components={{
code({ node, inline, className, children, ...props }) {
code({ inline, className, children, ...props }) {
return !inline ? (
<SyntaxHighlighter
{...props}
Expand Down
7 changes: 5 additions & 2 deletions sites/docs/src/examples/VegaExpressionEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
CompletionSource,
snippet,
} from "@codemirror/autocomplete";
import { utils } from "../../../../packages/prong-editor/src/index";

export type SchemaMap = Record<string, any>;
// vegaExpression.
Expand Down Expand Up @@ -87,7 +86,11 @@ export default function Editor(props: {

useEffect(() => {
if (view && view.state.doc.toString() !== code) {
utils.simpleUpdate(view, 0, view.state.doc.length, code);
view.dispatch(
view.state.update({
changes: { from: 0, to: view.state.doc.length, insert: code },
})
);
}
}, [code, view]);
return (
Expand Down
5 changes: 2 additions & 3 deletions sites/docs/src/examples/VegaLiteStyler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useState, useReducer } from "react";
import {
StandardBundle,
Projection,
prettifier,
Editor,
utils,
} from "../../../../packages/prong-editor/src/index";
Expand Down Expand Up @@ -228,7 +227,7 @@ function pathToKeyPath(path: string) {

function materializeSuggestions(currentCode: string, suggestions: any[]) {
const parsedRoot = utils.simpleParse(currentCode, {});
const allCombined = prettifier(
const allCombined = utils.prettifier(
suggestions.reduce(
(acc, { suggestion }) => merge(acc, { ...suggestion }),
parsedRoot
Expand Down Expand Up @@ -455,7 +454,7 @@ function VegaLiteExampleApp() {
onClick={() =>
dispatch({
type: "setCode",
payload: prettifier(theme),
payload: utils.prettifier(theme),
})
}
>
Expand Down
10 changes: 5 additions & 5 deletions sites/docs/src/examples/VegaLiteUseCase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { VegaLite } from "react-vega";
import "../stylesheets/vega-lite-example.css";

import {
prettifier,
StandardBundle,
Editor,
utils,
Expand All @@ -22,6 +21,7 @@ import {
extractFieldNames,
usePersistedState,
buildInlineDropDownProjection,
classNames,
} from "./example-utils";

const Pill: FC<{ name: string }> = function Pill(props) {
Expand Down Expand Up @@ -68,7 +68,7 @@ const Shelf: FC<{
return (
<div
ref={drop}
className={utils.classNames({
className={classNames({
shelf: true,
"shelf-empty": !isActive && !parsedCurrentValue,
"shelf-full": !isActive && parsedCurrentValue,
Expand Down Expand Up @@ -105,7 +105,7 @@ const UploadAndInline: FC<ProjectionProps> = (props) => {
name="file"
onChange={(event) => {
const file = event.target.files![0];
var reader = new FileReader();
const reader = new FileReader();
reader.onload = function (event) {
const result = event.target!.result;
const inlinedData = utils.simpleParse(result, []);
Expand Down Expand Up @@ -144,7 +144,7 @@ const UploadDataset: FC<{
.map((x: any) => JSON.stringify(x))
.join(",\n\t\t");
setCode(
prettifier(
utils.prettifier(
utils.simpleParse(
utils.setIn(
["data", "values", "values___value"],
Expand Down Expand Up @@ -190,7 +190,7 @@ function buildFileGet(fileName: string, currentCode: string) {
return fetch(`./data/${fileName}`)
.then((x) => x.text())
.then((x) => {
return prettifier(
return utils.prettifier(
utils.simpleParse(
utils.setIn(["data", "values", "values___value"], x, currentCode),
{}
Expand Down
7 changes: 7 additions & 0 deletions sites/docs/src/examples/example-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import {
} from "../../../../packages/prong-editor/src/index";
const { simpleParse, setIn } = utils;

export function classNames(input: Record<string, boolean>) {
return Object.entries(input)
.filter(([_key, value]) => value)
.map(([key]) => key)
.join(" ");
}

export const usePersistedState = (name: string, defaultValue: any) => {
const [value, setValue] = useState(defaultValue);
const nameRef = useRef(name);
Expand Down
12 changes: 7 additions & 5 deletions sites/docs/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,13 @@
dependencies:
"@types/react" "*"

"@types/react-syntax-highlighter@^15.5.7":
version "15.5.7"
resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.7.tgz#bd29020ccb118543d88779848f99059b64b02d0f"
integrity sha512-bo5fEO5toQeyCp0zVHBeggclqf5SQ/Z5blfFmjwO5dkMVGPgmiwZsJh9nu/Bo5L7IHTuGWrja6LxJVE2uB5ZrQ==
dependencies:
"@types/react" "*"

"@types/react@*", "@types/react@^18.2.14":
version "18.2.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127"
Expand Down Expand Up @@ -1661,11 +1668,6 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==

json-schema@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==

json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
Expand Down

0 comments on commit 3cbd372

Please sign in to comment.