Skip to content

Commit 2059b32

Browse files
committed
Removed code duplication between 2 files. #2805
1 parent 85058b4 commit 2059b32

File tree

4 files changed

+110
-26
lines changed

4 files changed

+110
-26
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// resolveUtils.unit.test.jsx
2+
3+
import resolvePathsForElementsWithAttribute from '../../../../../shared_file/resolveUtils';
4+
import { resolvePathToFile } from '../../../../../server/utils/filePath';
5+
6+
// Mock the dependencies
7+
jest.mock('../../../../../server/utils/filePath', () => ({
8+
resolvePathToFile: jest.fn()
9+
}));
10+
11+
jest.mock('../../../../../server/utils/fileUtils', () => ({
12+
MEDIA_FILE_REGEX: /\.(png|jpg|jpeg|gif|svg)$/i
13+
}));
14+
15+
describe('resolvePathsForElementsWithAttribute', () => {
16+
let mockSketchDoc;
17+
let mockFiles;
18+
19+
beforeEach(() => {
20+
jest.clearAllMocks();
21+
22+
// Create a mock DOM environment
23+
mockSketchDoc = document.implementation.createHTMLDocument();
24+
mockFiles = {
25+
'image.png': { url: 'https://example.com/image.png' },
26+
'missing.jpg': { url: null }
27+
};
28+
29+
resolvePathToFile.mockImplementation((fileName, files) => files[fileName]);
30+
});
31+
32+
it('should update the attribute when the file is resolved successfully', () => {
33+
const element = mockSketchDoc.createElement('img');
34+
element.setAttribute('src', 'image.png');
35+
mockSketchDoc.body.appendChild(element);
36+
37+
resolvePathsForElementsWithAttribute('src', mockSketchDoc, mockFiles);
38+
39+
expect(element.getAttribute('src')).toBe('https://example.com/image.png');
40+
});
41+
42+
it('should not update the attribute when the file resolution fails', () => {
43+
const element = mockSketchDoc.createElement('img');
44+
element.setAttribute('src', 'missing.jpg');
45+
mockSketchDoc.body.appendChild(element);
46+
47+
resolvePathsForElementsWithAttribute('src', mockSketchDoc, mockFiles);
48+
49+
expect(element.getAttribute('src')).toBe('missing.jpg');
50+
});
51+
52+
it('should not update the attribute when the value does not match MEDIA_FILE_REGEX', () => {
53+
const element = mockSketchDoc.createElement('img');
54+
element.setAttribute('src', 'document.pdf');
55+
mockSketchDoc.body.appendChild(element);
56+
57+
resolvePathsForElementsWithAttribute('src', mockSketchDoc, mockFiles);
58+
59+
expect(element.getAttribute('src')).toBe('document.pdf');
60+
});
61+
62+
it('should do nothing when no elements with the specified attribute are found', () => {
63+
resolvePathsForElementsWithAttribute('src', mockSketchDoc, mockFiles);
64+
65+
expect(mockSketchDoc.querySelectorAll('[src]').length).toBe(0);
66+
});
67+
});

