Skip to content

Commit

Permalink
feat(Barcode Generator): use bwip-js to add more barcode types
Browse files Browse the repository at this point in the history
Including Datamatrix, fix CorentinTh#1343
  • Loading branch information
sharevb committed Jan 26, 2025
1 parent 47917dc commit 77b6b39
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 54 deletions.
1 change: 0 additions & 1 deletion components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ declare module '@vue/runtime-core' {
NCode: typeof import('naive-ui')['NCode']
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDivider: typeof import('naive-ui')['NDivider']
NEllipsis: typeof import('naive-ui')['NEllipsis']
NginxFormatter: typeof import('./src/tools/nginx-formatter/nginx-formatter.vue')['default']
NH1: typeof import('naive-ui')['NH1']
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"apache-md5": "^1.1.8",
"arr-diff": "^4.0.0",
"bcryptjs": "^2.4.3",
"bwip-js": "^4.5.1",
"big.js": "^6.2.2",
"change-case": "^4.1.2",
"chatgpt-prompt-splitter": "^1.0.5",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

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

124 changes: 71 additions & 53 deletions src/tools/barcode-generator/barcode-generator.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,61 @@
<script setup lang="ts">
import VueBarcode from '@chenfengyuan/vue-barcode';
import JsBarcode from 'jsbarcode';
import bwipjs, { type RenderOptions } from 'bwip-js/browser';
import { Base64 } from 'js-base64';
import formats from './barcode.formats.json';
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
import { useQueryParamOrStorage } from '@/composable/queryParams';
const foreground = useQueryParamOrStorage({ name: 'fg', storageName: 'barcode-gen:fg', defaultValue: '#000000ff' });
const background = useQueryParamOrStorage({ name: 'bg', storageName: 'barcode-gen:bg', defaultValue: '#ffffffff' });
const width = useQueryParamOrStorage({ name: 'width', storageName: 'barcode-gen:width', defaultValue: 2 });
const height = useQueryParamOrStorage({ name: 'height', storageName: 'barcode-gen:height', defaultValue: 100 });
const foreground = useQueryParamOrStorage({ name: 'fg', storageName: 'barcode-gen:fg', defaultValue: '#000000' });
const background = useQueryParamOrStorage({ name: 'bg', storageName: 'barcode-gen:bg', defaultValue: '#FFFFFF' });
const scale = useQueryParamOrStorage({ name: 'scale', storageName: 'barcode-gen:scale', defaultValue: 2 });
const height = useQueryParamOrStorage({ name: 'height', storageName: 'barcode-gen:height', defaultValue: 25 });
const margin = useQueryParamOrStorage({ name: 'margin', storageName: 'barcode-gen:margin', defaultValue: 10 });
const format = useQueryParamOrStorage({ name: 'format', storageName: 'barcode-gen:format', defaultValue: 'auto' });
const format = useQueryParamOrStorage({ name: 'format', storageName: 'barcode-gen:format', defaultValue: 'code128' });
const displayValue = useQueryParamOrStorage({ name: 'display', storageName: 'barcode-gen:display', defaultValue: true });
const ean128 = useQueryParamOrStorage({ name: 'ean128', storageName: 'barcode-gen:ean128', defaultValue: false });
const value = ref('123456789');
const barcodeCanvas = ref<HTMLCanvasElement>();
const options = computed(() => ({
lineColor: foreground.value,
background: background.value,
width: width.value,
const options = computed<RenderOptions>(() => ({
barcolor: foreground.value,
textcolor: foreground.value,
backgroundcolor: background.value,
scale: scale.value,
height: height.value,
margin: margin.value,
format: format.value === 'auto' ? 'CODE128' : format.value,
displayValue: displayValue.value,
ean128: ean128.value,
padding: margin.value,
bcid: format.value === 'auto' ? 'code128' : format.value,
includetext: displayValue.value,
text: value.value,
textxalign: 'center',
}));
const formats = [
'auto',
'CODE39',
'CODE128', 'CODE128A', 'CODE128B', 'CODE128C',
'EAN13', 'EAN8', 'EAN5', 'EAN2', 'UPC', 'UPCE',
'ITF14',
'ITF',
'MSI', 'MSI10', 'MSI11', 'MSI1010', 'MSI1110',
'pharmacode',
'codabar',
'GenericBarcode',
];
const error = ref('');
watchEffect(() => {
if (!barcodeCanvas.value) {
return;
}
try {
bwipjs.toCanvas(barcodeCanvas.value, options.value);
}
catch (e: any) {
error.value = e.toString();
}
});
const barcodePNG = computed(() => {
const canvas = document.createElement('canvas');
JsBarcode(canvas, value.value, options.value);
return canvas.toDataURL('image/png');
return barcodeCanvas.value?.toDataURL('image/png') || '';
});
const barcodeSVG = computed(() => {
try {
return Base64.encode(bwipjs.toSVG(options.value));
}
catch (e: any) {
return '';
}
});
const { download } = useDownloadFileFromBase64({ source: barcodePNG, filename: 'barcode.png' });
const { download: downloadPNG } = useDownloadFileFromBase64({ source: barcodePNG, filename: 'barcode.png' });
const { download: downloadSVG } = useDownloadFileFromBase64({ source: barcodeSVG, filename: 'barcode.svg' });
</script>

<template>
Expand All @@ -61,20 +71,31 @@ const { download } = useDownloadFileFromBase64({ source: barcodePNG, filename: '
multiline
rows="1"
autosize
placeholder="Your text..."
placeholder="Your barcode..."
mb-6
/>
<n-form label-width="130" label-placement="left">
<c-select
v-model:value="format"
label="Format:"
label-position="left"
label-width="130px"
label-align="right"
:options="formats"
searchable
mb-4
/>

<n-form-item label="Foreground color:">
<n-color-picker v-model:value="foreground" :modes="['hex']" />
<n-color-picker v-model:value="foreground" :modes="['hex']" :show-alpha="false" />
</n-form-item>
<n-form-item label="Background color:">
<n-color-picker v-model:value="background" :modes="['hex']" />
<n-color-picker v-model:value="background" :modes="['hex']" :show-alpha="false" />
</n-form-item>
<n-form-item label="Width:">
<n-input-number v-model:value="width" :min="0" />
<n-form-item label="Scale:">
<n-input-number v-model:value="scale" :min="0" />
</n-form-item>
<n-form-item label="Height:">
<n-form-item label="Height (mm):">
<n-input-number v-model:value="height" :min="0" />
</n-form-item>
<n-form-item label="Margin:">
Expand All @@ -83,25 +104,22 @@ const { download } = useDownloadFileFromBase64({ source: barcodePNG, filename: '
<n-form-item label="Display text:">
<n-checkbox v-model:checked="displayValue" />
</n-form-item>
<c-select
v-model:value="format"
label="Format:"
label-position="left"
label-width="130px"
label-align="right"
:options="formats.map((value) => ({ label: value, value }))"
/>
</n-form>
</n-gi>
<n-gi>
<div flex flex-col items-center gap-3>
<VueBarcode
:options="options"
:value="value"
/>
<c-button @click="download">
Download barcode
</c-button>
<c-alert v-if="error">
{{ error }}
</c-alert>
<canvas ref="barcodeCanvas" />
<div flex justify-center>
<c-button mr-2 @click="downloadPNG">
Download PNG barcode
</c-button>
<c-button @click="downloadSVG">
Download SVG barcode
</c-button>
</div>
</div>
</n-gi>
</n-grid>
Expand Down
112 changes: 112 additions & 0 deletions src/tools/barcode-generator/barcode.formats.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[
{ "value": "auspost", "label": "AusPost 4 State Customer Code" },
{ "value": "azteccode", "label": "Aztec Code" },
{ "value": "azteccodecompact", "label": "Compact Aztec Code" },
{ "value": "aztecrune", "label": "Aztec Runes" },
{ "value": "bc412", "label": "BC412" },
{ "value": "channelcode", "label": "Channel Code" },
{ "value": "codablockf", "label": "Codablock F" },
{ "value": "code11", "label": "Code 11" },
{ "value": "code128", "label": "Code 128" },
{ "value": "code16k", "label": "Code 16K" },
{ "value": "code2of5", "label": "Code 25" },
{ "value": "code32", "label": "Italian Pharmacode" },
{ "value": "code39", "label": "Code 39" },
{ "value": "code39ext", "label": "Code 39 Extended" },
{ "value": "code49", "label": "Code 49" },
{ "value": "code93", "label": "Code 93" },
{ "value": "code93ext", "label": "Code 93 Extended" },
{ "value": "codeone", "label": "Code One" },
{ "value": "coop2of5", "label": "COOP 2 of 5" },
{ "value": "daft", "label": "Custom 4 state symbology" },
{ "value": "databarexpanded", "label": "GS1 DataBar Expanded" },
{ "value": "databarexpandedcomposite", "label": "GS1 DataBar Expanded Composite" },
{ "value": "databarexpandedstacked", "label": "GS1 DataBar Expanded Stacked" },
{ "value": "databarexpandedstackedcomposite", "label": "GS1 DataBar Expanded Stacked Composite" },
{ "value": "databarlimited", "label": "GS1 DataBar Limited" },
{ "value": "databarlimitedcomposite", "label": "GS1 DataBar Limited Composite" },
{ "value": "databaromni", "label": "GS1 DataBar Omnidirectional" },
{ "value": "databaromnicomposite", "label": "GS1 DataBar Omnidirectional Composite" },
{ "value": "databarstacked", "label": "GS1 DataBar Stacked" },
{ "value": "databarstackedcomposite", "label": "GS1 DataBar Stacked Composite" },
{ "value": "databarstackedomni", "label": "GS1 DataBar Stacked Omnidirectional" },
{ "value": "databarstackedomnicomposite", "label": "GS1 DataBar Stacked Omnidirectional Composite" },
{ "value": "databartruncated", "label": "GS1 DataBar Truncated" },
{ "value": "databartruncatedcomposite", "label": "GS1 DataBar Truncated Composite" },
{ "value": "datalogic2of5", "label": "Datalogic 2 of 5" },
{ "value": "datamatrix", "label": "Data Matrix" },
{ "value": "datamatrixrectangular", "label": "Data Matrix Rectangular" },
{ "value": "datamatrixrectangularextension", "label": "Data Matrix Rectangular Extension" },
{ "value": "dotcode", "label": "DotCode" },
{ "value": "ean13", "label": "EAN-13" },
{ "value": "ean13composite", "label": "EAN-13 Composite" },
{ "value": "ean14", "label": "GS1-14" },
{ "value": "ean2", "label": "EAN-2 (2 digit addon)" },
{ "value": "ean5", "label": "EAN-5 (5 digit addon)" },
{ "value": "ean8", "label": "EAN-8" },
{ "value": "ean8composite", "label": "EAN-8 Composite" },
{ "value": "flattermarken", "label": "Flattermarken" },
{ "value": "gs1-128", "label": "GS1-128" },
{ "value": "gs1-128composite", "label": "GS1-128 Composite" },
{ "value": "gs1-cc", "label": "GS1 Composite 2D Component" },
{ "value": "gs1datamatrix", "label": "GS1 Data Matrix" },
{ "value": "gs1datamatrixrectangular", "label": "GS1 Data Matrix Rectangular" },
{ "value": "gs1dldatamatrix", "label": "GS1 Digital Link Data Matrix" },
{ "value": "gs1dlqrcode", "label": "GS1 Digital Link QR Code" },
{ "value": "gs1dotcode", "label": "GS1 DotCode" },
{ "value": "gs1northamericancoupon", "label": "GS1 North American Coupon" },
{ "value": "gs1qrcode", "label": "GS1 QR Code" },
{ "value": "hanxin", "label": "Han Xin Code" },
{ "value": "hibcazteccode", "label": "HIBC Aztec Code" },
{ "value": "hibccodablockf", "label": "HIBC Codablock F" },
{ "value": "hibccode128", "label": "HIBC Code 128" },
{ "value": "hibccode39", "label": "HIBC Code 39" },
{ "value": "hibcdatamatrix", "label": "HIBC Data Matrix" },
{ "value": "hibcdatamatrixrectangular", "label": "HIBC Data Matrix Rectangular" },
{ "value": "hibcmicropdf417", "label": "HIBC MicroPDF417" },
{ "value": "hibcpdf417", "label": "HIBC PDF417" },
{ "value": "hibcqrcode", "label": "HIBC QR Code" },
{ "value": "iata2of5", "label": "IATA 2 of 5" },
{ "value": "identcode", "label": "Deutsche Post Identcode" },
{ "value": "industrial2of5", "label": "Industrial 2 of 5" },
{ "value": "interleaved2of5", "label": "Interleaved 2 of 5 (ITF)" },
{ "value": "isbn", "label": "ISBN" },
{ "value": "ismn", "label": "ISMN" },
{ "value": "issn", "label": "ISSN" },
{ "value": "itf14", "label": "ITF-14" },
{ "value": "japanpost", "label": "Japan Post 4 State Customer Code" },
{ "value": "kix", "label": "Royal Dutch TPG Post KIX" },
{ "value": "leitcode", "label": "Deutsche Post Leitcode" },
{ "value": "mailmark", "label": "Royal Mail Mailmark" },
{ "value": "mands", "label": "Marks & Spencer" },
{ "value": "matrix2of5", "label": "Matrix 2 of 5" },
{ "value": "maxicode", "label": "MaxiCode" },
{ "value": "micropdf417", "label": "MicroPDF417" },
{ "value": "microqrcode", "label": "Micro QR Code" },
{ "value": "msi", "label": "MSI Modified Plessey" },
{ "value": "onecode", "label": "USPS Intelligent Mail" },
{ "value": "pdf417", "label": "PDF417" },
{ "value": "pdf417compact", "label": "Compact PDF417" },
{ "value": "pharmacode", "label": "Pharmaceutical Binary Code" },
{ "value": "pharmacode2", "label": "Two-track Pharmacode" },
{ "value": "planet", "label": "USPS PLANET" },
{ "value": "plessey", "label": "Plessey UK" },
{ "value": "posicode", "label": "PosiCode" },
{ "value": "postnet", "label": "USPS POSTNET" },
{ "value": "pzn", "label": "Pharmazentralnummer (PZN)" },
{ "value": "qrcode", "label": "QR Code" },
{ "value": "rationalizedCodabar", "label": "Codabar" },
{ "value": "raw", "label": "Custom 1D symbology" },
{ "value": "rectangularmicroqrcode", "label": "Rectangular Micro QR Code" },
{ "value": "royalmail", "label": "Royal Mail 4 State Customer Code" },
{ "value": "sscc18", "label": "SSCC-18" },
{ "value": "swissqrcode", "label": "Swiss QR Code" },
{ "value": "symbol", "label": "Miscellaneous symbols" },
{ "value": "telepen", "label": "Telepen" },
{ "value": "telepennumeric", "label": "Telepen Numeric" },
{ "value": "ultracode", "label": "Ultracode" },
{ "value": "upca", "label": "UPC-A" },
{ "value": "upcacomposite", "label": "UPC-A Composite" },
{ "value": "upce", "label": "UPC-E" },
{ "value": "upcecomposite", "label": "UPC-E Composite" }
]
Loading

0 comments on commit 77b6b39

Please sign in to comment.