Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/external dependencies #353

Merged
merged 2 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions README-VANILLA.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,25 @@ Install using npm:
npm install vanilla-jsoneditor
```

Remark: for usage in a Svelte project, install `svelte-jsoneditor` instead.
Remark: for usage in a Svelte project, install and use `svelte-jsoneditor` instead of `vanilla-jsoneditor`.

## Use

If you have a setup for your project with a bundler (like Vite, Rollup, or Webpack), it is best to use the default ES import:

```ts
// for use in a React, Vue, or Angular project
import { JSONEditor } from 'vanilla-jsoneditor'
```

If you want to use the library straight in the browser, use the provided standalone ES bundle:

```ts
// for use directly in the browser
import { JSONEditor } from 'vanilla-jsoneditor/standalone.js'
```

The standalone bundle contains all dependencies of `vanilla-jsoneditor`, for example `lodash-es` and `Ajv`. If you use some of these dependencies in your project too, it means that they will be bundled twice in your web application, leading to a needlessly large application size. In general, it is preferable to use the default `import { JSONEditor } from 'vanilla-jsoneditor'` so dependencies can be reused.

## Use (Browser example loading the ES module):

Expand All @@ -44,7 +62,7 @@ Remark: for usage in a Svelte project, install `svelte-jsoneditor` instead.
<div id="jsoneditor"></div>

<script type="module">
import { JSONEditor } from 'vanilla-jsoneditor'
import { JSONEditor } from 'vanilla-jsoneditor/standalone.js'

// Or use it through a CDN (not recommended for use in production):
// import { JSONEditor } from 'https://unpkg.com/vanilla-jsoneditor/index.js'
Expand Down Expand Up @@ -84,7 +102,7 @@ Depending on whether you are using JavaScript of TypeScript, create either a JSX

### TypeScript:

```typescript
```tsx
//
// JSONEditorReact.tsx
//
Expand Down Expand Up @@ -126,7 +144,7 @@ export default JSONEditorReact

### JavaScript

```javascript
```jsx
//
// JSONEditorReact.jsx
//
Expand Down Expand Up @@ -172,7 +190,7 @@ If you are using NextJS, you will need to use a dynamic import to only render th

If you are using React in an conventional non-NextJS browser app, you can import the component using a standard import statement like `import JSONEditorReact from '../JSONEditorReact'`

```typescript
```tsx
//
// demo.tsx for use with NextJS
//
Expand Down Expand Up @@ -228,7 +246,7 @@ export default function Demo() {
}
```

```typescript
```tsx
//
// TextContent.tsx
//
Expand Down
30 changes: 22 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,27 @@ Or one-way binding:
</div>
```

### Standalone bundle (use in React, Vue, Angular, plain JavaScript, ...)
### Vanilla bundle (use in React, Vue, Angular, plain JavaScript, ...)

The library provides a standalone bundle of the editor via the npm library `vanilla-jsoneditor` (instead of `svelte-jsoneditor`) which can be used in any browser environment and framework. In a framework like React, Vue, or Angular, you'll need to write some wrapper code around the class interface.
The library provides a vanilla bundle of the editor via the npm library `vanilla-jsoneditor` (instead of `svelte-jsoneditor`) which can be used in any browser environment and framework. In a framework like React, Vue, or Angular, you'll need to write some wrapper code around the class interface.

Note that the `vanilla-jsoneditor` package contains all dependencies. These are purely needed for the TypeScript types that they export.
If you have a setup for your project with a bundler (like Vite, Rollup, or Webpack), it is best to use the default ES import:

Browser example loading the ES module:
```ts
// for use in a React, Vue, or Angular project
import { JSONEditor } from 'vanilla-jsoneditor'
```

If you want to use the library straight in the browser, use the provided standalone ES bundle:

```ts
// for use directly in the browser
import { JSONEditor } from 'vanilla-jsoneditor/standalone.js'
```

The standalone bundle contains all dependencies of `vanilla-jsoneditor`, for example `lodash-es` and `Ajv`. If you use some of these dependencies in your project too, it means that they will be bundled twice in your web application, leading to a needlessly large application size. In general, it is preferable to use the default `import { JSONEditor } from 'vanilla-jsoneditor'` so dependencies can be reused.

Browser example loading the standalone ES module:

```html
<!doctype html>
Expand All @@ -119,11 +133,11 @@ Browser example loading the ES module:
<div id="jsoneditor"></div>

