Skip to content

Commit

Permalink
Use encode/decode instead of manual splits
Browse files Browse the repository at this point in the history
  • Loading branch information
sdirix committed Feb 3, 2022
1 parent be63a89 commit 40b2367
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 30 deletions.
13 changes: 7 additions & 6 deletions packages/angular-material/src/other/master-detail/master.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
ArrayControlProps,
ControlElement,
createDefaultValue,
decode,
findUISchema,
getFirstPrimitiveProp,
JsonFormsState,
Expand All @@ -47,12 +48,12 @@ import {
const keywords = ['#', 'properties', 'items'];

export const removeSchemaKeywords = (path: string) => {
return path
.split('/')
.filter(s => !some(keywords, key => key === s))
.join('.')
.split('~1')
.join('/')
return decode(
path
.split('/')
.filter(s => !some(keywords, key => key === s))
.join('.')
);
};

@Component({
Expand Down
3 changes: 2 additions & 1 deletion packages/angular-material/src/other/table.renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
ArrayControlProps,
ControlElement,
deriveTypes,
encode,
isObjectArrayControl,
isPrimitiveArrayControl,
JsonSchema,
Expand Down Expand Up @@ -101,7 +102,7 @@ export class TableRenderer extends JsonFormsArrayControl {
): ColumnDescription[] => {
if (schema.type === 'object') {
return this.getValidColumnProps(schema).map(prop => {
const encProp = prop.split('/').join('~1');
const encProp = encode(prop);
const uischema = controlWithoutLabel(`#/properties/${encProp}`);
if (!this.isEnabled()) {
setReadonly(uischema);
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/generators/uischema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
Layout,
UISchemaElement
} from '../models';
import { deriveTypes, resolveSchema } from '../util';
import { deriveTypes, encode, resolveSchema } from '../util';

/**
* Creates a new ILayout.
Expand Down Expand Up @@ -162,8 +162,7 @@ const generateUISchema = (
const nextRef: string = currentRef + '/properties';
Object.keys(jsonSchema.properties).map(propName => {
let value = jsonSchema.properties[propName];
propName = propName.split('/').join('~1');
const ref = `${nextRef}/${propName}`;
const ref = `${nextRef}/${encode(propName)}`;
if (value.$ref !== undefined) {
value = resolveSchema(rootSchema, value.$ref);
}
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/util/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import startCase from 'lodash/startCase';

import { ControlElement, JsonSchema, LabelDescription } from '../models';
import { decode } from './path';

const deriveLabel = (
controlElement: ControlElement,
Expand All @@ -36,9 +37,7 @@ const deriveLabel = (
}
if (typeof controlElement.scope === 'string') {
const ref = controlElement.scope;
let label = ref.substr(ref.lastIndexOf('/') + 1);
label = label.split('~1').join('/').split('~0').join('~');

const label = decode(ref.substr(ref.lastIndexOf('/') + 1));
return startCase(label);
}

Expand Down
15 changes: 12 additions & 3 deletions packages/core/src/util/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ export const toDataPathSegments = (schemaPath: string): string[] => {
.replace(/oneOf\/[\d]\//g, '');
const segments = s.split('/');

const decodedSegments = segments.map(segment => {
return segment.split('~1').join('/').split('~0').join('~');
});
const decodedSegments = segments.map(decode);

const startFromRoot = decodedSegments[0] === '#' || decodedSegments[0] === '';
const startIndex = startFromRoot ? 2 : 1;
Expand Down Expand Up @@ -92,3 +90,14 @@ export const composeWithUi = (scopableUi: Scopable, path: string): string => {

return isEmpty(segments) ? path : compose(path, segments.join('.'));
};

/**
* Encodes the given segment to be used as part of a JSON Pointer
*
* JSON Pointer has special meaning for "/" and "~", therefore these must be encoded
*/
export const encode = (segment: string) => segment?.replace(/~/g, '~0').replace(/\//g, '~1');
/**
* Decodes a given JSON Pointer segment to its "normal" representation
*/
export const decode = (pointerSegment: string) => pointerSegment?.replace(/~1/g, '/').replace(/~0/, '~');
7 changes: 3 additions & 4 deletions packages/core/src/util/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import isEmpty from 'lodash/isEmpty';
import get from 'lodash/get';
import { JsonSchema } from '../models';
import { decode, encode } from './path';

/**
* Map for storing refs and the respective schemas they are pointing to.
Expand Down Expand Up @@ -115,9 +116,7 @@ export const resolveSchema = (
if (isEmpty(schema)) {
return undefined;
}
const validPathSegments = schemaPath.split('/').map(segment => {
return segment.split('~1').join('/').split('~0').join('~');
});
const validPathSegments = schemaPath.split('/').map(decode);
let resultSchema = schema;
for (let i = 0; i < validPathSegments.length; i++) {
let pathSegment = validPathSegments[i];
Expand All @@ -138,7 +137,7 @@ export const resolveSchema = (
resultSchema?.anyOf ?? []
);
for (let item of schemas) {
curSchema = resolveSchema(item, validPathSegments.slice(i).map(s => s.split('/').join('~1')).join('/'));
curSchema = resolveSchema(item, validPathSegments.slice(i).map(encode).join('/'));
if (curSchema) {
break;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/material/src/complex/MaterialTableControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ import {
Paths,
Resolve,
JsonFormsRendererRegistryEntry,
JsonFormsCellRendererRegistryEntry
JsonFormsCellRendererRegistryEntry,
encode
} from '@jsonforms/core';
import DeleteIcon from '@mui/icons-material/Delete';
import ArrowDownward from '@mui/icons-material/ArrowDownward';
Expand Down Expand Up @@ -206,18 +207,17 @@ interface NonEmptyCellComponentProps {
cells?: JsonFormsCellRendererRegistryEntry[],
isValid: boolean
}
const NonEmptyCellComponent = React.memo(({path, propName, schema,rootSchema, errors, enabled, renderers, cells, isValid}:NonEmptyCellComponentProps) => {
propName = propName?.split('/').join('~1');
const NonEmptyCellComponent = React.memo(({path, propName, schema, rootSchema, errors, enabled, renderers, cells, isValid}:NonEmptyCellComponentProps) => {
return (
<NoBorderTableCell>
{schema.properties ? (
<DispatchCell
schema={Resolve.schema(
schema,
`#/properties/${propName}`,
`#/properties/${encode(propName)}`,
rootSchema
)}
uischema={controlWithoutLabel(`#/properties/${propName}`)}
uischema={controlWithoutLabel(`#/properties/${encode(propName)}`)}
path={path}
enabled={enabled}
renderers={renderers}
Expand Down
9 changes: 4 additions & 5 deletions packages/vanilla/src/complex/TableArrayControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ import {
RankedTester,
Resolve,
Test,
getControlPath
getControlPath,
encode
} from '@jsonforms/core';
import { DispatchCell, withJsonFormsArrayControlProps } from '@jsonforms/react';
import { withVanillaControlProps } from '../util';
Expand Down Expand Up @@ -167,13 +168,11 @@ class TableArrayControl extends React.Component<ArrayControlProps & VanillaRende
childPath,
prop.toString()
);
let encProp = prop;
encProp = prop.split('/').join('~1');
return (
<td key={childPropPath}>
<DispatchCell
schema={Resolve.schema(schema, `#/properties/${encProp}`, rootSchema)}
uischema={createControlElement(encProp)}
schema={Resolve.schema(schema, `#/properties/${encode(prop)}`, rootSchema)}
uischema={createControlElement(encode(prop))}
path={childPath + '.' + prop}
/>
</td>
Expand Down

0 comments on commit 40b2367

Please sign in to comment.