Skip to content

Commit

Permalink
feat: json to ts type
Browse files Browse the repository at this point in the history
  • Loading branch information
vtrbo committed Feb 20, 2024
1 parent afbeeec commit c023ead
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 57 deletions.
19 changes: 19 additions & 0 deletions src/lib/utils/copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export async function copyText(str: string) {
if (navigator.clipboard && navigator.permissions) {
await navigator.clipboard.writeText(str)
}
else {
const textArea = document.createElement('textArea') as HTMLTextAreaElement
textArea.value = str
textArea.style.width = '0'
textArea.style.position = 'fixed'
textArea.style.left = '-999px'
textArea.style.top = '10px'
textArea.setAttribute('readonly', 'readonly')
document.body.appendChild(textArea)

textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
}
}
17 changes: 12 additions & 5 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
<script lang="ts">
import { KIcon } from '@ikun-ui/core'
import { KAffix, KIcon } from '@ikun-ui/core'
const toggle = () => {
window.document.documentElement.classList.toggle('dark')
}
</script>

<header>
<div class="p4 fbc shadow dark:shadow-light-50">
<div class="font-500">XParCai Tools</div>
<KIcon class="i-carbon:sun dark:i-carbon:moon" on:click={toggle}></KIcon>
</div>
<KAffix cls="w-full z-100" top={0}>
<div
class="h-56px px-4 fbc shadow bg-white dark:(shadow-light-50 bg-black)"
>
<a href="/">
<div class="font-500">XParCai Tools</div>
</a>
<KIcon class="i-carbon:sun dark:i-carbon:moon" on:click={toggle}></KIcon>
</div>
</KAffix>
<div class="w-full h-56px"></div>
</header>

<main class="p4 w-1200px ma">
Expand Down
144 changes: 92 additions & 52 deletions src/routes/json-to-ts-type/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<script lang="ts">
import {
KAlert,
KButton,
KCard,
KCheckbox,
KCheckboxGroup,
KCollapse,
KCollapseWrapper,
KDivider,
KInput,
KMessage,
} from '@ikun-ui/core'
import {
isArray,
Expand All @@ -19,24 +20,34 @@
toLinesCase,
toRawType,
} from '@vtrbo/utils'
import jsonStr from './test-json.json?raw'
import { copyText } from '$lib/utils/copy'
let jsonCode = ''
type TsType = [string, [boolean, string, any][]]
let tsTypes: TsType[] = []
let isChoose = true
let jsonCode = jsonStr
const tsTypes: [string, [boolean, string, any][]][] = []
function isJsonStr(str: string) {
if (!isString(str)) {
return false
}
try {
const jsonObj = JSON.parse(str)
const jsonObj = getJsonObj(str)
return isObject(jsonObj)
} catch (e) {
return false
}
}
function getJsonObj(str: string) {
// eslint-disable-next-line no-new-func
return new Function(`return ${str}`)()
}
function parseJson(str: string, name: string = 'XParCai') {
if (isJsonStr(str)) {
const jsonObj = JSON.parse(str)
const jsonObj = getJsonObj(str)
const kv: [boolean, string, any][] = []
for (const key in jsonObj) {
if (isArray(jsonObj[key])) {
Expand All @@ -60,72 +71,101 @@
}
}
tsTypes.unshift([name, kv])
} else {
tsTypes = []
}
}
function generateTsType(tsTypesArr: TsType[]) {
if (tsTypesArr.length > 0) {
let typeStrArr: string[] = []
tsTypesArr.forEach(([k, v]) => {
typeStrArr.push(`interface ${k} {`)
v.forEach(([vc, vk, vv]) => {
const typeStr = ` ${vk}${isChoose || vc ? '?' : ''}: ${vv};`
typeStrArr.push(typeStr)
})
typeStrArr.push('}')
})
copyText(typeStrArr.join('\r\n'))
} else {
copyText('')
}
KMessage.success({
content: '复制成功',
close: false,
})
}
$: {
tsTypes.length = 0
parseJson(jsonCode)
}
let isChoose = true
let chooseGroup = []
</script>

<KCard shadow="never">
<div slot="header">
<div class="flex items-center justify-end">
<KCheckbox
cls="select-none"
value={isChoose}
on:updateValue={(e) => (isChoose = e.detail)}
>
是否可选
</KCheckbox>
<div class="flex items-center justify-between">
<div>JSON TO TS TYPE</div>
</div>
</div>
<KCard shadow="never" title="JSON格式的文本" cls="bg-ikun-light-500">
<KInput bind:value={jsonCode} type="textarea" rows={10}></KInput>
{#if !isJsonStr(jsonCode)}
<KAlert
title="请确保输入JSON字符串"
type="error"
closable={false}
cls="mb4"
/>
{/if}
<KInput bind:value={jsonCode} type="textarea" rows={6}></KInput>
</KCard>
{#if tsTypes.length > 0}
<KDivider contentPosition="left">
<KButton cls="min-w-80px">复制</KButton>
<KButton
cls="min-w-80px inline-block"
on:click={() => generateTsType(tsTypes)}>复制</KButton
>
<KCheckbox
cls="select-none"
value={isChoose}
on:updateValue={(e) => (isChoose = e.detail)}
>
全部可选
</KCheckbox>
</KDivider>
<KCard shadow="never" title="可以修改后再复制" cls="bg-ikun-light-500">
<KCollapseWrapper accordion>
<KCheckboxGroup
{chooseGroup}
on:updateValue={(e) => (chooseGroup = e.detail)}
>
{#each tsTypes as [tsTypeKey, tsTypeValue], tsTypeUid}
<KCollapse uid={`collapse-${tsTypeUid}`} title={tsTypeKey} show>
<div slot="content">
{#each tsTypeValue as [optional, key, value], uid}
<KInput cls="w-full my-8px first:mt-0 last:mb-0" bind:value>
<div
class="flex items-center text-nowrap mr-8px"
slot="prefix"
>
<span>{key}</span>
{#if isChoose || optional}
<span>?</span>
{/if}
<span>: </span>
{#if !isChoose}
<KCheckbox
cls="flex ml-8px"
uid={`${tsTypeKey}-${tsTypeUid}-${key}-${uid}`}
>
可选
</KCheckbox>
{/if}
</div>
</KInput>
{/each}
</div>
</KCollapse>
{/each}
</KCheckboxGroup>
{#each tsTypes as [tsTypeKey, tsTypeValue], tsTypeUid}
<KCollapse uid={`collapse-${tsTypeUid}`} title={tsTypeKey} show>
<div slot="content">
{#each tsTypeValue as [optional, key, value], uid}
<KInput cls="w-full my-8px first:mt-0 last:mb-0" bind:value>
<div
class="flex items-center text-nowrap mr-8px"
slot="prefix"
>
<span>{key}</span>
{#if isChoose || optional}
<span>?</span>
{/if}
<span>: </span>
{#if !isChoose}
<KCheckbox
cls="flex ml-8px"
uid={`${tsTypeKey}-${tsTypeUid}-${key}-${uid}`}
bind:value={optional}
on:updateValue={(e) => (optional = e.detail)}
>
可选
</KCheckbox>
{/if}
</div>
</KInput>
{/each}
</div>
</KCollapse>
{/each}
</KCollapseWrapper>
</KCard>
{/if}
Expand Down

0 comments on commit c023ead

Please sign in to comment.