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: 1 addition & 1 deletion packages/web-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "carbon-devtools-v10",
"version": "2.8.4",
"version": "2.8.6",
"private": true,
"description": "A basic set of tools for teams building live Carbon pages for Carbon v10.",
"main": "dist/manifest.json",
Expand Down
10 changes: 7 additions & 3 deletions packages/web-extension/src/inject/components/Highlight/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ function addHighlight(component, options = {}) {
comp.width >= contentMax &&
comp.height >= contentMax
) {
highlight.innerHTML = `<span>${options.content}</span>`;
setContenSize(highlight, highlight.querySelector('span'));
// Create span element safely
const span = document.createElement('span');
span.textContent = options.content;
highlight.textContent = '';
highlight.appendChild(span);
setContenSize(highlight, span);
}
}
}
Expand Down Expand Up @@ -113,7 +117,7 @@ function removeHighlight(component) {
component.setAttribute('class', '');
component.setAttribute('style', '');
component.setAttribute('data-highlightid', '');
component.innerHTML = '';
component.textContent = '';
}

function removeAllHighlights() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ const selectors = Object.keys(allComponents).join(',');

const specsDependenciesClass = `${prefix}--specs-dependencies-tooltip`;

function escapeHTML(value) {
return String(value).replace(/[&<>"']/g, (char) => {
const escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
};
return escapeMap[char];
});
}

