Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/compatible anglur12 #368

Merged
merged 7 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from 5 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
55 changes: 38 additions & 17 deletions src/util/handleAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import type { Fetch } from './globalConfiguration';
import type { ScriptAttributes } from '../apps';

const COMMENT_REGEX = /<!--.*?-->/g;
const BASE_LOOSE_REGEX = /<base\s[^>]*href=['"]?([^'"]*)['"]?[^>]*>/;

const EMPTY_STRING = '';
const STYLESHEET_LINK_TYPE = 'stylesheet';

const cachedScriptsContent: object = {};
const cachedStyleContent: object = {};
const cachedProcessedContent: object = {};

const defaultFetch = window?.fetch.bind(window);

Expand Down Expand Up @@ -340,11 +342,29 @@ export function processHtml(html: string, entry?: string): ProcessedContent {

const domContent = (new DOMParser()).parseFromString(html.replace(COMMENT_REGEX, ''), 'text/html');

/*
* When using DOMParser,the origin of relative path of `<script />` 和 `<link />` is Framwork's origin.
* To escape this error, append <base /> element and then remove them to avoid conflict.
*/
if (entry) {
// add base URI for absolute resource. see more https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
const base = document.createElement('base');
base.href = entry;
domContent.getElementsByTagName('head')[0].appendChild(base);
const baseElementMatch = html.match(BASE_LOOSE_REGEX);

const baseElements = domContent.getElementsByTagName('base');
const hasBaseElement = baseElements.length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

baseElements.length > 0


if (baseElementMatch && hasBaseElement) {
// Only take the first one into consideration.
const baseElement = baseElements[0];

const [, baseHerf] = baseElementMatch;
baseElement.href = isAbsoluteUrl(baseHerf) ? baseHerf : getUrl(entry, baseHerf);
} else {
// add base URI for absolute resource.
// see more https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
const base = document.createElement('base');
base.href = entry;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

说明下 base 设置即便是 /xx/index.html 加载也可以

domContent.getElementsByTagName('head')[0].appendChild(base);
}
}

// process js assets
Expand Down Expand Up @@ -388,9 +408,13 @@ export function processHtml(html: string, entry?: string): ProcessedContent {
];

if (entry) {
// remove base node
const baseNode = domContent.getElementsByTagName('base')[0];
baseNode?.parentNode.removeChild(baseNode);
/*
* Remove all child's <base /> element to avoid conflict with parent's.
*/
const baseNodes = domContent.getElementsByTagName('base');
for (let i = 0; i < baseNodes.length; ++i) {
baseNodes[i]?.parentNode.removeChild(baseNodes[i]);
}
}

return {
Expand All @@ -402,8 +426,6 @@ export function processHtml(html: string, entry?: string): ProcessedContent {
};
}

const cachedProcessedContent: object = {};

export async function getEntryAssets({
root,
entry,
Expand All @@ -420,9 +442,10 @@ export async function getEntryAssets({
fetch?: Fetch;
assertsCached?: boolean;
}) {
let cachedContent = cachedProcessedContent[assetsCacheKey];
const cachedContent = cachedProcessedContent[assetsCacheKey];
let htmlContent = entryContent;

if (!cachedContent) {
let htmlContent = entryContent;
if (!htmlContent && entry) {
if (!fetch) {
warn('Current environment does not support window.fetch, please use custom fetch');
Expand All @@ -431,20 +454,18 @@ export async function getEntryAssets({
);
}

const res = await fetch(entry);
htmlContent = await res.text();
htmlContent = await fetch(entry).then((res) => res.text());
}
cachedContent = processHtml(htmlContent, entry || href);
cachedProcessedContent[assetsCacheKey] = cachedContent;
cachedProcessedContent[assetsCacheKey] = htmlContent;
}

const { html } = cachedContent;
const { html, assets } = processHtml(cachedContent ?? htmlContent, entry || href);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

执行结果上目前是没问题的,看下 cachedContent 设置为 false/ '' 的情况下 是拿 htmlContent 作为兜底还是以设置的值为准


if (root) {
root.appendChild(html);
}

return cachedContent.assets;
return assets;
}

export function getAssetsNode(): Array<HTMLStyleElement|HTMLScriptElement> {
Expand Down
82 changes: 79 additions & 3 deletions tests/handleAssets.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
} from '../src/util/handleAssets';
import { setCache } from '../src/util/cache';

const originalLocation = window.location;

const tempHTML =
'<!DOCTYPE html>' +
'<html>' +
Expand Down Expand Up @@ -119,7 +121,20 @@ describe('getComment', () => {
});

describe('processHtml', () => {
test('processHtml', () => {
beforeEach(() => {
delete window.location;
// @ts-ignore
window.location = Object.assign(new URL("https://localhost:3333"), {
ancestorOrigins: "",
assign: jest.fn(),
reload: jest.fn(),
replace: jest.fn()
});
});
afterEach(() => {
window.location = originalLocation;
});
test('processHtml - basic', () => {
expect(processHtml(undefined).html.innerHTML).toBe('');

const { html, assets: {jsList, cssList} } = processHtml(tempHTML);
Expand Down Expand Up @@ -155,16 +170,78 @@ describe('processHtml', () => {
expect(jsList[5].type).toBe(AssetTypeEnum.EXTERNAL);
expect(jsList[5].content).toContain('//g.alicdn.com/test.min.js');


// script inline assets
expect(jsList[0].type).toBe(AssetTypeEnum.INLINE);
expect(jsList[0].content).toContain('console.log()');
expect(jsList[4].type).toBe(AssetTypeEnum.INLINE);
expect(jsList[4].content).toContain('window.g_config');

});

test('processHtml - entry', () => {
const { html } = processHtml(tempHTML, "https://localhost:3333");
const div = document.createElement('div');
div.appendChild(html);
const content = div.innerHTML;

expect(content).toContain('<!--link https://localhost:3333/test.css processed by @ice/stark-->');
expect(content).toContain('<!--link https://localhost:3333/index.css processed by @ice/stark-->');
expect(content).not.toContain('href="/index.css"');
expect(content).not.toContain('href="index.css"');

expect(content).not.toContain('base href="https://localhost:3333"')
});

test('processHtml - baseElement - absolute', () => {
let localHtml = tempHTML.replace('<head>', '<head> <base href="https://localhost:3334">')

const { html, assets } = processHtml(localHtml);
const div = document.createElement('div');
div.appendChild(html);
const content = div.innerHTML;

expect(content).toContain('<!--link https://localhost:3334/test.css processed by @ice/stark-->');
expect(content).toContain('<!--link https://localhost:3334/index.css processed by @ice/stark-->');
expect(content).not.toContain('href="/index.css"');
expect(content).not.toContain('href="index.css"');

expect(content).not.toContain('base href="https://localhost:3333"')
});

test('processHtml - baseElement - relative', () => {
let localHtml = tempHTML.replace('<head>', '<head> <base href="./a/b">')

const { html } = processHtml(localHtml, "https://localhost:3334");
const div = document.createElement('div');
div.appendChild(html);
const content = div.innerHTML;

expect(content).toContain('<!--link https://localhost:3334/a/test.css processed by @ice/stark-->');
expect(content).toContain('<!--link https://localhost:3334/index.css processed by @ice/stark-->');
expect(content).not.toContain('href="/index.css"');
expect(content).not.toContain('href="index.css"');

expect(content).not.toContain('base href="https://localhost:3334"')
});

test('processHtml - baseElement - relative', () => {
let localHtml = tempHTML.replace('<head>', '<head> <base href="/">')

const { html } = processHtml(localHtml, "https://localhost:3334/a/b/index.html");
const div = document.createElement('div');
div.appendChild(html);
const content = div.innerHTML;

expect(content).toContain('<!--link https://localhost:3334/test.css processed by @ice/stark-->');
expect(content).toContain('<!--link https://localhost:3334/index.css processed by @ice/stark-->');
expect(content).not.toContain('href="/index.css"');
expect(content).not.toContain('href="index.css"');

expect(content).not.toContain('base href="https://localhost:3333"')
});
});


describe('appendExternalScript', () => {
test('appendExternalScript -> inline', () => {
const div = document.createElement('div');
Expand Down Expand Up @@ -569,7 +646,6 @@ describe('appendCSS', () => {
});
});


describe('isAbsoluteUrl', () => {
test('isAbsoluteUrl', () => {
expect(isAbsoluteUrl('https://www.baidu.com/')).toBe(true);
Expand Down