This commit is contained in:
utf26 2024-04-15 16:27:12 +02:00 committed by GitHub
commit 5e61907de6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 167 additions and 8 deletions

30
components.d.ts vendored
View file

@ -89,22 +89,34 @@ declare module '@vue/runtime-core' {
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default']
'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default']
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
IconMdiArrowDown: typeof import('~icons/mdi/arrow-down')['default']
IconMdiArrowRightBottom: typeof import('~icons/mdi/arrow-right-bottom')['default']
IconMdiCamera: typeof import('~icons/mdi/camera')['default']
IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
IconMdiClose: typeof import('~icons/mdi/close')['default']
IconMdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
IconMdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default']
IconMdiDownload: typeof import('~icons/mdi/download')['default']
IconMdiEye: typeof import('~icons/mdi/eye')['default']
IconMdiEyeOff: typeof import('~icons/mdi/eye-off')['default']
IconMdiHeart: typeof import('~icons/mdi/heart')['default']
IconMdiPause: typeof import('~icons/mdi/pause')['default']
IconMdiPlay: typeof import('~icons/mdi/play')['default']
IconMdiRecord: typeof import('~icons/mdi/record')['default']
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
IconMdiSearch: typeof import('~icons/mdi/search')['default']
IconMdiTranslate: typeof import('~icons/mdi/translate')['default']
IconMdiTriangleDown: typeof import('~icons/mdi/triangle-down')['default']
IconMdiVideo: typeof import('~icons/mdi/video')['default']
InputCopyable: typeof import('./src/components/InputCopyable.vue')['default']
IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default']
Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default']
Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default']
Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default']
Ipv6SubnetCalculator: typeof import('./src/tools/ipv6-subnet-calculator/ipv6-subnet-calculator.vue')['default']
Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default']
JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default']
JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default']
@ -126,25 +138,40 @@ declare module '@vue/runtime-core' {
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
NAlert: typeof import('naive-ui')['NAlert']
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
NCheckbox: typeof import('naive-ui')['NCheckbox']
NCode: typeof import('naive-ui')['NCode']
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
NColorPicker: typeof import('naive-ui')['NColorPicker']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDatePicker: typeof import('naive-ui')['NDatePicker']
NDivider: typeof import('naive-ui')['NDivider']
NDynamicInput: typeof import('naive-ui')['NDynamicInput']
NEllipsis: typeof import('naive-ui')['NEllipsis']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NH1: typeof import('naive-ui')['NH1']
NH2: typeof import('naive-ui')['NH2']
NH3: typeof import('naive-ui')['NH3']
NIcon: typeof import('naive-ui')['NIcon']
NImage: typeof import('naive-ui')['NImage']
NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NLabel: typeof import('naive-ui')['NLabel']
NLayout: typeof import('naive-ui')['NLayout']
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
NMenu: typeof import('naive-ui')['NMenu']
NProgress: typeof import('naive-ui')['NProgress']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSlider: typeof import('naive-ui')['NSlider']
NSpin: typeof import('naive-ui')['NSpin']
NStatistic: typeof import('naive-ui')['NStatistic']
NSwitch: typeof import('naive-ui')['NSwitch']
NTable: typeof import('naive-ui')['NTable']
NTag: typeof import('naive-ui')['NTag']
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']
@ -159,6 +186,7 @@ declare module '@vue/runtime-core' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default']

View file

@ -303,6 +303,10 @@ tools:
ipv4-subnet-calculator:
title: IPv4 subnet calculator
description: Parse your IPv4 CIDR blocks and get all the info you need about your sub network.
ipv6-subnet-calculator:
title: IPv6 subnet calculator
description: Parse your IPv6 CIDR blocks and get all the info you need about your sub network.
og-meta-generator:
title: Open graph meta generator

View file

@ -299,6 +299,10 @@ tools:
ipv4-subnet-calculator:
title: IPv4子网计算器
description: 解析IPv4 CIDR块并获取有关子网络的所有所需信息。
ipv6-subnet-calculator:
title: IPv6子网计算器
description: 解析IPv6 CIDR块并获取有关子网络的所有所需信息。
og-meta-generator:
title: 开放式图形元生成器

View file

@ -64,6 +64,7 @@
"highlight.js": "^11.7.0",
"iarna-toml-esm": "^3.0.5",
"ibantools": "^4.3.3",
"ip-address": "^9.0.5",
"json5": "^2.2.3",
"jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28",

28
pnpm-lock.yaml generated
View file

@ -92,6 +92,9 @@ dependencies:
ibantools:
specifier: ^4.3.3
version: 4.3.3
ip-address:
specifier: ^9.0.5
version: 9.0.5
json5:
specifier: ^2.2.3
version: 2.2.3
@ -3351,7 +3354,7 @@ packages:
dependencies:
'@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1
'@vueuse/shared': 10.7.2(vue@3.3.4)
'@vueuse/shared': 10.9.0(vue@3.3.4)
unhead: 0.5.1
vue: 3.3.4
transitivePeerDependencies:
@ -3993,10 +3996,10 @@ packages:
- vue
dev: false
/@vueuse/shared@10.7.2(vue@3.3.4):
resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
/@vueuse/shared@10.9.0(vue@3.3.4):
resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
dependencies:
vue-demi: 0.14.6(vue@3.3.4)
vue-demi: 0.14.7(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@ -6177,6 +6180,14 @@ packages:
sprintf-js: 1.1.2
dev: false
/ip-address@9.0.5:
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
engines: {node: '>= 12'}
dependencies:
jsbn: 1.1.0
sprintf-js: 1.1.3
dev: false
/ip-cidr@3.1.0:
resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==}
engines: {node: '>=10.0.0'}
@ -8183,6 +8194,10 @@ packages:
resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==}
dev: false
/sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
dev: false
/sql-formatter@13.0.0:
resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==}
hasBin: true
@ -9151,8 +9166,8 @@ packages:
vue: 3.3.4
dev: false
/vue-demi@0.14.6(vue@3.3.4):
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
/vue-demi@0.14.7(vue@3.3.4):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
@ -9442,6 +9457,7 @@ packages:
/workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
dependencies:
workbox-background-sync: 7.0.0
workbox-core: 7.0.0

