change relative path into absolute path
This commit is contained in:
@@ -2,8 +2,3 @@
|
|||||||
|
|
||||||
Snapshot the DOM into a stateful and serializable data structure.
|
Snapshot the DOM into a stateful and serializable data structure.
|
||||||
Also provide the ability to rebuild the DOM via snapshot.
|
Also provide the ability to rebuild the DOM via snapshot.
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
- [ ] Replace any url in css rules into absolute path.
|
|
||||||
- [ ] Select a suitable build strategy.
|
|
||||||
|
|||||||
@@ -28,6 +28,35 @@ function getCssRulesString(s: CSSStyleSheet): string | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const URL_IN_CSS_REF = /url\((['"])([^'"]*)\1\)/gm;
|
||||||
|
function absoluteToStylesheet(cssText: string, href: string): string {
|
||||||
|
return cssText.replace(URL_IN_CSS_REF, (_1, _2, filePath) => {
|
||||||
|
const stack = href.split('/');
|
||||||
|
const parts = filePath.split('/');
|
||||||
|
stack.pop();
|
||||||
|
for (const part of parts) {
|
||||||
|
if (part === '.') {
|
||||||
|
continue;
|
||||||
|
} else if (part === '..') {
|
||||||
|
stack.pop();
|
||||||
|
} else {
|
||||||
|
stack.push(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `url('${stack.join('/')}')`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const RELATIVE_PATH = /^(\.\.|\.|)\//;
|
||||||
|
function absoluteToDoc(doc: Document, attributeValue: string): string {
|
||||||
|
if (!RELATIVE_PATH.test(attributeValue)) {
|
||||||
|
return attributeValue;
|
||||||
|
}
|
||||||
|
const a: HTMLAnchorElement = document.createElement('a');
|
||||||
|
a.href = attributeValue;
|
||||||
|
return a.href;
|
||||||
|
}
|
||||||
|
|
||||||
function serializeNode(n: Node, doc: Document): serializedNode | false {
|
function serializeNode(n: Node, doc: Document): serializedNode | false {
|
||||||
switch (n.nodeType) {
|
switch (n.nodeType) {
|
||||||
case n.DOCUMENT_NODE:
|
case n.DOCUMENT_NODE:
|
||||||
@@ -46,8 +75,13 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
|
|||||||
const tagName = (n as HTMLElement).tagName.toLowerCase();
|
const tagName = (n as HTMLElement).tagName.toLowerCase();
|
||||||
let attributes: attributes = {};
|
let attributes: attributes = {};
|
||||||
for (const { name, value } of Array.from((n as HTMLElement).attributes)) {
|
for (const { name, value } of Array.from((n as HTMLElement).attributes)) {
|
||||||
|
// relative path in attribute
|
||||||
|
if (name === 'src' || name === 'href') {
|
||||||
|
attributes[name] = absoluteToDoc(doc, value);
|
||||||
|
} else {
|
||||||
attributes[name] = value;
|
attributes[name] = value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// remote css
|
// remote css
|
||||||
if (tagName === 'link') {
|
if (tagName === 'link') {
|
||||||
const stylesheet = Array.from(doc.styleSheets).find(s => {
|
const stylesheet = Array.from(doc.styleSheets).find(s => {
|
||||||
@@ -56,7 +90,7 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
|
|||||||
const cssText = getCssRulesString(stylesheet as CSSStyleSheet);
|
const cssText = getCssRulesString(stylesheet as CSSStyleSheet);
|
||||||
if (cssText) {
|
if (cssText) {
|
||||||
attributes = {
|
attributes = {
|
||||||
_cssText: cssText,
|
_cssText: absoluteToStylesheet(cssText, stylesheet!.href!),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ exports[`[html file]: iframe.html 1`] = `
|
|||||||
<title data-rrid=\\"12\\">iframe</title>
|
<title data-rrid=\\"12\\">iframe</title>
|
||||||
</head>
|
</head>
|
||||||
<body data-rrid=\\"16\\">
|
<body data-rrid=\\"16\\">
|
||||||
<iframe src=\\"/html/iframe-inner.html\\" width=\\"100\\" height=\\"50\\" data-rrid=\\"18\\"></iframe>
|
<iframe src=\\"http://localhost:3030/html/iframe-inner.html\\" width=\\"100\\" height=\\"50\\" data-rrid=\\"18\\"></iframe>
|
||||||
</body></html>"
|
</body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -110,6 +110,18 @@ exports[`[html file]: invalid-attribute.html 1`] = `
|
|||||||
</body></html>"
|
</body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`[html file]: with-relative-res.html 1`] = `
|
||||||
|
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\" data-rrid=\\"3\\"><head data-rrid=\\"4\\">
|
||||||
|
<meta charset=\\"UTF-8\\" data-rrid=\\"6\\" />
|
||||||
|
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\" data-rrid=\\"8\\" />
|
||||||
|
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
||||||
|
<title data-rrid=\\"12\\">Document</title>
|
||||||
|
</head>
|
||||||
|
<body data-rrid=\\"16\\">
|
||||||
|
<a href=\\"http://localhost:3030/basic.html\\" data-rrid=\\"18\\"></a>
|
||||||
|
<img src=\\"http://localhost:3030/a.jpg\\" alt=\\"\\" srcset=\\"\\" data-rrid=\\"20\\" /></body></html>"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`[html file]: with-script.html 1`] = `
|
exports[`[html file]: with-script.html 1`] = `
|
||||||
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\" data-rrid=\\"3\\"><head data-rrid=\\"4\\">
|
"<!DOCTYPE html><html xmlns=\\"http://www.w3.org/1999/xhtml\\" lang=\\"en\\" data-rrid=\\"3\\"><head data-rrid=\\"4\\">
|
||||||
<meta charset=\\"UTF-8\\" data-rrid=\\"6\\" />
|
<meta charset=\\"UTF-8\\" data-rrid=\\"6\\" />
|
||||||
@@ -117,7 +129,7 @@ exports[`[html file]: with-script.html 1`] = `
|
|||||||
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
||||||
<title data-rrid=\\"12\\">with script</title>
|
<title data-rrid=\\"12\\">with script</title>
|
||||||
</head><body data-rrid=\\"16\\">
|
</head><body data-rrid=\\"16\\">
|
||||||
<noscript src=\\"/js/a.js\\" data-rrid=\\"18\\"></noscript>
|
<noscript src=\\"http://localhost:3030/js/a.js\\" data-rrid=\\"18\\"></noscript>
|
||||||
<noscript data-rrid=\\"20\\"></noscript></body></html>"
|
<noscript data-rrid=\\"20\\"></noscript></body></html>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -127,7 +139,7 @@ exports[`[html file]: with-style-sheet.html 1`] = `
|
|||||||
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\" data-rrid=\\"8\\" />
|
<meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\" data-rrid=\\"8\\" />
|
||||||
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
||||||
<title data-rrid=\\"12\\">with style sheet</title>
|
<title data-rrid=\\"12\\">with style sheet</title>
|
||||||
<style data-rrid=\\"15\\">body { margin: 0px; }p { color: red; }body > p { color: yellow; }</style>
|
<style data-rrid=\\"15\\">body { margin: 0px; background: url('http://localhost:3030/a.jpg'); }p { color: red; background: url('http://localhost:3030/css/b.jpg'); }body > p { color: yellow; }</style>
|
||||||
</head><body data-rrid=\\"18\\">
|
</head><body data-rrid=\\"18\\">
|
||||||
</body></html>"
|
</body></html>"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
background: url('../a.jpg');
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
color: red;
|
color: red;
|
||||||
|
background: url('./b.jpg');
|
||||||
}
|
}
|
||||||
body > p {
|
body > p {
|
||||||
color: yellow;
|
color: yellow;
|
||||||
|
|||||||
13
test/html/with-relative-res.html
Normal file
13
test/html/with-relative-res.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="./basic.html"></a>
|
||||||
|
<img src="./a.jpg" alt="" srcset="">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user