<script type="module">
import { JSONEditor } from 'vanilla-jsoneditor'
import { JSONEditor } from 'vanilla-jsoneditor/standalone.js'

// Or use it through a CDN (not recommended for use in production):
// import { JSONEditor } from 'https://unpkg.com/vanilla-jsoneditor/index.js'
// import { JSONEditor } from 'https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/index.js'
// import { JSONEditor } from 'https://unpkg.com/vanilla-jsoneditor/standalone.js'
// import { JSONEditor } from 'https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/standalone.js'

let content = {
text: undefined,
Expand Down Expand Up @@ -180,7 +194,7 @@ Svelte component:
JavasScript class:

```js
import { JSONEditor } from 'vanilla-jsoneditor'
import { JSONEditor } from 'vanilla-jsoneditor' // or 'vanilla-jsoneditor/standalone.js'

const content = { text: '[1,2,3]' }

Expand Down
2 changes: 1 addition & 1 deletion examples/browser/basic_usage.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<div id="jsoneditor"></div>

<script type="module">
import { JSONEditor } from '../../package-vanilla/index.js'
import { JSONEditor } from '../../package-vanilla/standalone.js'

// create the editor
const editor = new JSONEditor({
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/custom_theme_color.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ <h1>JSONEditor with a custom theme color and large font</h1>
<div id="my-jsoneditor"></div>

<script type="module">
import { JSONEditor } from '../../package-vanilla/index.js'
import { JSONEditor } from '../../package-vanilla/standalone.js'

const editor = new JSONEditor({
target: document.getElementById('my-jsoneditor'),
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/json_schema_validation.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1>JSON schema validation</h1>
<div id="jsoneditor"></div>

<script type="module">
import { JSONEditor, createAjvValidator } from '../../package-vanilla/index.js'
import { JSONEditor, createAjvValidator } from '../../package-vanilla/standalone.js'

const schema = {
title: 'Employee',
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/toggle_options.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<div id="jsoneditor"></div>

<script type="module">
import { JSONEditor } from '../../package-vanilla/index.js'
import { JSONEditor } from '../../package-vanilla/standalone.js'

const content = {
text: undefined,
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@
"build:svelte:package-json": "node tools/createSveltePackageJson.js",
"build:vanilla": "npm-run-all build:vanilla:**",
"build:vanilla:clean": "del-cli package-vanilla",
"build:vanilla:bundle": "rollup --config rollup.config.bundle.js",
"build:vanilla:bundle-types": "rollup --config rollup.config.bundle-types.js",
"build:vanilla:library": "rollup --config rollup.config.vanilla-library.js",
"build:vanilla:bundle": "rollup --config rollup.config.vanilla-bundle.js",
"build:vanilla:types": "rollup --config rollup.config.vanilla-types.js",
"build:vanilla:copy:files": "cpy CHANGELOG.md LICENSE.md SECURITY.md package-vanilla",
"build:vanilla:copy:readme": "cpy --rename README.md README-VANILLA.md package-vanilla",
"build:vanilla:copy:themes": "cpy --flat src/lib/themes package-vanilla/themes",
Expand Down
18 changes: 18 additions & 0 deletions rollup.config.vanilla-bundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import config from './rollup.config.vanilla-library.js'
import path from 'path'

const packageFolder = 'package-vanilla'
const file = path.join(packageFolder, 'standalone.js')

export default {
...config,
external: undefined,
output: [
{
file,
format: 'es',
sourcemap: true,
inlineDynamicImports: true
}
]
}
2 changes: 2 additions & 0 deletions rollup.config.bundle.js → rollup.config.vanilla-library.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import path from 'path'
import svelte from 'rollup-plugin-svelte'
import terser from '@rollup/plugin-terser'
import sveltePreprocess from 'svelte-preprocess'
import { getVanillaDependencies } from './tools/getExternalDependencies.js'

const production = !process.env.ROLLUP_WATCH
const packageFolder = 'package-vanilla'
const file = path.join(packageFolder, 'index.js')

export default {
input: 'src/lib/index.ts',
external: getVanillaDependencies(),
output: [
{
file,
Expand Down
File renamed without changes.
5 changes: 2 additions & 3 deletions src/lib/components/modes/textmode/TextMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
highlightSpecialChars,
keymap,
lineNumbers,
rectangularSelection,
ViewUpdate
rectangularSelection
} from '@codemirror/view'
import {
defaultKeymap,
Expand Down Expand Up @@ -578,7 +577,7 @@
EditorView.domEventHandlers({
dblclick: handleDoubleClick
}),
EditorView.updateListener.of((update: ViewUpdate) => {
EditorView.updateListener.of((update) => {
editorState = update.state

if (update.docChanged) {
Expand Down
35 changes: 7 additions & 28 deletions tools/createVanillaPackageJson.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,16 @@
// create package.json and copy files like LICENSE.md to package-vanilla

import path from 'path'
import assert from 'assert'
import { readFileSync, writeFileSync } from 'fs'
import { getAbsolutePath } from './utils/getAbsolutePath.mjs'
import { getVanillaDependencies } from './getExternalDependencies.js'

const vanillaPackageFolder = getAbsolutePath(import.meta.url, '..', 'package-vanilla')

const pkg = JSON.parse(String(readFileSync(getAbsolutePath(import.meta.url, '..', 'package.json'))))
const typesPath = getAbsolutePath(import.meta.url, '..', 'package-vanilla', 'index.d.ts')
const types = String(readFileSync(typesPath))

// scan the index.d.ts bundle file for all occurrences of "import { ...} from '...'" and extract the name
const usedDependencyNames = uniq(
Array.from(types.matchAll(/(import|export) .+ from '(.+)'/g))
.map((match) => match[2])
.sort()
)
const expectedDependencyNames = [
'@fortawesome/free-solid-svg-icons',
'ajv',
'immutable-json-patch',
'svelte'
]

// We do not want to get surprises
assert.deepStrictEqual(
usedDependencyNames,
expectedDependencyNames,
`Used dependencies found in "${typesPath}" does not equal the expected dependencies. ` +
'Please update the list in createVanillaPackageJson.js manually.'
)
// We add svelte here: this is needed to export the TypeScript types
const usedDependencyNames = [...getVanillaDependencies(), 'svelte']

const usedDependencies = usedDependencyNames.reduce((deps, name) => {
deps[name] = pkg.dependencies[name]
Expand All @@ -44,17 +24,16 @@ const vanillaPackage = {
dependencies: usedDependencies, // needed for the TypeScript types
devDependencies: {},
svelte: undefined,
browser: './standalone.js',
exports: {
...pkg.exports,
'./index.js.map': './index.js.map'
'./index.js.map': './index.js.map',
'./standalone.js': './standalone.js',
'./standalone.js.map': './standalone.js.map'
}
}

writeFileSync(
path.join(vanillaPackageFolder, 'package.json'),
JSON.stringify(vanillaPackage, null, 2)
)

function uniq(array) {
return [...new Set(array)]
}
2 changes: 1 addition & 1 deletion tools/develop-vanilla.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
JSONEditor,
lodashQueryLanguage,
jmespathQueryLanguage
} from '../package-vanilla/index.js'
} from '../package-vanilla/standalone.js'

const json = {
array: [
Expand Down
11 changes: 11 additions & 0 deletions tools/getExternalDependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { readFileSync } from 'fs'
import { getAbsolutePath } from './utils/getAbsolutePath.mjs'

// Get all dependencies for the vanilla package: dependencies that do not start with "svelte*"
// (for example jsonrepair, lodash-es, ...)
export function getVanillaDependencies() {
const sveltePackageFolder = getAbsolutePath(import.meta.url, '..', 'package.json')

const pkg = JSON.parse(String(readFileSync(sveltePackageFolder)))
return Object.keys(pkg.dependencies).filter((name) => !name.startsWith('svelte'))
}