Skip to content

Commit

Permalink
feat: change the type of json from JSONValue to unknown (#371)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

The type `Content` is changed from `{ json: JSONValue} | { text: string }` into 
`{ json: unknown } | { text: string }`, and all other types having `JSONValue` changed 
to `unknown`. The return type of `JSONParser.stringify` changed from `string` to 
`string | undefined`.
  • Loading branch information
josdejong authored Dec 15, 2023
1 parent 0d59366 commit dc4671a
Show file tree
Hide file tree
Showing 55 changed files with 414 additions and 486 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Or one-way binding:
}
function handleChange(updatedContent, previousContent, { contentErrors, patchResult }) {
// content is an object { json: JSONValue } | { text: string }
// content is an object { json: unknown } | { text: string }
console.log('onChange: ', { updatedContent, previousContent, contentErrors, patchResult })
content = updatedContent
}
Expand Down Expand Up @@ -151,7 +151,7 @@ Browser example loading the standalone ES module:
props: {
content,
onChange: (updatedContent, previousContent, { contentErrors, patchResult }) => {
// content is an object { json: JSONValue } | { text: string }
// content is an object { json: unknown } | { text: string }
console.log('onChange', { updatedContent, previousContent, contentErrors, patchResult })
content = updatedContent
}
Expand Down Expand Up @@ -203,7 +203,7 @@ const editor = new JSONEditor({
props: {
content,
onChange: (updatedContent, previousContent, { contentErrors, patchResult }) => {
// content is an object { json: JSONValue } | { text: string }
// content is an object { json: unknown } | { text: string }
console.log('onChange', { updatedContent, previousContent, contentErrors, patchResult })
}
}
Expand All @@ -225,7 +225,7 @@ const editor = new JSONEditor({
- `escapeControlCharacters: boolean`. False by default. When `true`, control characters like newline and tab are rendered as escaped characters `\n` and `\t`. Only applicable for `'tree'` mode, in `'text'` mode control characters are always escaped.
- `escapeUnicodeCharacters: boolean`. False by default. When `true`, unicode characters like ☎ and 😀 are rendered escaped like `\u260e` and `\ud83d\ude00`.
- `flattenColumns: boolean`. True by default. Only applicable to `'table'` mode. When `true`, nested object properties will be displayed each in their own column, with the nested path as column name. When `false`, nested objects will be rendered inline, and double-clicking them will open them in a popup.
- `validator: function (json: JSONValue): ValidationError[]`. Validate the JSON document.
- `validator: function (json: unknown): ValidationError[]`. Validate the JSON document.
For example use the built-in JSON Schema validator powered by Ajv:

```js
Expand Down Expand Up @@ -438,7 +438,7 @@ Note that most methods are asynchronous and will resolve after the editor is re-
- `editor.expand(path => true)` expand all
- `editor.expand(path => false)` collapse all
- `editor.expand(path => path.length < 2)` expand all paths up to 2 levels deep
- `transform({ id?: string, rootPath?: [], onTransform: ({ operations: JSONPatchDocument, json: JSONValue, transformedJson: JSONValue }) => void, onClose: () => void })` programmatically trigger clicking of the transform button in the main menu, opening the transform model. If a callback `onTransform` is provided, it will replace the build-in logic to apply a transform, allowing you to process the transform operations in an alternative way. If provided, `onClose` callback will trigger when the transform modal closes, both after the user clicked apply or cancel. If an `id` is provided, the transform modal will load the previous status of this `id` instead of the status of the editors transform modal.
- `transform({ id?: string, rootPath?: [], onTransform: ({ operations: JSONPatchDocument, json: unknown, transformedJson: unknown }) => void, onClose: () => void })` programmatically trigger clicking of the transform button in the main menu, opening the transform model. If a callback `onTransform` is provided, it will replace the build-in logic to apply a transform, allowing you to process the transform operations in an alternative way. If provided, `onClose` callback will trigger when the transform modal closes, both after the user clicked apply or cancel. If an `id` is provided, the transform modal will load the previous status of this `id` instead of the status of the editors transform modal.
- `scrollTo(path: Path): Promise<void>` Scroll the editor vertically such that the specified path comes into view. Only applicable to modes `tree` and `table`. The path will be expanded when needed. The returned Promise is resolved after scrolling is finished.
- `findElement(path: Path)` Find the DOM element of a given path. Returns `null` when not found.
- `acceptAutoRepair(): Promise<Content>` In tree mode, invalid JSON is automatically repaired when loaded. When the repair was successful, the repaired contents are rendered but not yet applied to the document itself until the user clicks "Ok" or starts editing the data. Instead of accepting the repair, the user can also click "Repair manually instead". Invoking `.acceptAutoRepair()` will programmatically accept the repair. This will trigger an update, and the method itself also returns the updated contents. In case of `text` mode or when the editor is not in an "accept auto repair" status, nothing will happen, and the contents will be returned as is.
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
"eslint-plugin-svelte": "2.35.1",
"husky": "8.0.3",
"jsdom": "23.0.1",
"lossless-json": "3.0.2",
"lossless-json": "4.0.1",
"npm-run-all": "4.1.5",
"prettier": "3.1.0",
"prettier-plugin-svelte": "3.1.2",
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/JSONEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@
debug('parser changed, recreate editor')
if (isJSONContent(content)) {
const text = previousParser.stringify(content.json)
content = {
json: parser.parse(previousParser.stringify(content.json))
json: text !== undefined ? parser.parse(text) : undefined
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/controls/JSONPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script lang="ts">
import type { JSONParser, JSONValue } from '$lib/types'
import type { JSONParser } from '$lib/types'
import { truncate } from '$lib/utils/stringUtils.js'
import { getText } from '$lib/utils/jsonUtils.js'
import { MAX_CHARACTERS_TEXT_PREVIEW } from '$lib/constants.js'
export let text: string | undefined
export let json: JSONValue | undefined
export let json: unknown | undefined
export let indentation: number | string
export let parser: JSONParser
Expand Down
10 changes: 2 additions & 8 deletions src/lib/components/controls/navigationBar/NavigationBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,15 @@
import { createMultiSelection, getFocusPath } from '$lib/logic/selection.js'
import { createDebug } from '$lib/utils/debug.js'
import { caseInsensitiveNaturalCompare } from '$lib/logic/sort.js'
import type {
JSONPathParser,
JSONSelection,
JSONValue,
OnError,
OnJSONSelect
} from '$lib/types.js'
import type { JSONPathParser, JSONSelection, OnError, OnJSONSelect } from '$lib/types.js'
import Icon from 'svelte-awesome'
import { faClose, faEdit } from '@fortawesome/free-solid-svg-icons'
import NavigationBarItem from './NavigationBarItem.svelte'
import NavigationBarPathEditor from './NavigationBarPathEditor.svelte'
const debug = createDebug('jsoneditor:NavigationBar')
export let json: JSONValue
export let json: unknown
export let selection: JSONSelection | null
export let onSelect: OnJSONSelect
export let onError: OnError
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/controls/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { AbsolutePopupOptions } from '$lib/types'
export interface TooltipOptions {
text: string
openAbsolutePopup: (
component: typeof SvelteComponent,
component: typeof SvelteComponent<Record<string, unknown>>,
props: Record<string, unknown>,
options: AbsolutePopupOptions
) => number
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/modals/SortModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
import type { JSONPath } from 'immutable-json-patch'
import { compileJSONPointer, getIn } from 'immutable-json-patch'
import { createDebug } from '$lib/utils/debug.js'
import type { JSONValue, OnSort } from '$lib/types.js'
import type { OnSort } from '$lib/types.js'
import { onEscape } from '$lib/actions/onEscape.js'
import type { Context } from 'svelte-simple-modal'
const debug = createDebug('jsoneditor:SortModal')
export let id: string
export let json: JSONValue // the whole document
export let json: unknown // the whole document
export let rootPath: JSONPath
export let onSort: OnSort
Expand Down
7 changes: 3 additions & 4 deletions src/lib/components/modals/TransformModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
Content,
JSONParser,
JSONPathParser,
JSONValue,
OnChangeQueryLanguage,
OnClassName,
OnPatch,
Expand All @@ -34,7 +33,7 @@
const debug = createDebug('jsoneditor:TransformModal')
export let id = 'transform-modal-' + uniqueId()
export let json: JSONValue
export let json: unknown
export let rootPath: JSONPath = []
export let indentation: number | string
Expand All @@ -54,7 +53,7 @@
export let onTransform: OnPatch
let selectedJson: JSONValue | undefined
let selectedJson: unknown | undefined
$: selectedJson = getIn(json, rootPath)
let selectedContent: Content
$: selectedContent = selectedJson ? { json: selectedJson } : { text: '' }
Expand Down Expand Up @@ -97,7 +96,7 @@
debug('handleChangeQuery', { query, isManual })
}
function previewTransform(json: JSONValue | undefined, query: string) {
function previewTransform(json: unknown | undefined, query: string) {
if (json === undefined) {
previewContent = { text: '' }
previewError = 'Error: No JSON'
Expand Down
32 changes: 16 additions & 16 deletions src/lib/components/modals/TransformWizard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import { isEqual } from 'lodash-es'
import type { JSONPath } from 'immutable-json-patch'
import { setIn } from 'immutable-json-patch'
import type { JSONValue, QueryLanguageOptions } from '$lib/types.js'
import type { PathOption, QueryLanguageOptions } from '$lib/types.js'
const debug = createDebug('jsoneditor:TransformWizard')
export let json: JSONValue
export let json: unknown
export let queryOptions: QueryLanguageOptions = {}
export let onChange: (queryOptions: QueryLanguageOptions) => void
Expand Down Expand Up @@ -46,65 +46,65 @@
$: projectionPaths =
queryOptions?.projection?.paths && projectionOptions
? queryOptions.projection.paths
? (queryOptions.projection.paths
.map((path) => projectionOptions.find((option) => isEqual(option.value, path)))
.filter((option) => !!option)
.filter((option) => !!option) as PathOption[])
: null
function changeFilterPath(path: JSONPath) {
function changeFilterPath(path: JSONPath | undefined) {
if (!isEqual(queryOptions?.filter?.path, path)) {
debug('changeFilterPath', path)
queryOptions = setIn(queryOptions, ['filter', 'path'], path, true)
onChange(queryOptions)
}
}
function changeFilterRelation(relation) {
function changeFilterRelation(relation: string | undefined) {
if (!isEqual(queryOptions?.filter?.relation, relation)) {
debug('changeFilterRelation', relation)
queryOptions = setIn(queryOptions, ['filter', 'relation'], relation, true)
onChange(queryOptions)
}
}
function changeFilterValue(value) {
function changeFilterValue(value: string | undefined) {
if (!isEqual(queryOptions?.filter?.value, value)) {
debug('changeFilterValue', value)
queryOptions = setIn(queryOptions, ['filter', 'value'], value, true)
onChange(queryOptions)
}
}
function changeSortPath(path) {
function changeSortPath(path: JSONPath | undefined) {
if (!isEqual(queryOptions?.sort?.path, path)) {
debug('changeSortPath', path)
queryOptions = setIn(queryOptions, ['sort', 'path'], path, true)
onChange(queryOptions)
}
}
function changeSortDirection(direction) {
function changeSortDirection(direction: string | undefined) {
if (!isEqual(queryOptions?.sort?.direction, direction)) {
debug('changeSortDirection', direction)
queryOptions = setIn(queryOptions, ['sort', 'direction'], direction, true)
onChange(queryOptions)
}
}
function changeProjectionPaths(paths) {
function changeProjectionPaths(paths: JSONPath[] | unknown) {
if (!isEqual(queryOptions?.projection?.paths, paths)) {
debug('changeProjectionPaths', paths)
queryOptions = setIn(queryOptions, ['projection', 'paths'], paths, true)
onChange(queryOptions)
}
}
$: changeFilterPath(filterPath?.value || null)
$: changeFilterRelation(filterRelation?.value || null)
$: changeFilterValue(filterValue || null)
$: changeSortPath(sortPath?.value || null)
$: changeSortDirection(sortDirection?.value || null)
$: changeProjectionPaths(projectionPaths ? projectionPaths.map((item) => item.value) : null)
$: changeFilterPath(filterPath?.value)
$: changeFilterRelation(filterRelation?.value)
$: changeFilterValue(filterValue)
$: changeSortPath(sortPath?.value)
$: changeSortDirection(sortDirection?.value)
$: changeProjectionPaths(projectionPaths ? projectionPaths.map((item) => item.value) : undefined)
</script>

<table class="jse-transform-wizard">
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/modes/tablemode/JSONValue.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
AfterPatchCallback,
JSONEditorContext,
JSONSelection,
JSONValue,
SearchResultItem
} from '$lib/types'
import type { JSONPatchDocument, JSONPath } from 'immutable-json-patch'
import { isEditingSelection, isValueSelection } from '$lib/logic/selection.js'
import { createNestedValueOperations } from '$lib/logic/operations.js'
export let path: JSONPath
export let value: JSONValue
export let value: unknown
export let context: JSONEditorContext
export let enforceString: boolean
export let selection: JSONSelection | null
Expand Down
21 changes: 10 additions & 11 deletions src/lib/components/modes/tablemode/TableMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
JSONParser,
JSONPatchResult,
JSONSelection,
JSONValue,
OnBlur,
OnChange,
OnChangeMode,
Expand Down Expand Up @@ -207,7 +206,7 @@
}
})
let json: JSONValue | undefined
let json: unknown | undefined
let text: string | undefined
let parseError: ParseError | undefined = undefined
Expand Down Expand Up @@ -248,7 +247,7 @@
$: refreshScrollTop(json)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function refreshScrollTop(_json: JSONValue | undefined) {
function refreshScrollTop(_json: unknown | undefined) {
// When the contents go from lots of items and scrollable contents to only a few items and
// no vertical scroll, the actual scrollTop changes to 0 but there is no on:scroll event
// triggered, so the internal scrollTop variable is not up-to-date.
Expand Down Expand Up @@ -291,7 +290,7 @@
}
}
function clearSelectionWhenNotExisting(json: JSONValue | undefined) {
function clearSelectionWhenNotExisting(json: unknown | undefined) {
if (!documentState.selection || json === undefined) {
return
}
Expand Down Expand Up @@ -443,7 +442,7 @@
previousText,
previousTextIsRepaired
}: {
previousJson: JSONValue | undefined
previousJson: unknown | undefined
previousText: string | undefined
previousState: DocumentState
previousTextIsRepaired: boolean
Expand Down Expand Up @@ -523,7 +522,7 @@
const memoizedValidate = memoizeOne(validateJSON)
function updateValidationErrors(
json: JSONValue,
json: unknown,
validator: Validator | null,
parser: JSONParser,
validationParser: JSONParser
Expand Down Expand Up @@ -1074,7 +1073,7 @@
{
op: 'replace',
path: pointer,
value: updatedValue as JSONValue
value: updatedValue
}
],
(patchedJson, patchedState) => {
Expand Down Expand Up @@ -1388,7 +1387,7 @@
}
// TODO: this function is duplicated from TreeMode. See if we can reuse the code instead
function handleReplaceJson(updatedJson: JSONValue, afterPatch?: AfterPatchCallback) {
function handleReplaceJson(updatedJson: unknown, afterPatch?: AfterPatchCallback) {
const previousState = documentState
const previousJson = json
const previousText = text
Expand Down Expand Up @@ -1545,8 +1544,8 @@
if (onTransform) {
onTransform({
operations,
json: json as JSONValue,
transformedJson: immutableJSONPatch(json as JSONValue, operations)
json: json,
transformedJson: immutableJSONPatch(json, operations)
})
} else {
debug('onTransform', rootPath, operations)
Expand All @@ -1572,7 +1571,7 @@
// open a popup where you can edit the nested object/array
onJSONEditorModal({
content: {
json: getIn(json as JSONValue, path) as JSONValue
json: getIn(json, path)
},
path,
onPatch: context.onPatch,
Expand Down
Loading

0 comments on commit dc4671a

Please sign in to comment.