This commit is contained in:
parent
5bd0bf1a95
commit
4ac92e5fa2
@ -14,11 +14,13 @@
|
|||||||
"@monaco-editor/react": "^4.6.0",
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.11.10",
|
"framer-motion": "^11.11.10",
|
||||||
|
"json5": "^2.2.3",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
"styled-components": "^6.1.13"
|
"styled-components": "^6.1.13",
|
||||||
|
"yaml": "^2.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.13.0",
|
"@eslint/js": "^9.13.0",
|
||||||
|
@ -20,6 +20,9 @@ importers:
|
|||||||
framer-motion:
|
framer-motion:
|
||||||
specifier: ^11.11.10
|
specifier: ^11.11.10
|
||||||
version: 11.11.10(@emotion/is-prop-valid@1.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 11.11.10(@emotion/is-prop-valid@1.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
json5:
|
||||||
|
specifier: ^2.2.3
|
||||||
|
version: 2.2.3
|
||||||
normalize.css:
|
normalize.css:
|
||||||
specifier: ^8.0.1
|
specifier: ^8.0.1
|
||||||
version: 8.0.1
|
version: 8.0.1
|
||||||
@ -35,6 +38,9 @@ importers:
|
|||||||
styled-components:
|
styled-components:
|
||||||
specifier: ^6.1.13
|
specifier: ^6.1.13
|
||||||
version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
yaml:
|
||||||
|
specifier: ^2.6.0
|
||||||
|
version: 2.6.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.13.0
|
specifier: ^9.13.0
|
||||||
@ -950,6 +956,11 @@ packages:
|
|||||||
json-stable-stringify-without-jsonify@1.0.1:
|
json-stable-stringify-without-jsonify@1.0.1:
|
||||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||||
|
|
||||||
|
json5@2.2.3:
|
||||||
|
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
@ -1368,6 +1379,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
yaml@2.6.0:
|
||||||
|
resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==}
|
||||||
|
engines: {node: '>= 14'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
yocto-queue@0.1.0:
|
yocto-queue@0.1.0:
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -2117,6 +2133,8 @@ snapshots:
|
|||||||
|
|
||||||
json-stable-stringify-without-jsonify@1.0.1: {}
|
json-stable-stringify-without-jsonify@1.0.1: {}
|
||||||
|
|
||||||
|
json5@2.2.3: {}
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
@ -2490,4 +2508,6 @@ snapshots:
|
|||||||
|
|
||||||
word-wrap@1.2.5: {}
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
|
yaml@2.6.0: {}
|
||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
@ -16,7 +16,7 @@ export const Editor: FC = () => {
|
|||||||
loading={<></>}
|
loading={<></>}
|
||||||
value={value}
|
value={value}
|
||||||
language="yaml"
|
language="yaml"
|
||||||
onChange={(v) => setValue(v ?? '')}
|
onChange={(v) => setValue(v?.trim() ?? '')}
|
||||||
options={{
|
options={{
|
||||||
automaticLayout: true,
|
automaticLayout: true,
|
||||||
lineNumbersMinChars: 3,
|
lineNumbersMinChars: 3,
|
||||||
@ -31,7 +31,7 @@ export const Editor: FC = () => {
|
|||||||
smoothScrolling: true,
|
smoothScrolling: true,
|
||||||
cursorSmoothCaretAnimation: 'on',
|
cursorSmoothCaretAnimation: 'on',
|
||||||
cursorBlinking: 'smooth',
|
cursorBlinking: 'smooth',
|
||||||
cursorStyle: 'block'
|
cursorStyle: 'line'
|
||||||
}}
|
}}
|
||||||
theme="vs-dark" />
|
theme="vs-dark" />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
import { ChangeEvent, FC, useState } from "react";
|
import { ChangeEvent, FC, useEffect, useState } from "react";
|
||||||
import style from './style.module.scss'
|
import style from './style.module.scss'
|
||||||
import { Button } from "../Components/Button";
|
import { Button } from "../Components/Button";
|
||||||
import { Input } from "../Components/Input";
|
import { Input } from "../Components/Input";
|
||||||
import { TextArea } from "../Components/TextArea";
|
import { TextArea } from "../Components/TextArea";
|
||||||
import { TransformCheckboxOption, TransformOption, TransformTextboxOption, WrappedTransform } from "../Transforms/Transform";
|
import clsx from "clsx";
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState } from "recoil";
|
||||||
import { EditorValueState } from "../GlobalStates/EditorValueState";
|
import { EditorValueState } from "../GlobalStates/EditorValueState";
|
||||||
import clsx from "clsx";
|
import {
|
||||||
|
isTransformCheckboxOption,
|
||||||
|
isTransformIntboxOption,
|
||||||
|
isTransformTextboxOption,
|
||||||
|
TransformCheckboxOption,
|
||||||
|
TransformIntboxOption,
|
||||||
|
TransformTextboxOption,
|
||||||
|
WrappedTransform,
|
||||||
|
WrappedTransformResult
|
||||||
|
} from "../Transforms/Transform";
|
||||||
|
|
||||||
interface TransformGridItemProp {
|
interface TransformGridItemProp {
|
||||||
transform: WrappedTransform
|
transform: WrappedTransform
|
||||||
@ -14,9 +23,17 @@ interface TransformGridItemProp {
|
|||||||
|
|
||||||
export const TransformGridItem: FC<TransformGridItemProp> = ({ transform }) => {
|
export const TransformGridItem: FC<TransformGridItemProp> = ({ transform }) => {
|
||||||
const [value, setValue] = useRecoilState(EditorValueState)
|
const [value, setValue] = useRecoilState(EditorValueState)
|
||||||
const [options, setOptions] = useState(new Map<string, TransformOption>())
|
const [options, setOptions] = useState(transform.options)
|
||||||
|
const [result, setResult] = useState<WrappedTransformResult>({
|
||||||
|
error: false,
|
||||||
|
value: ''
|
||||||
|
})
|
||||||
|
|
||||||
const result = transform.fn(value, options)
|
useEffect(() => {
|
||||||
|
transform
|
||||||
|
.fn(value, options)
|
||||||
|
.then(setResult.bind(this))
|
||||||
|
}, [value, options])
|
||||||
|
|
||||||
const onCheckboxOptionChanged =
|
const onCheckboxOptionChanged =
|
||||||
(option: TransformCheckboxOption) =>
|
(option: TransformCheckboxOption) =>
|
||||||
@ -43,6 +60,18 @@ export const TransformGridItem: FC<TransformGridItemProp> = ({ transform }) => {
|
|||||||
setOptions(new Map(options))
|
setOptions(new Map(options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onIntboxOptionChanged =
|
||||||
|
(option: TransformIntboxOption) =>
|
||||||
|
(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|
||||||
|
options.set(option.key, {
|
||||||
|
...option,
|
||||||
|
value: parseInt(event.target.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
setOptions(new Map(options))
|
||||||
|
}
|
||||||
|
|
||||||
const onForwardButtonPressed = () => {
|
const onForwardButtonPressed = () => {
|
||||||
if (result.error)
|
if (result.error)
|
||||||
return
|
return
|
||||||
@ -60,33 +89,49 @@ export const TransformGridItem: FC<TransformGridItemProp> = ({ transform }) => {
|
|||||||
<h2 className={style.name}>{transform.name}</h2>
|
<h2 className={style.name}>{transform.name}</h2>
|
||||||
|
|
||||||
<div className={style.options}>
|
<div className={style.options}>
|
||||||
{transform.options
|
{[...options.values()]
|
||||||
?.filter((option) => option.type === 'CHECKBOX')
|
?.filter(isTransformCheckboxOption)
|
||||||
.map((option, i) => (
|
.map((option, i) => (
|
||||||
<label key={i} className={style.optionItem}>
|
<label key={i} className={style.optionItem}>
|
||||||
<p>{option.label ?? option.key}:</p>
|
<p>{option.label ?? option.key}:</p>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
checked={option.value}
|
||||||
onChange={onCheckboxOptionChanged(option)}
|
onChange={onCheckboxOptionChanged(option)}
|
||||||
type="checkbox" />
|
type="checkbox" />
|
||||||
</label>))}
|
</label>))}
|
||||||
|
|
||||||
{transform.options
|
{[...options.values()]
|
||||||
?.filter((option) => option.type === 'TEXTBOX')
|
?.filter(isTransformTextboxOption)
|
||||||
.map((option, i) => (
|
.map((option, i) => (
|
||||||
<label key={i} className={style.optionItem}>
|
<label key={i} className={style.optionItem}>
|
||||||
<p>{option.label ?? option.key}:</p>
|
<p>{option.label ?? option.key}:</p>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
|
value={option.value}
|
||||||
onChange={onTextboxOptionChanged(option)}
|
onChange={onTextboxOptionChanged(option)}
|
||||||
type="checkbox" />
|
type="text" />
|
||||||
|
</label>))}
|
||||||
|
|
||||||
|
|
||||||
|
{[...options.values()]
|
||||||
|
?.filter(isTransformIntboxOption)
|
||||||
|
.map((option, i) => (
|
||||||
|
<label key={i} className={style.optionItem}>
|
||||||
|
<p>{option.label ?? option.key}:</p>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
min={1}
|
||||||
|
value={option.value}
|
||||||
|
onChange={onIntboxOptionChanged(option)}
|
||||||
|
type="number" />
|
||||||
</label>))}
|
</label>))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextArea
|
<TextArea
|
||||||
value={result.value}
|
|
||||||
readOnly
|
readOnly
|
||||||
|
value={result.value}
|
||||||
placeholder="(empty)"
|
placeholder="(empty)"
|
||||||
className={clsx(result.error && style.error)} />
|
className={clsx(result.error && style.error)} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,10 +2,10 @@ import { Transform } from "./Transform";
|
|||||||
|
|
||||||
export const Base64DecodeTransform: Transform = {
|
export const Base64DecodeTransform: Transform = {
|
||||||
name: 'base64d',
|
name: 'base64d',
|
||||||
fn: (v) => btoa(v)
|
fn: async (v) => btoa(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Base64EncodeTransform: Transform = {
|
export const Base64EncodeTransform: Transform = {
|
||||||
name: 'base64e',
|
name: 'base64e',
|
||||||
fn: (v) => atob(v)
|
fn: async (v) => atob(v)
|
||||||
}
|
}
|
||||||
|
23
src/Transforms/GzipTransform.ts
Normal file
23
src/Transforms/GzipTransform.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Transform } from "./Transform"
|
||||||
|
|
||||||
|
const decompressGzip = async (base64: string) => {
|
||||||
|
const byteCharacters = atob(base64)
|
||||||
|
const byteNumbers = new Array(byteCharacters.length)
|
||||||
|
|
||||||
|
for (let i = 0; i < byteCharacters.length; i++)
|
||||||
|
byteNumbers[i] = byteCharacters.charCodeAt(i)
|
||||||
|
|
||||||
|
const decompressedStream =
|
||||||
|
new Blob([new Uint8Array(byteNumbers)])
|
||||||
|
.stream()
|
||||||
|
.pipeThrough(new DecompressionStream("gzip"))
|
||||||
|
|
||||||
|
return await new Response(decompressedStream).text()
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GzipDecompressTransform: Transform = {
|
||||||
|
name: 'gzipd',
|
||||||
|
|
||||||
|
fn: (v) => decompressGzip(v)
|
||||||
|
}
|
||||||
|
|
50
src/Transforms/JSONTransforms.ts
Normal file
50
src/Transforms/JSONTransforms.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import JSON5 from 'json5'
|
||||||
|
import { Transform } from "./Transform";
|
||||||
|
|
||||||
|
export const JSONBeautifyTransform: Transform = {
|
||||||
|
name: 'jsonbtf',
|
||||||
|
|
||||||
|
fn: async (v, o) =>
|
||||||
|
o.get('multiline')?.value === true
|
||||||
|
? JSON.stringify(JSON5.parse(v), null, o.get('tab')?.value as number ?? 2)
|
||||||
|
: v.split('\n').map((v2) => JSON.stringify(JSON5.parse(v2), null, o.get('tab')?.value as number ?? 2)).join('\n'),
|
||||||
|
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
type: 'CHECKBOX',
|
||||||
|
key: 'multiline'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'INTBOX',
|
||||||
|
key: 'tab',
|
||||||
|
value: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JSONSimplifyTransform: Transform = {
|
||||||
|
name: 'jsonsmp',
|
||||||
|
|
||||||
|
fn: async (v) =>
|
||||||
|
JSON.stringify(JSON5.parse(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JSONEscapeTransform: Transform = {
|
||||||
|
name: 'jsonesc',
|
||||||
|
|
||||||
|
fn: async (v) =>
|
||||||
|
JSON.stringify(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JSONUnescapeTransform: Transform = {
|
||||||
|
name: 'jsonunesc',
|
||||||
|
|
||||||
|
fn: async (v) => {
|
||||||
|
const result = JSON5.parse(v)
|
||||||
|
|
||||||
|
if (typeof result !== 'string')
|
||||||
|
throw new Error('Not JSON escaped')
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
21
src/Transforms/RegexpTransform.ts
Normal file
21
src/Transforms/RegexpTransform.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Transform } from "./Transform";
|
||||||
|
|
||||||
|
export const RegexpTransform: Transform = {
|
||||||
|
name: 'regexp',
|
||||||
|
fn: async (v) => {
|
||||||
|
const [expression, samples] = v.split('\n\n')
|
||||||
|
const regexp = new RegExp(expression)
|
||||||
|
|
||||||
|
const parsedSamples = samples
|
||||||
|
.split('\n')
|
||||||
|
.map((sample) =>
|
||||||
|
JSON.stringify(regexp.exec(sample)?.groups))
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
return [
|
||||||
|
expression,
|
||||||
|
samples,
|
||||||
|
parsedSamples
|
||||||
|
].join('\n\n')
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
import { Base64DecodeTransform, Base64EncodeTransform } from "./Base64Transforms"
|
import { Base64DecodeTransform, Base64EncodeTransform } from "./Base64Transforms"
|
||||||
|
import { GzipDecompressTransform } from "./GzipTransform"
|
||||||
|
import { JSONBeautifyTransform, JSONEscapeTransform, JSONSimplifyTransform, JSONUnescapeTransform } from "./JSONTransforms"
|
||||||
|
import { RegexpTransform } from "./RegexpTransform"
|
||||||
import { URIDecodeTransform, URIEncodeTransform } from "./URITransforms"
|
import { URIDecodeTransform, URIEncodeTransform } from "./URITransforms"
|
||||||
|
import { JSON2YAMLTransform, YAML2JSONTransform } from "./YAMLTransforms"
|
||||||
|
|
||||||
export interface TransformCheckboxOption {
|
export interface TransformCheckboxOption {
|
||||||
type: 'CHECKBOX',
|
type: 'CHECKBOX',
|
||||||
@ -16,44 +20,72 @@ export interface TransformTextboxOption {
|
|||||||
value?: string
|
value?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TransformIntboxOption {
|
||||||
|
type: 'INTBOX',
|
||||||
|
key: string,
|
||||||
|
label?: string,
|
||||||
|
value?: number
|
||||||
|
}
|
||||||
|
|
||||||
export type TransformOption =
|
export type TransformOption =
|
||||||
TransformCheckboxOption | TransformTextboxOption
|
TransformCheckboxOption | TransformTextboxOption | TransformIntboxOption
|
||||||
|
|
||||||
|
export const isTransformCheckboxOption = (object: any): object is TransformCheckboxOption =>
|
||||||
|
object.type === 'CHECKBOX'
|
||||||
|
|
||||||
|
export const isTransformTextboxOption = (object: any): object is TransformTextboxOption =>
|
||||||
|
object.type === 'TEXTBOX'
|
||||||
|
|
||||||
|
export const isTransformIntboxOption = (object: any): object is TransformIntboxOption =>
|
||||||
|
object.type === 'INTBOX'
|
||||||
|
|
||||||
export interface Transform {
|
export interface Transform {
|
||||||
name: string
|
name: string
|
||||||
fn: (value: string, options: Map<string, TransformOption>) => string
|
fn: (value: string, options: Map<string, TransformOption>) => Promise<string>
|
||||||
options?: TransformOption[]
|
options?: TransformOption[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WrappedTransform extends Omit<Transform, 'fn'> {
|
export interface WrappedTransformResult {
|
||||||
wrapped: true,
|
error: boolean
|
||||||
fn: (value: string, options: Map<string, TransformOption>) => {
|
|
||||||
error: boolean,
|
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WrappedTransform extends Omit<Transform, 'fn' | 'options'> {
|
||||||
|
wrapped: true,
|
||||||
|
|
||||||
|
fn: (value: string, options: Map<string, TransformOption>) =>
|
||||||
|
Promise<WrappedTransformResult>,
|
||||||
|
|
||||||
|
options: Map<string, TransformOption>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const wrapTransform = (transform: Transform): WrappedTransform => ({
|
export const wrapTransform = (transform: Transform): WrappedTransform => ({
|
||||||
...transform,
|
...transform,
|
||||||
fn: (...args) => {
|
|
||||||
try {
|
fn: async (...args) =>
|
||||||
return {
|
await transform.fn(...args)
|
||||||
error: false,
|
.then((value) =>
|
||||||
value: transform.fn(...args)
|
({ error: false, value: value.toString() }))
|
||||||
}
|
.catch((error) =>
|
||||||
} catch (err: any) {
|
({ error: true, value: error.toString() })),
|
||||||
return {
|
|
||||||
error: true,
|
options: new Map<string, TransformOption>(
|
||||||
value: err.toString()
|
(transform.options ?? []).map((v) => [v.key, v])
|
||||||
}
|
),
|
||||||
}
|
|
||||||
},
|
|
||||||
wrapped: true
|
wrapped: true
|
||||||
})
|
})
|
||||||
|
|
||||||
export const transforms: Transform[] = [
|
export const transforms: Transform[] = [
|
||||||
|
RegexpTransform,
|
||||||
|
GzipDecompressTransform,
|
||||||
Base64DecodeTransform,
|
Base64DecodeTransform,
|
||||||
Base64EncodeTransform,
|
Base64EncodeTransform,
|
||||||
URIDecodeTransform,
|
URIDecodeTransform,
|
||||||
URIEncodeTransform
|
URIEncodeTransform,
|
||||||
|
JSONBeautifyTransform,
|
||||||
|
JSONSimplifyTransform,
|
||||||
|
JSONEscapeTransform,
|
||||||
|
JSONUnescapeTransform,
|
||||||
|
JSON2YAMLTransform,
|
||||||
|
YAML2JSONTransform
|
||||||
]
|
]
|
||||||
|
@ -3,7 +3,7 @@ import { Transform } from "./Transform";
|
|||||||
export const URIDecodeTransform: Transform = {
|
export const URIDecodeTransform: Transform = {
|
||||||
name: 'urid',
|
name: 'urid',
|
||||||
|
|
||||||
fn: (v, o) =>
|
fn: async (v, o) =>
|
||||||
o.get('cmp')?.value === true
|
o.get('cmp')?.value === true
|
||||||
? decodeURIComponent(v)
|
? decodeURIComponent(v)
|
||||||
: decodeURI(v),
|
: decodeURI(v),
|
||||||
@ -17,7 +17,7 @@ export const URIDecodeTransform: Transform = {
|
|||||||
export const URIEncodeTransform: Transform = {
|
export const URIEncodeTransform: Transform = {
|
||||||
name: 'urie',
|
name: 'urie',
|
||||||
|
|
||||||
fn: (v, o) =>
|
fn: async (v, o) =>
|
||||||
o.get('cmp')?.value === true
|
o.get('cmp')?.value === true
|
||||||
? encodeURIComponent(v)
|
? encodeURIComponent(v)
|
||||||
: encodeURI(v),
|
: encodeURI(v),
|
||||||
|
17
src/Transforms/YAMLTransforms.ts
Normal file
17
src/Transforms/YAMLTransforms.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Transform } from "./Transform";
|
||||||
|
import YAML from 'yaml'
|
||||||
|
import JSON5 from 'json5'
|
||||||
|
|
||||||
|
export const YAML2JSONTransform: Transform = {
|
||||||
|
name: 'yaml2json',
|
||||||
|
|
||||||
|
fn: async (v) =>
|
||||||
|
JSON.stringify(YAML.parse(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const JSON2YAMLTransform: Transform = {
|
||||||
|
name: 'json2yaml',
|
||||||
|
|
||||||
|
fn: async (v) =>
|
||||||
|
YAML.stringify(JSON5.parse(v))
|
||||||
|
}
|
11
src/main.css
11
src/main.css
@ -10,3 +10,14 @@ h1, h2, h3, h4, h5, h6, p, pre, textarea, input, button, li, ul, ol {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=number] {
|
||||||
|
appearance: textfield;
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user