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.
|
||||
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 {
|
||||
switch (n.nodeType) {
|
||||
case n.DOCUMENT_NODE:
|
||||
@@ -46,7 +75,12 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
|
||||
const tagName = (n as HTMLElement).tagName.toLowerCase();
|
||||
let attributes: attributes = {};
|
||||
for (const { name, value } of Array.from((n as HTMLElement).attributes)) {
|
||||
attributes[name] = value;
|
||||
// relative path in attribute
|
||||
if (name === 'src' || name === 'href') {
|
||||
attributes[name] = absoluteToDoc(doc, value);
|
||||
} else {
|
||||
attributes[name] = value;
|
||||
}
|
||||
}
|
||||
// remote css
|
||||
if (tagName === 'link') {
|
||||
@@ -56,7 +90,7 @@ function serializeNode(n: Node, doc: Document): serializedNode | false {
|
||||
const cssText = getCssRulesString(stylesheet as CSSStyleSheet);
|
||||
if (cssText) {
|
||||
attributes = {
|
||||
_cssText: cssText,
|
||||
_cssText: absoluteToStylesheet(cssText, stylesheet!.href!),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ exports[`[html file]: iframe.html 1`] = `
|
||||
<title data-rrid=\\"12\\">iframe</title>
|
||||
</head>
|
||||
<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>"
|
||||
`;
|
||||
|
||||
@@ -110,6 +110,18 @@ exports[`[html file]: invalid-attribute.html 1`] = `
|
||||
</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`] = `
|
||||
"<!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\\" />
|
||||
@@ -117,7 +129,7 @@ exports[`[html file]: with-script.html 1`] = `
|
||||
<meta http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
||||
<title data-rrid=\\"12\\">with script</title>
|
||||
</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>"
|
||||
`;
|
||||
|
||||
@@ -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 http-equiv=\\"X-UA-Compatible\\" content=\\"ie=edge\\" data-rrid=\\"10\\" />
|
||||
<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\\">
|
||||
</body></html>"
|
||||
`;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
body {
|
||||
margin: 0;
|
||||
background: url('../a.jpg');
|
||||
}
|
||||
p {
|
||||
color: red;
|
||||
background: url('./b.jpg');
|
||||
}
|
||||
body > p {
|
||||
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