SVG previews
No localization selected
Difference
Rendering difference…
After
Observed contributionConservative candidate
$|
$|// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
fn escape_html(value : String) -> String {
value
.replace_all(old="&", new="&")
.replace_all(old="<", new="<")
.replace_all(old=">", new=">")
.replace_all(old="\"", new=""")
.replace_all(old="'", new="'")
}
///|
fn preview_element_insert_offset(
source : String,
span : @xml.SourceSpan,
) -> Int {
let mut offset = span.end.offset - 1
while offset > span.start.offset && source[offset] != '>' {
offset -= 1
}
if offset > span.start.offset && source[offset - 1] == '/' {
offset - 1
} else {
offset
}
}
///|
fn preview_source(source : String, width : Int, height : Int) -> String {
let reader = @xml.NamespaceReader::from_string(source)
let events = reader.read_events_until_eof() catch { _ => return source }
for event in events {
match event.kind {
Start(element) | Empty(element) => {
if element.name.local_name != "svg" {
return source
}
for attribute in element.attributes {
if attribute.name.local_name == "viewBox" &&
attribute.name.namespace_uri is None {
return source
}
}
// CSS sizing alone does not scale the user space of a root SVG without
// viewBox. Adapt only the sandbox copy to the Comparison Viewport.
let offset = preview_element_insert_offset(source, event.span)
return "\{source.view(end_offset=offset)} viewBox=\"0 0 \{width} \{height}\"\{source.view(start_offset=offset)}"
}
_ => ()
}
}
source
}
///|
fn sandbox_document(source : String, width : Int, height : Int) -> String {
escape_html(
"\{preview_source(source, width, height)}",
)
}
///|
/// Render a self-contained interactive HTML presentation of a report.
///
/// The original SVG sources are embedded as sandboxed preview documents. The
/// supplied Structured Report remains the sole source of classification,
/// ordering, magnitude, localization, and Diagnostics; this function does not
/// run comparison again. Review marks and navigation are session-only UI state.
pub fn render_html_report(
before_svg : String,
after_svg : String,
report : StructuredReport,
) -> String {
let width = report.profile.viewport_width
let height = report.profile.viewport_height
let report_json = escape_html(report.to_json_string())
let before_document = sandbox_document(before_svg, width, height)
let after_document = sandbox_document(after_svg, width, height)
let styles = html_report_styles()
let script = html_report_script()
let html =
$|
$|
$|
$|
$|SVG Diff Report
$|
$|SVG previews
No localization selected
$|Before
$|Difference
Rendering difference…
$|After
$|Observed contributionConservative candidate
$|
$|
html
}