1 parent
6213fec7d2
commit
fdbc9a9d1b
7 files changed
+598
-2
No files matched your search
@@ -0,0 +1,24 @@
|
||||
export type RegistryEntry = {
|
||||
id: string; hive: string; key: string; name: string; view: string; valueType: string; data: string;
|
||||
};
|
||||
export const registryTypes = ['REG_SZ', 'REG_EXPAND_SZ', 'REG_DWORD', 'REG_QWORD', 'REG_MULTI_SZ', 'REG_BINARY'];
|
||||
const esc = (value: string) => value.replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]!);
|
||||
export function newRegistryEntry(architecture: string, id = `registry-${crypto.randomUUID()}`): RegistryEntry {
|
||||
return { id, hive: 'HKLM', key: 'Software\\Baron\\Application', name: '', view: architecture === 'x86' ? '32' : '64', valueType: 'REG_SZ', data: '' };
|
||||
}
|
||||
export function renderRegistryEditor(entries: RegistryEntry[], disabled: boolean): string {
|
||||
const lock = disabled ? 'disabled' : '';
|
||||
return `<div class="callout"><strong>MSIX 앱 전용 레지스트리</strong><br>HKLM\\Software 아래의 설정을 패키지에 포함합니다. 빌드 PC의 레지스트리는 변경하지 않습니다. HKCU 초기화와 시스템 전체 COM·파일 연결 등록은 아직 지원하지 않습니다.</div>
|
||||
<div class="registry-toolbar"><strong>${entries.length}개 설정</strong><button class="primary" data-action="registry-add" ${lock}>레지스트리 값 추가</button></div>
|
||||
${entries.length ? '' : '<p class="muted">등록된 값이 없습니다. 필요한 키, 값 이름, 형식과 데이터를 추가하세요.</p>'}
|
||||
${entries.map((entry, index) => {
|
||||
const path = `registry.${index}`;
|
||||
const input = (label: string, key: keyof RegistryEntry, help = '') => `<label class="field">${label}<input data-field="${path}.${key}" value="${esc(entry[key])}" ${lock}><small>${help}</small></label>`;
|
||||
const select = (label: string, key: keyof RegistryEntry, choices: string[]) => `<label class="field">${label}<select data-field="${path}.${key}" ${lock}>${[...new Set([entry[key], ...choices])].map(value => `<option value="${esc(value)}" ${value === entry[key] ? 'selected' : ''}>${esc(value)}</option>`).join('')}</select></label>`;
|
||||
return `<section class="registry-card" aria-label="레지스트리 항목 ${index + 1}"><div class="registry-toolbar"><strong>항목 ${index + 1}</strong><button data-action="registry-remove:${index}" ${lock} aria-label="레지스트리 항목 ${index + 1} 삭제">삭제</button></div><div class="form-grid">
|
||||
${input('항목 ID', 'id', '프로젝트 안에서 고유한 ID')}${select('루트', 'hive', ['HKLM'])}
|
||||
${input('키 경로', 'key', '예: Software\\Baron\\EG-BIM')}${select('레지스트리 뷰', 'view', ['64', '32'])}
|
||||
${input('값 이름', 'name', '비워 두면 해당 키의 기본값')}${select('값 형식', 'valueType', registryTypes)}
|
||||
</div><label class="field">데이터<textarea data-field="${path}.data" rows="3" spellcheck="false" ${lock}>${esc(entry.data)}</textarea><small>문자열은 그대로 저장합니다. 숫자는 10진수 또는 0x16진수, MULTI_SZ는 한 줄에 한 값, BINARY는 00 FF처럼 입력하세요. QWORD도 숫자 손실 없이 저장합니다. [INSTALLDIR] 같은 MSI 속성은 치환하지 않습니다.</small></label></section>`;
|
||||
}).join('')}`;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { newRegistryEntry, renderRegistryEditor } from '../src/registry-editor.ts';
|
||||
|
||||
test('new entries select the app view and preserve lossless text data', () => {
|
||||
assert.equal(newRegistryEntry('x86', 'one').view, '32');
|
||||
const entry = newRegistryEntry('x64', 'two');
|
||||
entry.valueType = 'REG_QWORD'; entry.data = '18446744073709551615';
|
||||
assert.match(renderRegistryEditor([entry], false), /18446744073709551615/);
|
||||
assert.equal(JSON.parse(JSON.stringify(entry)).data, entry.data);
|
||||
});
|
||||
test('registry editor escapes markup and addresses rows after deletion', () => {
|
||||
const first = newRegistryEntry('x64', 'first');
|
||||
const second = newRegistryEntry('x64', 'second');
|
||||
second.data = '</textarea><script>alert(1)</script>';
|
||||
second.name = '" onfocus="bad';
|
||||
const entries = [first, second]; entries.splice(0, 1);
|
||||
const html = renderRegistryEditor(entries, true);
|
||||
assert.ok(!html.includes('<script>'));
|
||||
assert.ok(html.includes('</textarea>'));
|
||||
assert.ok(html.includes('" onfocus="bad'));
|
||||
assert.ok(html.includes('registry.0.data'));
|
||||
assert.ok(html.includes('data-action="registry-remove:0" disabled'));
|
||||
});
|
||||
Reference in new issue
Block a user