11const params = new URLSearchParams ( location . search ) ;
22
33const toHex = ( val ) => val . toString ( 16 ) . padStart ( 2 , "0" ) . toUpperCase ( ) ;
4- const strToHexStream = ( str ) => str . split ( "" ) . map ( ( c ) => c . charCodeAt ( 0 ) . toString ( 16 ) ) . join ( "" ) . toUpperCase ( ) ;
4+ const strToHexStream = ( str ) => str . split ( "" ) . map ( ( c ) => c . charCodeAt ( 0 ) . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" ) . toUpperCase ( ) ;
5+ const hexToAscii = ( hex ) => {
6+ let ascii = "" ;
7+ for ( let i = 0 ; i < hex . length ; i += 2 ) {
8+ const byte = hex . substr ( i , 2 ) ;
9+ ascii += String . fromCharCode ( parseInt ( byte , 16 ) ) ;
10+ }
11+ return ascii ;
12+ } ;
513// expose to devtool
614window . toHex = toHex ;
715window . strToHexStream = strToHexStream ;
16+ window . hexToAscii = hexToAscii ;
817
918const copyToClipboard = ( text ) => {
1019 const p = document . createElement ( "p" ) ;
@@ -46,7 +55,7 @@ const App = (props) => {
4655
4756 const [ generatedSspWithTag , setGeneratedSspWithTag ] = React . useState ( "" ) ;
4857
49- const [ aspTags , setAspTags ] = React . useState ( [ { id : 1 , tag : "" , payload : "" } ] ) ;
58+ const [ aspTags , setAspTags ] = React . useState ( [ { id : 1 , tag : "" , payload : "" , payloadMode : "hex" } ] ) ;
5059 const [ nextTagId , setNextTagId ] = React . useState ( 2 ) ;
5160
5261 const [ generatedAsp , setGeneratedAsp ] = React . useState ( "" ) ;
@@ -64,7 +73,7 @@ const App = (props) => {
6473 adf1Aid,
6574 ramQuota,
6675 nvramQuota,
67- aspTags : aspTags . map ( ( { tag, payload} ) => ( { tag, payload} ) )
76+ aspTags : aspTags . map ( ( { tag, payload, payloadMode } ) => ( { tag, payload, payloadMode } ) )
6877 } ;
6978
7079 const blob = new Blob ( [ JSON . stringify ( config , null , 2 ) ] , { type : 'application/json' } ) ;
@@ -102,9 +111,10 @@ const App = (props) => {
102111 const newTags = config . aspTags . map ( ( tag , index ) => ( {
103112 id : index + 1 ,
104113 tag : tag . tag || "" ,
105- payload : tag . payload || ""
114+ payload : tag . payload || "" ,
115+ payloadMode : tag . payloadMode || "hex"
106116 } ) ) ;
107- setAspTags ( newTags . length > 0 ? newTags : [ { id : 1 , tag : "" , payload : "" } ] ) ;
117+ setAspTags ( newTags . length > 0 ? newTags : [ { id : 1 , tag : "" , payload : "" , payloadMode : "hex" } ] ) ;
108118 setNextTagId ( newTags . length + 1 ) ;
109119 }
110120 } catch ( error ) {
@@ -131,11 +141,12 @@ const App = (props) => {
131141 let asp = "" ;
132142
133143 // 各タグを処理
134- aspTags . forEach ( ( { tag, payload} ) => {
144+ aspTags . forEach ( ( { tag, payload, payloadMode } ) => {
135145 if ( tag ) {
136146 const tagHex = tag . toUpperCase ( ) ;
137147 if ( payload ) {
138- const payloadHex = payload . toUpperCase ( ) ;
148+ // asciiモードの場合は変換
149+ const payloadHex = payloadMode === 'ascii' ? strToHexStream ( payload ) . toUpperCase ( ) : payload . toUpperCase ( ) ;
139150 const ll = toHex ( payloadHex . length / 2 ) ;
140151 asp += tagHex + ll + payloadHex ;
141152 } else {
@@ -154,7 +165,7 @@ const App = (props) => {
154165 }
155166
156167 const addTag = ( ) => {
157- setAspTags ( [ ...aspTags , { id : nextTagId , tag : "" , payload : "" } ] ) ;
168+ setAspTags ( [ ...aspTags , { id : nextTagId , tag : "" , payload : "" , payloadMode : "hex" } ] ) ;
158169 setNextTagId ( nextTagId + 1 ) ;
159170 }
160171
@@ -427,29 +438,86 @@ const App = (props) => {
427438 } )
428439 ) ,
429440 React . createElement ( 'div' , null ,
430- React . createElement ( 'label' , { className : 'block mb-2 text-sm font-medium text-gray-900 dark:text-white' } ,
431- 'ペイロード (hex)'
441+ React . createElement ( 'div' , { className : 'flex items-center justify-between mb-2' } ,
442+ React . createElement ( 'label' , { className : 'text-sm font-medium text-gray-900 dark:text-white' } ,
443+ 'ペイロード'
444+ ) ,
445+ React . createElement ( 'div' , { className : 'flex items-center space-x-4' } ,
446+ React . createElement ( 'label' , { className : 'flex items-center' } ,
447+ React . createElement ( 'input' , {
448+ type : 'radio' ,
449+ name : `payloadMode-${ tagItem . id } ` ,
450+ value : 'hex' ,
451+ checked : tagItem . payloadMode === 'hex' ,
452+ onChange : ( ) => {
453+ // 現在asciiモードの場合、hexに変換
454+ if ( tagItem . payloadMode === 'ascii' && tagItem . payload ) {
455+ const hexPayload = strToHexStream ( tagItem . payload ) ;
456+ setAspTags ( aspTags . map ( t =>
457+ t . id === tagItem . id ? { ...t , payloadMode : 'hex' , payload : hexPayload } : t
458+ ) ) ;
459+ } else {
460+ updateTag ( tagItem . id , 'payloadMode' , 'hex' ) ;
461+ }
462+ } ,
463+ className : 'w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
464+ } ) ,
465+ React . createElement ( 'span' , { className : 'ml-2 text-sm text-gray-900 dark:text-gray-300' } , 'hex' )
466+ ) ,
467+ React . createElement ( 'label' , { className : 'flex items-center' } ,
468+ React . createElement ( 'input' , {
469+ type : 'radio' ,
470+ name : `payloadMode-${ tagItem . id } ` ,
471+ value : 'ascii' ,
472+ checked : tagItem . payloadMode === 'ascii' ,
473+ onChange : ( ) => {
474+ // 現在hexモードの場合、asciiに変換(有効なhex文字列の場合のみ)
475+ if ( tagItem . payloadMode === 'hex' && tagItem . payload && tagItem . payload . length % 2 === 0 ) {
476+ try {
477+ const ascii = hexToAscii ( tagItem . payload ) ;
478+ setAspTags ( aspTags . map ( t =>
479+ t . id === tagItem . id ? { ...t , payloadMode : 'ascii' , payload : ascii } : t
480+ ) ) ;
481+ } catch ( e ) {
482+ // 変換できない場合はモードだけ変更
483+ updateTag ( tagItem . id , 'payloadMode' , 'ascii' ) ;
484+ }
485+ } else {
486+ updateTag ( tagItem . id , 'payloadMode' , 'ascii' ) ;
487+ }
488+ } ,
489+ className : 'w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
490+ } ) ,
491+ React . createElement ( 'span' , { className : 'ml-2 text-sm text-gray-900 dark:text-gray-300' } , 'ascii' )
492+ )
493+ )
432494 ) ,
433495 React . createElement ( 'input' , {
434496 type : 'text' ,
435497 className : 'bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white' ,
436498 value : tagItem . payload ,
437499 onChange : ( e ) => {
438- const value = e . target . value . toUpperCase ( ) ;
439- if ( / ^ [ 0 - 9 A - F ] * $ / . test ( value ) ) {
440- updateTag ( tagItem . id , 'payload' , value ) ;
500+ if ( tagItem . payloadMode === 'hex' ) {
501+ const value = e . target . value . toUpperCase ( ) ;
502+ if ( / ^ [ 0 - 9 A - F ] * $ / . test ( value ) ) {
503+ updateTag ( tagItem . id , 'payload' , value ) ;
504+ }
505+ } else {
506+ // asciiモードは制限なし
507+ updateTag ( tagItem . id , 'payload' , e . target . value ) ;
441508 }
442509 } ,
443- placeholder : ' 例: 0123456789ABCDEF'
510+ placeholder : tagItem . payloadMode === 'hex' ? ' 例: 0123456789ABCDEF' : '例: Hello World '
444511 } )
445512 )
446513 ) ,
447514 tagItem . tag && tagItem . payload && React . createElement ( 'div' , { className : 'mt-2' } ,
448515 React . createElement ( 'span' , {
449- className : tagItem . payload . length % 2 !== 0
450- ? 'bg-red-100 text-red-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-red-900 dark:text-red-300'
451- : 'bg-blue-100 text-blue-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300'
452- } , `LL (長さ): ${ tagItem . payload . length % 2 === 0 ? toHex ( tagItem . payload . length / 2 ) : ( tagItem . payload . length / 2 ) . toFixed ( 1 ) } ` )
516+ className : 'bg-blue-100 text-blue-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300'
517+ } , `LL (長さ): ${ ( ( ) => {
518+ const hexPayload = tagItem . payloadMode === 'ascii' ? strToHexStream ( tagItem . payload ) : tagItem . payload ;
519+ return toHex ( hexPayload . length / 2 ) ;
520+ } ) ( ) } `)
453521 )
454522 )
455523 ) ,
0 commit comments