Added xsd support
This commit is contained in:
51
CLAUDE.md
Normal file
51
CLAUDE.md
Normal file
@ -0,0 +1,51 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a simple XML requirements viewer application consisting of:
|
||||
- `xml_requirements_viewer.html` - A standalone HTML application for viewing XML requirements
|
||||
- `sample_requirements.xml` - A sample XML file containing formatted requirements
|
||||
|
||||
## Architecture
|
||||
|
||||
The project is a single-page HTML application with embedded CSS and JavaScript. No build process, dependencies, or server is required - it runs entirely in the browser.
|
||||
|
||||
### Core Components
|
||||
|
||||
- **HTML Structure**: Standard HTML5 with responsive design
|
||||
- **CSS Styling**: Embedded styles with dark mode support via `@media (prefers-color-scheme: dark)`
|
||||
- **JavaScript Functionality**:
|
||||
- Drag-and-drop file handling
|
||||
- XML parsing using DOMParser
|
||||
- Dynamic DOM manipulation for requirements display
|
||||
|
||||
### XML Structure
|
||||
|
||||
The viewer expects XML files with this structure:
|
||||
```xml
|
||||
<requirements>
|
||||
<requirement id="REQ-XXX">
|
||||
<title>Title</title>
|
||||
<priority>High/Medium/Low</priority>
|
||||
<category>Category</category>
|
||||
<text>HTML-formatted requirement text with custom tags</text>
|
||||
<status>Active/Draft</status>
|
||||
</requirement>
|
||||
</requirements>
|
||||
```
|
||||
|
||||
### Custom XML Tags Supported
|
||||
|
||||
The viewer supports various custom formatting tags within `<text>` elements:
|
||||
- Text formatting: `<strong>`, `<em>`, `<u>`, `<del>`, `<sup>`, `<sub>`, `<mark>`, `<small>`
|
||||
- Code elements: `<code>`, `<kbd>`, `<samp>`, `<var>`, `<pre>`
|
||||
- Semantic tags: `<critical>`, `<optional>`, `<deprecated>`, `<todo>`
|
||||
- Technical tags: `<value>`, `<unit>`, `<term>`, `<acronym>`, `<version>`
|
||||
- Structure: `<br>`, `<hr>`, `<ul>`, `<ol>`, `<li>`, `<blockquote>`
|
||||
- References: `<ref>`, `<url>`, `<link>`
|
||||
|
||||
## Usage
|
||||
|
||||
Open `xml_requirements_viewer.html` in a web browser and drag/drop or select XML files to view formatted requirements.
|
||||
321
software-rules-html-xml.xml
Normal file
321
software-rules-html-xml.xml
Normal file
@ -0,0 +1,321 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SoftwareRules xmlns="http://example.com/software-rules"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://example.com/software-rules software-rules.xsd"
|
||||
version="2.0"
|
||||
lastUpdated="2025-01-15">
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>SEC-001</ruleId>
|
||||
<ruleName><strong>Password Complexity Check</strong></ruleName>
|
||||
<category>Security</category>
|
||||
<priority>Critical</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
Ensures passwords meet <strong>minimum complexity requirements</strong>:
|
||||
<ul>
|
||||
<li>At least <mark>12 characters</mark> in length</li>
|
||||
<li>Contains <em>uppercase</em> and <em>lowercase</em> letters</li>
|
||||
<li>Includes <u>numbers</u> and special characters</li>
|
||||
<li>No <s>dictionary words</s> allowed</li>
|
||||
</ul>
|
||||
<blockquote>A strong password is your first line of defense.</blockquote>
|
||||
</description>
|
||||
<condition><code>password.length >= 13 AND hasUpperCase AND hasLowerCase AND hasNumber AND hasSpecialChar</code></condition>
|
||||
<action>VALIDATE_PASSWORD</action>
|
||||
<errorMessage><strong>Error:</strong> Password must be <mark>at least 12 characters</mark> and contain uppercase, lowercase, numbers, and special characters</errorMessage>
|
||||
<appliesTo>UserRegistration</appliesTo>
|
||||
<appliesTo>PasswordReset</appliesTo>
|
||||
<appliesTo>AccountCreation</appliesTo>
|
||||
<createdBy>admin</createdBy>
|
||||
<createdDate>2024-01-15</createdDate>
|
||||
<modifiedBy>security_team</modifiedBy>
|
||||
<modifiedDate>2024-06-20</modifiedDate>
|
||||
<tags>authentication</tags>
|
||||
<tags>security</tags>
|
||||
<tags>compliance</tags>
|
||||
<riskLevel>5</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>PERF-002</ruleId>
|
||||
<ruleName><em>Query Timeout Limit</em></ruleName>
|
||||
<category>Performance</category>
|
||||
<priority>High</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
<h3>Performance Protection Rule</h3>
|
||||
<p>This rule prevents database queries from running longer than <strong>30 seconds</strong>.</p>
|
||||
<p>Key settings:</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Max Execution Time</td>
|
||||
<td><code>30000ms</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Action</td>
|
||||
<td>Terminate Query</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr/>
|
||||
<small>Note: This limit can be overridden for batch operations.</small>
|
||||
</description>
|
||||
<condition><pre>if (query.executionTime > 30000) {
|
||||
return TERMINATE;
|
||||
}</pre></condition>
|
||||
<action>TERMINATE_QUERY</action>
|
||||
<errorMessage>Query execution exceeded maximum allowed time of <strong>30 seconds</strong></errorMessage>
|
||||
<appliesTo>DatabaseOperations</appliesTo>
|
||||
<appliesTo>ReportGeneration</appliesTo>
|
||||
<createdBy>dba_team</createdBy>
|
||||
<createdDate>2024-02-10</createdDate>
|
||||
<modifiedBy>performance_team</modifiedBy>
|
||||
<modifiedDate>2024-11-05</modifiedDate>
|
||||
<tags>database</tags>
|
||||
<tags>performance</tags>
|
||||
<riskLevel>3</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="false">
|
||||
<ruleId>VAL-003</ruleId>
|
||||
<ruleName>Email Format Validation</ruleName>
|
||||
<category>DataValidation</category>
|
||||
<priority>Medium</priority>
|
||||
<status>Testing</status>
|
||||
<description>
|
||||
Validates email addresses against <abbr title="Request for Comments">RFC</abbr> 5322 standard.
|
||||
<br/><br/>
|
||||
<strong>Valid format:</strong> <code>user@domain.com</code>
|
||||
<br/>
|
||||
<strong>Invalid formats:</strong>
|
||||
<ul>
|
||||
<li><del>user@</del></li>
|
||||
<li><del>@domain.com</del></li>
|
||||
<li><del>user domain.com</del></li>
|
||||
</ul>
|
||||
<details>
|
||||
<summary>Click for regex pattern</summary>
|
||||
<code>^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$</code>
|
||||
</details>
|
||||
</description>
|
||||
<condition>email.matches(RFC5322_REGEX)</condition>
|
||||
<action>VALIDATE_EMAIL</action>
|
||||
<errorMessage>Please enter a <u>valid email address</u></errorMessage>
|
||||
<appliesTo>UserProfile</appliesTo>
|
||||
<appliesTo>ContactForm</appliesTo>
|
||||
<createdBy>dev_team</createdBy>
|
||||
<createdDate>2024-03-22</createdDate>
|
||||
<tags>validation</tags>
|
||||
<tags>email</tags>
|
||||
<riskLevel>1</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>BUS-004</ruleId>
|
||||
<ruleName>Transaction Amount Limit</ruleName>
|
||||
<category>BusinessLogic</category>
|
||||
<priority>High</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
<h4>Transaction Limits by User Tier</h4>
|
||||
<ol>
|
||||
<li><strong>Basic Tier:</strong> Maximum $1,000 per transaction</li>
|
||||
<li><strong>Premium Tier:</strong> Maximum $10,000 per transaction</li>
|
||||
<li><strong>Enterprise Tier:</strong> Maximum $100,000 per transaction</li>
|
||||
</ol>
|
||||
<p>Transactions exceeding these limits will be <mark>automatically blocked</mark> and flagged for review.</p>
|
||||
<p>For limit increases, contact <a href="mailto:support@example.com">support@example.com</a></p>
|
||||
</description>
|
||||
<condition>transaction.amount > user.maxTransactionLimit</condition>
|
||||
<action>BLOCK_TRANSACTION</action>
|
||||
<errorMessage>Transaction amount of <strong>${amount}</strong> exceeds your account limit</errorMessage>
|
||||
<appliesTo>PaymentProcessing</appliesTo>
|
||||
<appliesTo>WireTransfers</appliesTo>
|
||||
<appliesTo>ACHTransfers</appliesTo>
|
||||
<createdBy>compliance_officer</createdBy>
|
||||
<createdDate>2024-01-05</createdDate>
|
||||
<modifiedBy>risk_management</modifiedBy>
|
||||
<modifiedDate>2024-09-15</modifiedDate>
|
||||
<tags>financial</tags>
|
||||
<tags>limits</tags>
|
||||
<tags>risk</tags>
|
||||
<riskLevel>4</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>COMP-005</ruleId>
|
||||
<ruleName><mark>GDPR Data Retention</mark></ruleName>
|
||||
<category>Compliance</category>
|
||||
<priority>Critical</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
<h3>⚠️ GDPR Compliance Rule</h3>
|
||||
<p>Personal data retention must comply with <strong>GDPR Article 5(1)(e)</strong>.</p>
|
||||
<blockquote>
|
||||
"Personal data shall be kept in a form which permits identification of data subjects for
|
||||
<u>no longer than is necessary</u> for the purposes for which the personal data are processed."
|
||||
</blockquote>
|
||||
<p><strong>Maximum retention periods:</strong></p>
|
||||
<dl>
|
||||
<dt>Customer Data</dt>
|
||||
<dd>2 years after account closure</dd>
|
||||
<dt>Employee Data</dt>
|
||||
<dd>7 years after employment ends</dd>
|
||||
<dt>Marketing Data</dt>
|
||||
<dd>1 year after last interaction</dd>
|
||||
</dl>
|
||||
<p><small>Reference: <cite>GDPR Regulation (EU) 2016/679</cite></small></p>
|
||||
</description>
|
||||
<condition>data.retentionPeriod > 730 AND data.type == 'PERSONAL'</condition>
|
||||
<action>FLAG_FOR_DELETION</action>
|
||||
<errorMessage><strong>⚠️ Warning:</strong> Personal data retention period exceeded <mark>GDPR requirements</mark></errorMessage>
|
||||
<appliesTo>DataManagement</appliesTo>
|
||||
<appliesTo>UserRecords</appliesTo>
|
||||
<createdBy>legal_team</createdBy>
|
||||
<createdDate>2024-05-25</createdDate>
|
||||
<tags>GDPR</tags>
|
||||
<tags>privacy</tags>
|
||||
<tags>compliance</tags>
|
||||
<riskLevel>5</riskLevel>
|
||||
<automationEnabled>false</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>ACC-006</ruleId>
|
||||
<ruleName>Multi-Factor Authentication Required</ruleName>
|
||||
<category>UserAccess</category>
|
||||
<priority>High</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
<p>MFA is <strong>mandatory</strong> for privileged accounts.</p>
|
||||
<p>Press <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>M</kbd> to open MFA settings.</p>
|
||||
<p>Supported methods:</p>
|
||||
<ul>
|
||||
<li>📱 SMS verification</li>
|
||||
<li>📧 Email OTP</li>
|
||||
<li>🔐 Authenticator app</li>
|
||||
<li>🔑 Hardware token</li>
|
||||
</ul>
|
||||
<p>Formula: <var>security_score</var> = <var>password_strength</var> × <var>mfa_enabled</var><sup>2</sup></p>
|
||||
</description>
|
||||
<condition>user.role IN ('admin', 'finance', 'hr') AND !session.hasMFA</condition>
|
||||
<action>REQUIRE_MFA</action>
|
||||
<errorMessage><strong>🔒 Security Alert:</strong> Multi-factor authentication is <u>required</u> for this operation</errorMessage>
|
||||
<appliesTo>AdminPanel</appliesTo>
|
||||
<appliesTo>FinancialReports</appliesTo>
|
||||
<appliesTo>EmployeeData</appliesTo>
|
||||
<createdBy>security_team</createdBy>
|
||||
<createdDate>2024-04-10</createdDate>
|
||||
<modifiedBy>ciso</modifiedBy>
|
||||
<modifiedDate>2024-12-01</modifiedDate>
|
||||
<tags>security</tags>
|
||||
<tags>authentication</tags>
|
||||
<tags>MFA</tags>
|
||||
<riskLevel>4</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="true">
|
||||
<ruleId>SEC-007</ruleId>
|
||||
<ruleName><strong style="color: red;">SQL Injection Prevention</strong></ruleName>
|
||||
<category>Security</category>
|
||||
<priority>Critical</priority>
|
||||
<status>Active</status>
|
||||
<description>
|
||||
<h2>🛡️ Critical Security Rule</h2>
|
||||
<p>This rule detects and blocks potential SQL injection attempts.</p>
|
||||
<p><strong>Common injection patterns blocked:</strong></p>
|
||||
<pre>
|
||||
SELECT * FROM users WHERE id = '1' OR '1'='1'
|
||||
DROP TABLE users; --
|
||||
UNION SELECT * FROM passwords
|
||||
</pre>
|
||||
<p>Protection includes:</p>
|
||||
<ol>
|
||||
<li><strong>Input validation</strong> - All inputs sanitized</li>
|
||||
<li><strong>Parameterized queries</strong> - No direct concatenation</li>
|
||||
<li><strong>Escape sequences</strong> - Special characters handled</li>
|
||||
</ol>
|
||||
<figure>
|
||||
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Crect width='100' height='100' fill='%23ff0000'/%3E%3Ctext x='50' y='50' text-anchor='middle' fill='white' font-size='40'%3E⚠️%3C/text%3E%3C/svg%3E" alt="Warning"/>
|
||||
<figcaption>High Risk Alert</figcaption>
|
||||
</figure>
|
||||
<p><ins>Updated: Now includes NoSQL injection prevention</ins></p>
|
||||
</description>
|
||||
<condition><samp>if (detectSQLInjection(input)) { return BLOCK; }</samp></condition>
|
||||
<action>BLOCK_REQUEST</action>
|
||||
<errorMessage><span style="color: red; font-weight: bold;">⛔ SECURITY VIOLATION:</span> Potentially malicious input detected and blocked</errorMessage>
|
||||
<appliesTo>APIEndpoints</appliesTo>
|
||||
<appliesTo>SearchFunctions</appliesTo>
|
||||
<createdBy>security_team</createdBy>
|
||||
<createdDate>2024-01-20</createdDate>
|
||||
<tags>security</tags>
|
||||
<tags>injection</tags>
|
||||
<tags>SQL</tags>
|
||||
<riskLevel>5</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
<Rule enabled="false">
|
||||
<ruleId>PERF-008</ruleId>
|
||||
<ruleName>API Rate Limiting</ruleName>
|
||||
<category>Performance</category>
|
||||
<priority>Medium</priority>
|
||||
<status>Deprecated</status>
|
||||
<description>
|
||||
<p><s>This rule has been deprecated</s> in favor of the new adaptive rate limiting system.</p>
|
||||
<p>Previous limits were:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tier</th>
|
||||
<th>Requests/Hour</th>
|
||||
<th>Burst Limit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Free</td>
|
||||
<td>100</td>
|
||||
<td>10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pro</td>
|
||||
<td>1,000</td>
|
||||
<td>50</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Enterprise</td>
|
||||
<td>10,000</td>
|
||||
<td>500</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<address>
|
||||
For questions, contact:<br/>
|
||||
API Team<br/>
|
||||
api-support@example.com
|
||||
</address>
|
||||
<time datetime="2024-12-31">Deprecated on December 31, 2024</time>
|
||||
</description>
|
||||
<condition>user.apiCalls > 1000 AND timeWindow == '1hour'</condition>
|
||||
<action>THROTTLE_REQUESTS</action>
|
||||
<errorMessage>API rate limit exceeded. Please try again later</errorMessage>
|
||||
<appliesTo>PublicAPI</appliesTo>
|
||||
<createdBy>api_team</createdBy>
|
||||
<createdDate>2024-02-28</createdDate>
|
||||
<tags>API</tags>
|
||||
<tags>rate-limiting</tags>
|
||||
<riskLevel>2</riskLevel>
|
||||
<automationEnabled>true</automationEnabled>
|
||||
</Rule>
|
||||
|
||||
</SoftwareRules>
|
||||
74
software-rules.xsd.txt
Normal file
74
software-rules.xsd.txt
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://example.com/software-rules"
|
||||
xmlns:tns="http://example.com/software-rules"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<!-- Root element -->
|
||||
<xs:element name="SoftwareRules">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Rule" type="tns:RuleType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="version" type="xs:string" use="required"/>
|
||||
<xs:attribute name="lastUpdated" type="xs:date" use="optional"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- Complex type for Rule -->
|
||||
<xs:complexType name="RuleType">
|
||||
<xs:sequence>
|
||||
<xs:element name="ruleId" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="ruleName" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="category" type="tns:CategoryType" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="priority" type="tns:PriorityType" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="status" type="tns:StatusType" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="condition" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="action" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="errorMessage" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="appliesTo" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="createdBy" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="createdDate" type="xs:date" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="modifiedBy" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="modifiedDate" type="xs:date" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="tags" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="riskLevel" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="automationEnabled" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="enabled" type="xs:boolean" default="true"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Enumeration for Category -->
|
||||
<xs:simpleType name="CategoryType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Security"/>
|
||||
<xs:enumeration value="Performance"/>
|
||||
<xs:enumeration value="DataValidation"/>
|
||||
<xs:enumeration value="BusinessLogic"/>
|
||||
<xs:enumeration value="Compliance"/>
|
||||
<xs:enumeration value="UserAccess"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Enumeration for Priority -->
|
||||
<xs:simpleType name="PriorityType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Critical"/>
|
||||
<xs:enumeration value="High"/>
|
||||
<xs:enumeration value="Medium"/>
|
||||
<xs:enumeration value="Low"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Enumeration for Status -->
|
||||
<xs:simpleType name="StatusType">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Active"/>
|
||||
<xs:enumeration value="Inactive"/>
|
||||
<xs:enumeration value="Testing"/>
|
||||
<xs:enumeration value="Deprecated"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
</xs:schema>
|
||||
@ -128,7 +128,13 @@
|
||||
.field-row {
|
||||
display: flex;
|
||||
margin: 8px 0;
|
||||
padding: 8px 0;
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px dotted #e0e0e0;
|
||||
}
|
||||
|
||||
.field-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
@ -145,6 +151,20 @@
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Style for multi-value fields */
|
||||
.field-value-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.field-value-item {
|
||||
padding: 4px 8px;
|
||||
background: #f5f5f5;
|
||||
border-left: 2px solid #007bff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.element-pair {
|
||||
position: relative;
|
||||
}
|
||||
@ -412,6 +432,10 @@
|
||||
background: linear-gradient(90deg, transparent, #4fc3f7, transparent);
|
||||
}
|
||||
|
||||
.field-row {
|
||||
border-bottom-color: #444;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
color: #64b5f6;
|
||||
}
|
||||
@ -420,6 +444,11 @@
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.field-value-item {
|
||||
background: #3d3d3d;
|
||||
border-left-color: #4fc3f7;
|
||||
}
|
||||
|
||||
.element-index {
|
||||
background: #4fc3f7;
|
||||
}
|
||||
@ -1012,12 +1041,16 @@
|
||||
const siblings = Array.from(element.children).filter(c => c.tagName === fieldName);
|
||||
|
||||
if (siblings.length > 1) {
|
||||
// For multi-value fields, combine them
|
||||
// For multi-value fields, create a list
|
||||
const values = siblings.map(s => formatElementContent(s)).filter(v => v && v !== '<em>(empty)</em>');
|
||||
if (values.length > 0) {
|
||||
// Create a formatted list of values
|
||||
const listHtml = '<div class="field-value-list">' +
|
||||
values.map(v => `<div class="field-value-item">${v}</div>`).join('') +
|
||||
'</div>';
|
||||
fields.push({
|
||||
name: fieldName,
|
||||
value: values.join(', ')
|
||||
value: listHtml
|
||||
});
|
||||
}
|
||||
processedTags.add(fieldName);
|
||||
@ -1155,124 +1188,12 @@
|
||||
}
|
||||
|
||||
function formatElementContent(element) {
|
||||
let html = '';
|
||||
// Simply get the inner HTML of the element, which preserves all HTML formatting
|
||||
const innerHTML = element.innerHTML;
|
||||
|
||||
element.childNodes.forEach(node => {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
html += node.textContent;
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
// Format known tags
|
||||
const tagName = node.tagName.toLowerCase();
|
||||
const content = formatElementContent(node);
|
||||
|
||||
// Apply appropriate formatting based on tag
|
||||
switch(tagName) {
|
||||
case 'strong':
|
||||
case 'b':
|
||||
html += `<strong>${content}</strong>`;
|
||||
break;
|
||||
case 'em':
|
||||
case 'i':
|
||||
html += `<em>${content}</em>`;
|
||||
break;
|
||||
case 'u':
|
||||
html += `<u>${content}</u>`;
|
||||
break;
|
||||
case 'del':
|
||||
case 'strike':
|
||||
html += `<del>${content}</del>`;
|
||||
break;
|
||||
case 'sup':
|
||||
html += `<sup>${content}</sup>`;
|
||||
break;
|
||||
case 'sub':
|
||||
html += `<sub>${content}</sub>`;
|
||||
break;
|
||||
case 'mark':
|
||||
case 'highlight':
|
||||
html += `<mark>${content}</mark>`;
|
||||
break;
|
||||
case 'small':
|
||||
html += `<small>${content}</small>`;
|
||||
break;
|
||||
case 'code':
|
||||
html += `<code>${content}</code>`;
|
||||
break;
|
||||
case 'kbd':
|
||||
html += `<kbd>${content}</kbd>`;
|
||||
break;
|
||||
case 'samp':
|
||||
html += `<samp>${content}</samp>`;
|
||||
break;
|
||||
case 'var':
|
||||
html += `<var>${content}</var>`;
|
||||
break;
|
||||
case 'pre':
|
||||
html += `<pre>${content}</pre>`;
|
||||
break;
|
||||
case 'critical':
|
||||
html += `<span class="critical">${content}</span>`;
|
||||
break;
|
||||
case 'optional':
|
||||
html += `<span class="optional">${content}</span>`;
|
||||
break;
|
||||
case 'deprecated':
|
||||
html += `<span class="deprecated">${content}</span>`;
|
||||
break;
|
||||
case 'todo':
|
||||
html += `<span class="todo">${content}</span>`;
|
||||
break;
|
||||
case 'value':
|
||||
html += `<span class="value">${content}</span>`;
|
||||
break;
|
||||
case 'unit':
|
||||
html += `<span class="unit">${content}</span>`;
|
||||
break;
|
||||
case 'term':
|
||||
html += `<span class="term">${content}</span>`;
|
||||
break;
|
||||
case 'acronym':
|
||||
html += `<span class="acronym">${content}</span>`;
|
||||
break;
|
||||
case 'version':
|
||||
html += `<span class="version">${content}</span>`;
|
||||
break;
|
||||
case 'br':
|
||||
html += '<br>';
|
||||
break;
|
||||
case 'hr':
|
||||
html += '<hr>';
|
||||
break;
|
||||
case 'ul':
|
||||
html += `<ul>${content}</ul>`;
|
||||
break;
|
||||
case 'ol':
|
||||
html += `<ol>${content}</ol>`;
|
||||
break;
|
||||
case 'li':
|
||||
html += `<li>${content}</li>`;
|
||||
break;
|
||||
case 'blockquote':
|
||||
html += `<blockquote>${content}</blockquote>`;
|
||||
break;
|
||||
case 'ref':
|
||||
html += `<span class="ref">${content}</span>`;
|
||||
break;
|
||||
case 'url':
|
||||
html += `<span class="url">${content}</span>`;
|
||||
break;
|
||||
case 'link':
|
||||
const href = node.getAttribute('href') || '#';
|
||||
html += `<a href="${href}" class="url">${content}</a>`;
|
||||
break;
|
||||
default:
|
||||
// For unknown tags, just include the content
|
||||
html += content;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return html || '<em>(empty)</em>';
|
||||
// If there's content, return it as-is (browser will handle HTML tags)
|
||||
// If empty, return the (empty) indicator
|
||||
return innerHTML ? innerHTML.trim() : '<em>(empty)</em>';
|
||||
}
|
||||
|
||||
function formatXMLElement(element) {
|
||||
|
||||
Reference in New Issue
Block a user