View file

@ -34,6 +34,7 @@ import { tool as ipv4AddressConverter } from './ipv4-address-converter';
import { tool as benchmarkBuilder } from './benchmark-builder';
import { tool as userAgentParser } from './user-agent-parser';
import { tool as ipv4SubnetCalculator } from './ipv4-subnet-calculator';
import { tool as ipv6SubnetCalculator } from './ipv6-subnet-calculator';
import { tool as dockerRunToDockerComposeConverter } from './docker-run-to-docker-compose-converter';
import { tool as htmlWysiwygEditor } from './html-wysiwyg-editor';
import { tool as rsaKeyPairGenerator } from './rsa-key-pair-generator';
@ -152,7 +153,7 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Network',
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator],
components: [ipv4SubnetCalculator, ipv6SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator],
},
{
name: 'Math',

View file

@ -0,0 +1,12 @@
import { RouterOutlined } from '@vicons/material';
import { defineTool } from '../tool';
import { translate } from '@/plugins/i18n.plugin';
export const tool = defineTool({
name: translate('tools.ipv6-subnet-calculator.title'),
path: '/ipv6-subnet-calculator',
description: translate('tools.ipv6-subnet-calculator.description'),
keywords: ['ipv6', 'subnet', 'calculator', 'mask', 'network', 'cidr', 'netmask', 'bitmask', 'broadcast', 'address'],
component: () => import('./ipv6-subnet-calculator.vue'),
icon: RouterOutlined,
});

View file

@ -0,0 +1,93 @@
<script setup lang="ts">
import { Address6 } from 'ip-address';
import { useStorage } from '@vueuse/core';
import { withDefaultOnError } from '@/utils/defaults';
import { isNotThrowing } from '@/utils/boolean';
import SpanCopyable from '@/components/SpanCopyable.vue';
const ip = useStorage('ipv6-subnet-calculator:ip', 'fd00::1/64');
const getNetworkInfo = (address: string) => new Address6(address.trim());
const networkInfo = computed(() => withDefaultOnError(() => getNetworkInfo(ip.value), undefined));
const ipValidationRules = [
{
message: 'We cannot parse this address, check the format',
validator: (value: string) => isNotThrowing(() => getNetworkInfo(value.trim())),
},
];
const sections: {
label: string
getValue: (blocks: Address6) => string | undefined
undefinedFallback?: string
}[] = [
{
label: 'IP address',
getValue: (block: Address6) => block.correctForm(),
},
{
label: 'Full IP address',
getValue: (block: Address6) => block.canonicalForm(),
},
{
label: 'Total IP addresses',
getValue: (block: Address6) => {
const totalAddresses = BigInt(2) ** BigInt(128 - block.subnetMask);
return totalAddresses.toString();
},
},
{
label: 'Total networks',
getValue: ({ subnetMask }) => subnetMask <= 64 ? (BigInt(2) ** BigInt(64 - subnetMask)).toString() : '',
},
{
label: 'Netmask',
getValue: ({ subnetMask }) => subnetMask.toString(),
},
{
label: 'Network size',
getValue: (block: Address6) => block.possibleSubnets().toString(),
},
{
label: 'First address',
getValue: (block: Address6) => block.startAddress().correctForm(),
},
{
label: 'Last address',
getValue: (block: Address6) => block.endAddress().correctForm(),
},
{
label: 'IP range',
getValue: (block: Address6) => `${block.startAddress().correctForm()} - ${block.endAddress().correctForm()}`,
},
];
</script>
<template>
<div>
<c-input-text
v-model:value="ip" label="An IPv6 address with or without mask" placeholder="The ipv6 address..."
:validation-rules="ipValidationRules" mb-4
/>
<div v-if="networkInfo">
<n-table>
<tbody>
<tr v-for="{ getValue, label, undefinedFallback } in sections" :key="label">
<td font-bold>
{{ label }}
</td>
<td>
<SpanCopyable v-if="getValue(networkInfo)" :value="getValue(networkInfo)" />
<span v-else op-70>
{{ undefinedFallback }}
</span>
</td>
</tr>
</tbody>
</n-table>
</div>
</div>
</template>