Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions e2e/harness/tsLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ function createTsLoader(options = {}) {
const target = resolveRelative(abs, request);
const targetRel = toRepoRelative(target);
if (Object.prototype.hasOwnProperty.call(mocks, targetRel)) return mocks[targetRel];
// Mirrors webpack's `asset/source` rule for stylesheets: the import is the file's text.
if (target.endsWith('.css')) return { __esModule: true, default: fs.readFileSync(target, 'utf8') };
return load(targetRel);
}
return repoRequire(request);
Expand Down
17 changes: 11 additions & 6 deletions scripts/test-webview.js
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,8 @@ function testObjModSaveCommitsFocusedEditor() {

function testObjModTooltipFontWiring() {
const host = fs.readFileSync(path.join(root, 'src/features/objModPreview.ts'), 'utf8');
// Viewer CSS lives in its own stylesheet now; only the runtime @font-face rule stays in the host.
const css = fs.readFileSync(path.join(root, 'src/webview/objModEditor/objModEditor.css'), 'utf8');
const packageJson = fs.readFileSync(path.join(root, 'package.json'), 'utf8');
const packageData = JSON.parse(packageJson);

Expand All @@ -1059,10 +1061,10 @@ function testObjModTooltipFontWiring() {
assert.ok(host.includes('@font-face'), 'objmod should declare the project font for tooltip previews');
assert.ok(!host.includes("Buffer.from(bytes).toString('base64')"), 'project fonts should not be embedded as large data URLs');
assert.ok(/\.tt-collapsed-box,\r?\n\.tt-preview \{/.test(host), 'the custom font should be assigned only to tooltip boxes');
assert.ok(!host.includes('.tt-collapsed-box *'), 'the custom font should not use descendant-wide override selectors');
assert.ok(host.includes('td.value { font-family: var(--font); }'), 'ordinary field values should use the VS Code UI font');
assert.ok(host.includes('.tt-empty { color: var(--muted); font-style: normal; }'), 'ordinary empty values should not be italicized');
assert.ok(host.includes('.tt-collapsed-box .tt-empty,'), 'only framed WC3 text may retain the italic empty placeholder');
assert.ok(!host.includes('.tt-collapsed-box *') && !css.includes('.tt-collapsed-box *'), 'the custom font should not use descendant-wide override selectors');
assert.ok(css.includes('td.value { font-family: var(--font); }'), 'ordinary field values should use the VS Code UI font');
assert.ok(css.includes('.tt-empty { color: var(--muted); font-style: normal; }'), 'ordinary empty values should not be italicized');
assert.ok(css.includes('.tt-collapsed-box .tt-empty,'), 'only framed WC3 text may retain the italic empty placeholder');
assert.ok(packageJson.includes('wurst.objModTooltipFont'), 'the tooltip font setting should be contributed by the extension');
assert.equal(packageData.contributes.configuration.properties['wurst.objModTooltipFont'].default, '', 'the tooltip font setting must default to disabled');
}
Expand Down Expand Up @@ -1164,11 +1166,14 @@ function testObjModSavedAndUsedTooltipColors() {
assert.ok(host.includes("context.globalState"), 'saved custom colors should follow the user across workspaces');
assert.ok(host.includes("msg.type === 'rememberCustomColor'"), 'the objmod host should persist custom colors sent by the picker');
assert.ok(host.includes('customColors,'), 'saved custom colors should be restored into new objmod webviews');
assert.ok(host.includes('.tt-custom-colors[hidden] { display: none; }'), 'an empty saved palette should remain hidden despite its flex layout');
const css = fs.readFileSync(path.join(root, 'src/webview/objModEditor/objModEditor.css'), 'utf8');
assert.ok(css.includes('.tt-custom-colors[hidden] { display: none; }'), 'an empty saved palette should remain hidden despite its flex layout');
}

function testObjModDensityAndTreeStyling() {
const host = fs.readFileSync(path.join(root, 'src/features/objModPreview.ts'), 'utf8');
// Host markup plus the extracted stylesheet: these guards cover both the DOM and its CSS.
const host = fs.readFileSync(path.join(root, 'src/features/objModPreview.ts'), 'utf8')
+ '\n' + fs.readFileSync(path.join(root, 'src/webview/objModEditor/objModEditor.css'), 'utf8');
const webview = fs.readFileSync(path.join(root, 'src/webview/objModEditorWebview.ts'), 'utf8');

assert.ok(host.includes('id="density-toggle" class="density-toggle" role="switch"'), 'density must render as an obvious switch control');
Expand Down
181 changes: 2 additions & 179 deletions src/features/mapDataPreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as fs from 'fs';
import * as vscode from 'vscode';
import { BinReader, BinWriter, parseW3i as parseW3iFile, serializeW3i, W3iFile, W3iPlayer, W3iForce } from 'casc-ts/formats';
import { BinaryEdit, EditableBinaryDocument, EditableBinaryEditorProvider, ParsedPreviewContext, registerParsedPreviewer } from './preview/framework';
import MAP_DATA_CSS from '../webview/mapData.css';
import {
loadTriggerStringsForUri, resolveTriggerString, ResolvedText, TriggerStringTable,
findWtsUri, applyWtsEdits,
Expand Down Expand Up @@ -387,185 +388,7 @@ function page(title: string, body: string, extraCss = '', scripts = false): stri
: "default-src 'none'; style-src 'unsafe-inline';",
title: escapeHtml(title),
extraCss: `
.content { flex: 1; overflow: auto; }
.md-header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px 9px;
border-bottom: 1px solid var(--border);
background: var(--sidebar);
}
.md-title {
color: var(--vscode-textLink-foreground, var(--fg));
font-size: 15px;
font-weight: 600;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.md-meta { color: var(--muted); font-size: 12px; margin-top: 1px; }
.readonly-badge {
display: inline-block;
margin-left: 8px;
padding: 1px 5px;
border: 1px solid var(--border);
border-radius: 2px;
color: var(--muted);
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
}
.dialog { max-width: 1060px; padding: 14px 16px 22px; }
h2 {
color: var(--fg);
font-size: 12px;
font-weight: 600;
margin: 0 0 9px;
}
.section {
border-top: 1px solid var(--border);
padding-top: 12px;
margin-top: 14px;
}
.section:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
gap: 9px 12px;
}
.form-grid.compact { grid-template-columns: repeat(auto-fit, minmax(145px, 1fr)); }
.field { min-width: 0; }
.field.wide { grid-column: 1 / -1; }
.field-label {
display: flex;
align-items: center;
gap: 6px;
color: var(--muted);
font-size: 11px;
line-height: 1.25;
margin-bottom: 3px;
}
.source-pill {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border: 1px solid var(--border);
border-radius: 2px;
padding: 0 4px;
color: var(--vscode-textLink-foreground, var(--muted));
font-family: var(--mono);
font-size: 10px;
}
.source-pill.missing {
color: var(--vscode-errorForeground, #f14c4c);
}
.field-control {
width: 100%;
min-width: 0;
height: 26px;
padding: 3px 6px;
color: var(--input-fg);
background: var(--input-bg);
border: 1px solid var(--input-border, var(--border));
border-radius: 2px;
font: inherit;
line-height: 18px;
}
textarea.field-control {
height: auto;
min-height: 58px;
resize: none;
line-height: 1.35;
}
.field-control:disabled {
opacity: 1;
cursor: default;
}
.field-control.mono { font-family: var(--mono); }
.checkbox-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 7px 14px;
}
.check-row {
display: flex;
align-items: flex-start;
gap: 7px;
min-width: 0;
color: var(--fg);
}
.check-row input {
flex: 0 0 auto;
margin: 1px 0 0;
accent-color: var(--vscode-checkbox-selectBackground, var(--vscode-button-background));
}
.check-row input:disabled { opacity: 1; }
.check-row span {
min-width: 0;
overflow-wrap: anywhere;
}
.empty { color: var(--muted); font-style: italic; }
.error {
color: var(--vscode-errorForeground, #f14c4c);
border: 1px solid color-mix(in srgb, currentColor 65%, transparent);
padding: 7px 9px;
margin-bottom: 12px;
border-radius: 2px;
}
.table-wrap {
overflow: auto;
border: 1px solid var(--border);
}
table { border-collapse: collapse; width: 100%; font-size: 12px; min-width: 620px; }
th {
text-align: left;
background: var(--vscode-editorGroupHeader-tabsBackground, var(--sidebar));
border-bottom: 1px solid var(--border);
padding: 6px 8px;
font-weight: 600;
}
td {
border-bottom: 1px solid color-mix(in srgb, var(--border) 45%, transparent);
padding: 5px 8px;
vertical-align: top;
}
tbody tr:last-child td { border-bottom: 0; }
td.num { text-align: right; font-family: var(--mono); }
td.mono { font-family: var(--mono); }
.metric-strip {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 10px;
}
.metric {
border: 1px solid var(--border);
background: var(--input-bg);
padding: 4px 7px;
border-radius: 2px;
color: var(--muted);
font-size: 12px;
}
.metric strong { color: var(--fg); font-weight: 600; }
.tag-list { display: flex; flex-wrap: wrap; gap: 5px; }
.tag {
border: 1px solid var(--border);
background: var(--input-bg);
border-radius: 2px;
padding: 2px 6px;
font-family: var(--mono);
font-size: 12px;
}
canvas {
image-rendering: pixelated;
max-width: min(100%, 768px);
border: 1px solid var(--border);
background: var(--vscode-editor-background, #1e1e1e);
}
.swatch { display:inline-block; width:12px; height:12px; border:1px solid var(--border); vertical-align:-2px; margin-right:6px; }
${MAP_DATA_CSS}
${extraCss}`,
body: `<div class="content">${body}</div>`,
});
Expand Down
Loading
Loading