client/modules/Preview/EmbedFrame.jsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import decomment from 'decomment';
88
import { resolvePathToFile } from '../../../server/utils/filePath';
99
import getConfig from '../../utils/getConfig';
1010
import {
11-
MEDIA_FILE_REGEX,
1211
MEDIA_FILE_QUOTED_REGEX,
1312
STRING_REGEX,
1413
PLAINTEXT_FILE_REGEX,
@@ -18,6 +17,7 @@ import {
1817
import { getAllScriptOffsets } from '../../utils/consoleUtils';
1918
import { registerFrame } from '../../utils/dispatcher';
2019
import { createBlobUrl } from './filesReducer';
20+
import resolvePathsForElementsWithAttribute from '../../../shared_file/resolveUtils';
2121

2222
let objectUrls = {};
2323
let objectPaths = {};
@@ -34,19 +34,6 @@ const Frame = styled.iframe`
3434
`}
3535
`;
3636

37-
function resolvePathsForElementsWithAttribute(attr, sketchDoc, files) {
38-
const elements = sketchDoc.querySelectorAll(`[${attr}]`);
39-
const elementsArray = Array.prototype.slice.call(elements);
40-
elementsArray.forEach((element) => {
41-
if (element.getAttribute(attr).match(MEDIA_FILE_REGEX)) {
42-
const resolvedFile = resolvePathToFile(element.getAttribute(attr), files);
43-
if (resolvedFile && resolvedFile.url) {
44-
element.setAttribute(attr, resolvedFile.url);
45-
}
46-
}
47-
});
48-
}
49-
5037
function resolveCSSLinksInString(content, files) {
5138
let newContent = content;
5239
let cssFileStrings = content.match(STRING_REGEX);
@@ -218,7 +205,12 @@ function injectLocalFiles(files, htmlFile, options) {
218205
base.href = `${window.origin}${basePath}${basePath.length > 1 && '/'}`;
219206
sketchDoc.head.appendChild(base);
220207

208+
// Resolve paths for elements with the 'src' attribute
209+
// This updates the 'src' attribute of elements (e.g., <img>, <script>) to their resolved URLs
221210
resolvePathsForElementsWithAttribute('src', sketchDoc, resolvedFiles);
211+
212+
// Resolve paths for elements with the 'href' attribute
213+
// This updates the 'href' attribute of elements (e.g., <a>, <link>) to their resolved URLs
222214
resolvePathsForElementsWithAttribute('href', sketchDoc, resolvedFiles);
223215
// should also include background, data, poster, but these are used way less often
224216

server/utils/previewGeneration.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { resolvePathToFile } from '../utils/filePath';
2+
import { resolvePathsForElementsWithAttribute } from '../../shared_file/resolveUtils';
23

34
import {
4-
MEDIA_FILE_REGEX,
55
STRING_REGEX,
66
PLAINTEXT_FILE_REGEX,
77
EXTERNAL_LINK_REGEX,
@@ -44,17 +44,9 @@ export function injectMediaUrls(filesToInject, allFiles, projectId) {
4444
});
4545
}
4646

47-
export function resolvePathsForElementsWithAttribute(attr, sketchDoc, files) {
48-
const elements = sketchDoc.querySelectorAll(`[${attr}]`);
49-
const elementsArray = Array.prototype.slice.call(elements);
50-
elementsArray.forEach((element) => {
51-
if (element.getAttribute(attr).match(MEDIA_FILE_REGEX)) {
52-
const resolvedFile = resolvePathToFile(element.getAttribute(attr), files);
53-
if (resolvedFile && resolvedFile.url) {
54-
element.setAttribute(attr, resolvedFile.url);
55-
}
56-
}
57-
});
47+
// Wrapped the function in a proper call
48+
export function resolveMediaElements(sketchDoc, files) {
49+
resolvePathsForElementsWithAttribute('src', sketchDoc, files);
5850
}
5951

6052
export function resolveScripts(sketchDoc, files, projectId) {

shared_file/resolveUtils.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Import necessary utilities for resolving file paths and checking media file patterns
2+
import { resolvePathToFile } from '../server/utils/filePath'; // Utility to resolve file paths
3+
import { MEDIA_FILE_REGEX } from '../server/utils/fileUtils'; // Regex pattern to identify media files
4+
5+
// Shared function to resolve paths for elements with a specific attribute
6+
export default function resolvePathsForElementsWithAttribute(
7+
attr,
8+
sketchDoc,
9+
files
10+
) {
11+
// Find all elements in the document that have the specified attribute
12+
const elements = sketchDoc.querySelectorAll(`[${attr}]`);
13+
14+
// Convert the NodeList to an array for easier iteration
15+
const elementsArray = Array.prototype.slice.call(elements);
16+
17+
// Iterate over each element with the specified attribute
18+
elementsArray.forEach((element) => {
19+
// Get the value of the attribute
20+
const attrValue = element.getAttribute(attr);
21+
22+
// Use RegExp.test() instead of match() !== null
23+
if (MEDIA_FILE_REGEX.test(attrValue)) {
24+
// Resolve the file path using the provided files mapping
25+
const resolvedFile = resolvePathToFile(attrValue, files);
26+
27+
// If the file is resolved successfully and has a URL, update the attribute
28+
if (resolvedFile && resolvedFile.url) {
29+
element.setAttribute(attr, resolvedFile.url);
30+
}
31+
}
32+
});
33+
}

0 commit comments

Comments
 (0)