function highlightSpecsDependencies(target) {
let componentName;
let componentIdentified = false;
Expand All @@ -32,7 +45,7 @@ function highlightSpecsDependencies(target) {
componentName = siblings.pop(); // pull off the last item for point name
dependencies = findAllDomShadow(selectors, target); // get dependencies

tooltipContent += `<h2 class="${specsDependenciesClass}__title">${componentName}</h2>`;
tooltipContent += `<h2 class="${specsDependenciesClass}__title">${escapeHTML(componentName)}</h2>`;

// manage siblings
if (siblings.length) {
Expand Down Expand Up @@ -84,7 +97,7 @@ function highlightSpecsDependencies(target) {

if (dependencyName && unique.indexOf(dependencyName) < 0) {
unique.push(dependencyName);
tooltipContent += `<li class="${specsDependenciesClass}__list-item">${dependencyName}</li>`;
tooltipContent += `<li class="${specsDependenciesClass}__list-item">${escapeHTML(dependencyName)}</li>`;
}
}

Expand All @@ -97,7 +110,7 @@ function highlightSpecsDependencies(target) {
if (unique.length > 0) {
tooltipContent = tooltipContent.replace(
/<!--dependencycount-->/g,
`<span>${unique.length}</span> `
`<span>${escapeHTML(unique.length)}</span> `
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import {

const { prefix } = settings;

function escapeHTML(value) {
return String(value).replace(/[&<>"']/g, (char) => {
const escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
};
return escapeMap[char];
});
}

const aspectRatiosCalc = aspectRatios.map((ratio) => {
const vals = ratio.split(':');
return vals[0] / vals[1];
Expand Down Expand Up @@ -42,7 +55,7 @@ function highlightSpecsRatio(target) {
tooltipContent += `<span class="${prefix}--tooltip--primary">${width}x${height}</span>`;
}

tooltipContent += `<span class="${prefix}--tooltip--secondary">${componentName}</span>`;
tooltipContent += `<span class="${prefix}--tooltip--secondary">${escapeHTML(componentName)}</span>`;

addHighlight(target, { ...highlightOptions, type: 'specs' });
updateTooltipContent(tooltipContent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,16 @@ function positionSpacer(
spacer.dataset.component = componentName;

if (value >= 16) {
spacer.innerHTML = `<span class="value">${value}</span>`;
// Create span element safely
const span = document.createElement('span');
span.className = 'value';
span.textContent = value;
spacer.textContent = '';
spacer.appendChild(span);

if (value < spacer.querySelector('.value').offsetWidth) {
// if the text doesn't fit in the box then let's remove the text
spacer.innerHTML = '';
spacer.textContent = '';
}
}

Expand Down Expand Up @@ -300,7 +305,7 @@ function resetAllSpacers() {
}

function resetSpacer(spacer) {
spacer.innerHTML = ``;
spacer.textContent = '';
spacer.style.width = null;
spacer.style.height = null;
spacer.style.minHeight = null;
Expand Down
42 changes: 32 additions & 10 deletions packages/web-extension/src/inject/components/Tooltip/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,31 @@ function initTooltip() {
const tooltipHTML = document.createElement('div');
tooltipHTML.classList.add(tooltipClass);
tooltipHTML.setAttribute('data-floating-menu-direction', 'top');
tooltipHTML.innerHTML = `
<span class="${tooltipClass}__caret"></span>
<div class="${tooltipClass}__content" tabindex="-1" role="dialog"></div>
`;

// Create caret span
const caret = document.createElement('span');
caret.classList.add(`${tooltipClass}__caret`);

// Create content div
const content = document.createElement('div');
content.classList.add(`${tooltipClass}__content`);
content.setAttribute('tabindex', '-1');
content.setAttribute('role', 'dialog');

tooltipHTML.appendChild(caret);
tooltipHTML.appendChild(content);
devtoolsContainer.appendChild(tooltipHTML);
}
}

function updateTooltipContent(content) {
const tooltipContent = body.querySelector('.' + tooltipContentClass);

tooltipContent.innerHTML = content;
// Use template element for HTML parsing; callers must escape untrusted dynamic text.
const template = document.createElement('template');
template.innerHTML = String(content);
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
tooltipContent.textContent = '';
tooltipContent.appendChild(template.content);
}

function positionTooltip(component) {
Expand Down Expand Up @@ -150,24 +163,33 @@ function showHideTooltip(show) {
}
}

function escapeHTML(value) {
return String(value)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}

function __specValueItem(type, value) {
let html;

if (type === 'warning') {
html = `
<li class="${prefix}--tooltip-specs__warning">
${value}
${escapeHTML(value)}
</li>
`;
} else {
html = `<li>`;

if (type) {
html += `<h3 class="${prefix}--tooltip-specs__prop">${type}</h3>`;
html += `<h3 class="${prefix}--tooltip-specs__prop">${escapeHTML(type)}</h3>`;
}

if (value) {
html += `<p class="${prefix}--tooltip-specs__value">${value}</p>`;
html += `<p class="${prefix}--tooltip-specs__value">${escapeHTML(value)}</p>`;
}

html += `</li>`;
Expand All @@ -190,11 +212,11 @@ function __specsContainer(groups) {
groupsContent += `<div class="${prefix}--tooltip-specs__group ${groupLayoutClass}">`;

if (eyebrow) {
groupsContent += `<h1 class="${prefix}--tooltip-specs__eyebrow">${eyebrow}</h1>`;
groupsContent += `<h1 class="${prefix}--tooltip-specs__eyebrow">${escapeHTML(eyebrow)}</h1>`;
}

if (title) {
groupsContent += `<h2 class="${prefix}--tooltip-specs__title">${title}</h2>`;
groupsContent += `<h2 class="${prefix}--tooltip-specs__title">${escapeHTML(title)}</h2>`;
}

if (content) {
Expand Down
5 changes: 4 additions & 1 deletion packages/web-extension/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
"browser_specific_settings": {
"gecko": {
"strict_min_version": "121.0",
"id": "{a12521e6-1ba2-4d48-9ec2-9286a37d82d1}"
"id": "{a12521e6-1ba2-4d48-9ec2-9286a37d82d1}",
"data_collection_permissions": {
"required": false
}
}
},
"web_accessible_resources": [
Expand Down
7 changes: 6 additions & 1 deletion packages/web-extension/src/options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,10 @@ function Options() {
}

const body = document.querySelector('body');
body.innerHTML = '<div id="app"></div>' + body.innerHTML;

// Create app div safely without innerHTML
const appDiv = document.createElement('div');
appDiv.id = 'app';
body.insertBefore(appDiv, body.firstChild);

ReactDOM.render(<Options />, document.getElementById('app'));
22 changes: 16 additions & 6 deletions packages/web-extension/src/popup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,17 @@ function Popup() {
<article
className={`${prefix}--popup ${experimentalFlag(
() => `${prefix}--popup--experimental`
)}`}>
)}`}
>
<header className={`${prefix}--popup__header`}>
<div className={`${prefix}--col-sm-3`}>
<h1 className={`${prefix}--popup__heading`}>
Carbon Devtools
{experimentalFlag(() => (
<Tag
type="magenta"
className={`${prefix}--popup__experimental-tag`}>
className={`${prefix}--popup__experimental-tag`}
>
Exp
</Tag>
))}
Expand All @@ -114,7 +116,8 @@ function Popup() {
<section
className={`${prefix}--popup__panel-container ${activePanel(
panelState
)}`}>
)}`}
>
<main className={`${prefix}--grid ${prefix}--popup__panel`}>
<Content
initialMsg={initialMsg}
Expand All @@ -126,14 +129,16 @@ function Popup() {
<Button
className={`${prefix}--popup__panel-close`}
kind="ghost"
onClick={() => panelControls.close(panelState.name)}>
onClick={() => panelControls.close(panelState.name)}
>
<ChevronLeft height="16" />
Back
</Button>
<div className={`${prefix}--grid`}>
<div className={`${prefix}--row`}>
<h1
className={`${prefix}--popup__panel-title ${prefix}--col-sm-3`}>
className={`${prefix}--popup__panel-title ${prefix}--col-sm-3`}
>
{panelState.name}
</h1>
</div>
Expand All @@ -156,5 +161,10 @@ function activePanel(stateName) {
}

const body = document.querySelector('body');
body.innerHTML = '<div id="app"></div>' + body.innerHTML;

// Create app div safely without innerHTML
const appDiv = document.createElement('div');
appDiv.id = 'app';
body.insertBefore(appDiv, body.firstChild);

ReactDOM.render(<Popup />, document.getElementById('app'));