@lynx-js/web-mainthread-apis 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/createMainThreadGlobalThis.d.ts +3 -2
- package/dist/createMainThreadGlobalThis.js +8 -4
- package/dist/crossThreadHandlers/createQueryComponent.d.ts +4 -0
- package/dist/crossThreadHandlers/createQueryComponent.js +57 -0
- package/dist/prepareMainThreadAPIs.d.ts +2 -2
- package/dist/prepareMainThreadAPIs.js +9 -2
- package/dist/pureElementPAPIs.js +3 -2
- package/dist/utils/processStyleInfo.d.ts +14 -7
- package/dist/utils/processStyleInfo.js +126 -54
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @lynx-js/web-mainthread-apis
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix: \_\_QueryComponentImpl in mts should execute only once for same url ([#1763](https://github.com/lynx-family/lynx-stack/pull/1763))
|
|
8
|
+
|
|
9
|
+
- fix: avoid duplicate style transformation ([#1748](https://github.com/lynx-family/lynx-stack/pull/1748))
|
|
10
|
+
|
|
11
|
+
After this commit, we use DAG methods to handle the styleInfos
|
|
12
|
+
|
|
13
|
+
- feat: support lazy bundle with CSSOG(`enableCSSSelector: false`). ([#1770](https://github.com/lynx-family/lynx-stack/pull/1770))
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`93d707b`](https://github.com/lynx-family/lynx-stack/commit/93d707b82a59f7256952e21da6dcad2999f8233d)]:
|
|
16
|
+
- @lynx-js/web-constants@0.17.0
|
|
17
|
+
- @lynx-js/web-style-transformer@0.17.0
|
|
18
|
+
|
|
19
|
+
## 0.16.1
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- feat: supports lazy bundle. (This feature requires `@lynx-js/lynx-core >= 0.1.3`) ([#1235](https://github.com/lynx-family/lynx-stack/pull/1235))
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [[`608f375`](https://github.com/lynx-family/lynx-stack/commit/608f375e20732cc4c9f141bfbf9800ba6896100b)]:
|
|
26
|
+
- @lynx-js/web-constants@0.16.1
|
|
27
|
+
- @lynx-js/web-style-transformer@0.16.1
|
|
28
|
+
|
|
3
29
|
## 0.16.0
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LynxTemplate, type PageConfig, type FlushElementTreeOptions, type Cloneable, type BrowserConfig, type publishEventEndpoint, type publicComponentEventEndpoint, type reportErrorEndpoint, type RpcCallType, type LynxContextEventTarget, type MainThreadGlobalThis, type WebFiberElementImpl, type I18nResourceTranslationOptions, type SSRHydrateInfo, type SSRDehydrateHooks, type JSRealm } from '@lynx-js/web-constants';
|
|
1
|
+
import { type LynxTemplate, type PageConfig, type FlushElementTreeOptions, type Cloneable, type BrowserConfig, type publishEventEndpoint, type publicComponentEventEndpoint, type reportErrorEndpoint, type RpcCallType, type LynxContextEventTarget, type MainThreadGlobalThis, type WebFiberElementImpl, type I18nResourceTranslationOptions, type SSRHydrateInfo, type SSRDehydrateHooks, type JSRealm, type QueryComponentPAPI } from '@lynx-js/web-constants';
|
|
2
2
|
export interface MainThreadRuntimeCallbacks {
|
|
3
3
|
mainChunkReady: () => void;
|
|
4
4
|
flushElementTree: (options: FlushElementTreeOptions, timingFlags: string[], exposureChangedElements: WebFiberElementImpl[]) => void;
|
|
@@ -8,7 +8,8 @@ export interface MainThreadRuntimeCallbacks {
|
|
|
8
8
|
publishEvent: RpcCallType<typeof publishEventEndpoint>;
|
|
9
9
|
publicComponentEvent: RpcCallType<typeof publicComponentEventEndpoint>;
|
|
10
10
|
_I18nResourceTranslation: (options: I18nResourceTranslationOptions) => unknown | undefined;
|
|
11
|
-
updateCssOGStyle: (uniqueId: number, newClassName: string, cssID: string | null) => void;
|
|
11
|
+
updateCssOGStyle: (uniqueId: number, newClassName: string, cssID: string | null, entryName: string | null) => void;
|
|
12
|
+
__QueryComponent: QueryComponentPAPI;
|
|
12
13
|
}
|
|
13
14
|
export interface MainThreadRuntimeConfig {
|
|
14
15
|
pageConfig: PageConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2023 The Lynx Authors. All rights reserved.
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
import { lynxUniqueIdAttribute, systemInfo, parentComponentUniqueIdAttribute, componentIdAttribute, LynxEventNameToW3cByTagName, LynxEventNameToW3cCommon, lynxTagAttribute, W3cEventNameToLynx, cssIdAttribute, lynxDefaultDisplayLinearAttribute, __lynx_timing_flag, lynxDisposedAttribute, } from '@lynx-js/web-constants';
|
|
4
|
+
import { lynxUniqueIdAttribute, systemInfo, parentComponentUniqueIdAttribute, componentIdAttribute, LynxEventNameToW3cByTagName, LynxEventNameToW3cCommon, lynxTagAttribute, W3cEventNameToLynx, cssIdAttribute, lynxDefaultDisplayLinearAttribute, __lynx_timing_flag, lynxDisposedAttribute, lynxEntryNameAttribute, } from '@lynx-js/web-constants';
|
|
5
5
|
import { createMainThreadLynx } from './createMainThreadLynx.js';
|
|
6
6
|
import { __AddClass, __AddConfig, __AddDataset, __AddInlineStyle, __AppendElement, __ElementIsEqual, __FirstElement, __GetAttributes, __GetChildren, __GetClasses, __GetComponentID, __GetDataByKey, __GetDataset, __GetElementConfig, __GetElementUniqueID, __GetID, __GetParent, __GetTag, __GetTemplateParts, __InsertElementBefore, __LastElement, __MarkPartElement, __MarkTemplateElement, __NextElement, __RemoveElement, __ReplaceElement, __ReplaceElements, __SetClasses, __SetConfig, __SetCSSId, __SetDataset, __SetID, __SetInlineStyles, __UpdateComponentID, __UpdateComponentInfo, __GetAttributeByName, } from './pureElementPAPIs.js';
|
|
7
7
|
import { createCrossThreadEvent } from './utils/createCrossThreadEvent.js';
|
|
@@ -291,9 +291,10 @@ export function createMainThreadGlobalThis(config) {
|
|
|
291
291
|
// @ts-expect-error fixme
|
|
292
292
|
temp.replaceWith(childB);
|
|
293
293
|
};
|
|
294
|
-
const __SetCSSIdForCSSOG = (elements, cssId) => {
|
|
294
|
+
const __SetCSSIdForCSSOG = (elements, cssId, entryName) => {
|
|
295
295
|
for (const element of elements) {
|
|
296
296
|
element.setAttribute(cssIdAttribute, cssId + '');
|
|
297
|
+
entryName && element.setAttribute(lynxEntryNameAttribute, entryName);
|
|
297
298
|
const cls = element.getAttribute('class');
|
|
298
299
|
cls && __SetClassesForCSSOG(element, cls);
|
|
299
300
|
}
|
|
@@ -304,13 +305,15 @@ export function createMainThreadGlobalThis(config) {
|
|
|
304
305
|
element.setAttribute('class', newClassName);
|
|
305
306
|
const cssId = element.getAttribute(cssIdAttribute);
|
|
306
307
|
const uniqueId = Number(element.getAttribute(lynxUniqueIdAttribute));
|
|
307
|
-
|
|
308
|
+
const entryName = element.getAttribute(lynxEntryNameAttribute);
|
|
309
|
+
callbacks.updateCssOGStyle(uniqueId, newClassName, cssId, entryName);
|
|
308
310
|
};
|
|
309
311
|
const __SetClassesForCSSOG = (element, classNames) => {
|
|
310
312
|
__SetClasses(element, classNames);
|
|
311
313
|
const cssId = element.getAttribute(cssIdAttribute);
|
|
312
314
|
const uniqueId = Number(element.getAttribute(lynxUniqueIdAttribute));
|
|
313
|
-
|
|
315
|
+
const entryName = element.getAttribute(lynxEntryNameAttribute);
|
|
316
|
+
callbacks.updateCssOGStyle(uniqueId, classNames ?? '', cssId, entryName);
|
|
314
317
|
};
|
|
315
318
|
const __LoadLepusChunk = (path) => {
|
|
316
319
|
try {
|
|
@@ -469,6 +472,7 @@ export function createMainThreadGlobalThis(config) {
|
|
|
469
472
|
__LoadLepusChunk,
|
|
470
473
|
__GetPageElement,
|
|
471
474
|
__globalProps: globalProps,
|
|
475
|
+
__QueryComponent: callbacks.__QueryComponent,
|
|
472
476
|
SystemInfo,
|
|
473
477
|
lynx: createMainThreadLynx(config, SystemInfo),
|
|
474
478
|
_ReportError: (err, _) => callbacks._ReportError(err, _, release),
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type JSRealm, type LynxCrossThreadContext, type MainThreadGlobalThis, type QueryComponentPAPI, type Rpc, type StyleInfo, type TemplateLoader } from '@lynx-js/web-constants';
|
|
2
|
+
export declare function createQueryComponent(loadTemplate: TemplateLoader, updateLazyComponentStyle: (styleInfo: StyleInfo, entryName: string) => void, backgroundThreadRpc: Rpc, mtsGlobalThisRef: {
|
|
3
|
+
mtsGlobalThis: MainThreadGlobalThis;
|
|
4
|
+
}, jsContext: LynxCrossThreadContext, mtsRealm: JSRealm): QueryComponentPAPI;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { queryComponentEndpoint, updateBTSTemplateCacheEndpoint, } from '@lynx-js/web-constants';
|
|
2
|
+
export function createQueryComponent(loadTemplate, updateLazyComponentStyle, backgroundThreadRpc, mtsGlobalThisRef, jsContext, mtsRealm) {
|
|
3
|
+
const updateBTSTemplateCache = backgroundThreadRpc.createCall(updateBTSTemplateCacheEndpoint);
|
|
4
|
+
const lazyCache = new Map();
|
|
5
|
+
const __QueryComponentImpl = (url, callback) => {
|
|
6
|
+
const cacheLazy = lazyCache.get(url);
|
|
7
|
+
const loadPromise = cacheLazy
|
|
8
|
+
?? loadTemplate(url).then(async (template) => {
|
|
9
|
+
const updateBTSCachePromise = updateBTSTemplateCache(url, template);
|
|
10
|
+
let lepusRootChunkExport = await mtsRealm.loadScript(template.lepusCode.root);
|
|
11
|
+
if (mtsGlobalThisRef.mtsGlobalThis.processEvalResult) {
|
|
12
|
+
lepusRootChunkExport = mtsGlobalThisRef.mtsGlobalThis
|
|
13
|
+
.processEvalResult(lepusRootChunkExport, url);
|
|
14
|
+
}
|
|
15
|
+
updateLazyComponentStyle(template.styleInfo, url);
|
|
16
|
+
await updateBTSCachePromise;
|
|
17
|
+
jsContext.dispatchEvent({
|
|
18
|
+
type: '__OnDynamicJSSourcePrepared',
|
|
19
|
+
data: url,
|
|
20
|
+
});
|
|
21
|
+
return lepusRootChunkExport;
|
|
22
|
+
});
|
|
23
|
+
!cacheLazy && lazyCache.set(url, loadPromise);
|
|
24
|
+
loadPromise.then(lepusRootChunkExport => {
|
|
25
|
+
callback?.({
|
|
26
|
+
code: 0,
|
|
27
|
+
data: {
|
|
28
|
+
url,
|
|
29
|
+
evalResult: lepusRootChunkExport,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}).catch((error) => {
|
|
33
|
+
console.error(`lynx web: lazy bundle load failed:`, error);
|
|
34
|
+
lazyCache.delete(url);
|
|
35
|
+
callback?.({
|
|
36
|
+
code: -1,
|
|
37
|
+
data: undefined,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
return null;
|
|
41
|
+
};
|
|
42
|
+
backgroundThreadRpc.registerHandler(queryComponentEndpoint, (url) => {
|
|
43
|
+
const ret = new Promise(resolve => {
|
|
44
|
+
__QueryComponentImpl(url, (result) => {
|
|
45
|
+
resolve({
|
|
46
|
+
code: result.code,
|
|
47
|
+
detail: {
|
|
48
|
+
schema: url,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
return ret;
|
|
54
|
+
});
|
|
55
|
+
return __QueryComponentImpl;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=createQueryComponent.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Rpc, type StartMainThreadContextConfig, type RpcCallType, type reportErrorEndpoint, type I18nResourceTranslationOptions, type InitI18nResources, type I18nResources, type SSRHydrateInfo, type SSRDehydrateHooks, type JSRealm } from '@lynx-js/web-constants';
|
|
2
|
-
export declare function prepareMainThreadAPIs(backgroundThreadRpc: Rpc, rootDom: Document | ShadowRoot, document: Document, mtsRealm: JSRealm, commitDocument: (exposureChangedElements: HTMLElement[]) => Promise<void> | void, markTimingInternal: (timingKey: string, pipelineId?: string) => void, flushMarkTimingInternal: () => void, reportError: RpcCallType<typeof reportErrorEndpoint>, triggerI18nResourceFallback: (options: I18nResourceTranslationOptions) => void, initialI18nResources: (data: InitI18nResources) => I18nResources, ssrHooks?: SSRDehydrateHooks): {
|
|
1
|
+
import { type Rpc, type StartMainThreadContextConfig, type RpcCallType, type reportErrorEndpoint, type I18nResourceTranslationOptions, type InitI18nResources, type I18nResources, type SSRHydrateInfo, type SSRDehydrateHooks, type JSRealm, type TemplateLoader } from '@lynx-js/web-constants';
|
|
2
|
+
export declare function prepareMainThreadAPIs(backgroundThreadRpc: Rpc, rootDom: Document | ShadowRoot, document: Document, mtsRealm: JSRealm, commitDocument: (exposureChangedElements: HTMLElement[]) => Promise<void> | void, markTimingInternal: (timingKey: string, pipelineId?: string) => void, flushMarkTimingInternal: () => void, reportError: RpcCallType<typeof reportErrorEndpoint>, triggerI18nResourceFallback: (options: I18nResourceTranslationOptions) => void, initialI18nResources: (data: InitI18nResources) => I18nResources, loadTemplate: TemplateLoader, ssrHooks?: SSRDehydrateHooks): {
|
|
3
3
|
startMainThread: (config: StartMainThreadContextConfig, ssrHydrateInfo?: SSRHydrateInfo) => Promise<void>;
|
|
4
4
|
};
|
|
@@ -8,8 +8,9 @@ import { createMainThreadGlobalThis } from './createMainThreadGlobalThis.js';
|
|
|
8
8
|
import { createExposureService } from './utils/createExposureService.js';
|
|
9
9
|
import { initWasm } from '@lynx-js/web-style-transformer';
|
|
10
10
|
import { appendStyleElement } from './utils/processStyleInfo.js';
|
|
11
|
+
import { createQueryComponent } from './crossThreadHandlers/createQueryComponent.js';
|
|
11
12
|
const initWasmPromise = initWasm();
|
|
12
|
-
export function prepareMainThreadAPIs(backgroundThreadRpc, rootDom, document, mtsRealm, commitDocument, markTimingInternal, flushMarkTimingInternal, reportError, triggerI18nResourceFallback, initialI18nResources, ssrHooks) {
|
|
13
|
+
export function prepareMainThreadAPIs(backgroundThreadRpc, rootDom, document, mtsRealm, commitDocument, markTimingInternal, flushMarkTimingInternal, reportError, triggerI18nResourceFallback, initialI18nResources, loadTemplate, ssrHooks) {
|
|
13
14
|
const postTimingFlags = backgroundThreadRpc.createCall(postTimingFlagsEndpoint);
|
|
14
15
|
const backgroundStart = backgroundThreadRpc.createCall(BackgroundThreadStartEndpoint);
|
|
15
16
|
const publishEvent = backgroundThreadRpc.createCall(publishEventEndpoint);
|
|
@@ -29,7 +30,11 @@ export function prepareMainThreadAPIs(backgroundThreadRpc, rootDom, document, mt
|
|
|
29
30
|
sendEventEndpoint: dispatchCoreContextOnBackgroundEndpoint,
|
|
30
31
|
});
|
|
31
32
|
const i18nResources = initialI18nResources(initI18nResources);
|
|
32
|
-
const { updateCssOGStyle } = appendStyleElement(styleInfo, pageConfig, rootDom, document,
|
|
33
|
+
const { updateCssOGStyle, updateLazyComponentStyle } = appendStyleElement(styleInfo, pageConfig, rootDom, document, ssrHydrateInfo);
|
|
34
|
+
const mtsGlobalThisRef = {
|
|
35
|
+
mtsGlobalThis: undefined,
|
|
36
|
+
};
|
|
37
|
+
const __QueryComponent = createQueryComponent(loadTemplate, updateLazyComponentStyle, backgroundThreadRpc, mtsGlobalThisRef, jsContext, mtsRealm);
|
|
33
38
|
const mtsGlobalThis = createMainThreadGlobalThis({
|
|
34
39
|
lynxTemplate: template,
|
|
35
40
|
mtsRealm,
|
|
@@ -127,8 +132,10 @@ export function prepareMainThreadAPIs(backgroundThreadRpc, rootDom, document, mt
|
|
|
127
132
|
}
|
|
128
133
|
return triggerI18nResourceFallback(options);
|
|
129
134
|
},
|
|
135
|
+
__QueryComponent,
|
|
130
136
|
},
|
|
131
137
|
});
|
|
138
|
+
mtsGlobalThisRef.mtsGlobalThis = mtsGlobalThis;
|
|
132
139
|
markTimingInternal('decode_end');
|
|
133
140
|
await mtsRealm.loadScript(template.lepusCode.root);
|
|
134
141
|
jsContext.__start(); // start the jsContext after the runtime is created
|
package/dist/pureElementPAPIs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2023 The Lynx Authors. All rights reserved.
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
import { componentIdAttribute, cssIdAttribute, lynxComponentConfigAttribute, lynxDatasetAttribute, lynxElementTemplateMarkerAttribute, lynxPartIdAttribute, lynxTagAttribute, lynxUniqueIdAttribute, } from '@lynx-js/web-constants';
|
|
4
|
+
import { componentIdAttribute, cssIdAttribute, lynxComponentConfigAttribute, lynxDatasetAttribute, lynxElementTemplateMarkerAttribute, lynxEntryNameAttribute, lynxPartIdAttribute, lynxTagAttribute, lynxUniqueIdAttribute, } from '@lynx-js/web-constants';
|
|
5
5
|
import { queryCSSProperty } from './style/cssPropertyMap.js';
|
|
6
6
|
import { transformInlineStyleString, transformParsedStyles, } from './style/transformInlineStyle.js';
|
|
7
7
|
import hyphenateStyleName from 'hyphenate-style-name';
|
|
@@ -92,9 +92,10 @@ export const __UpdateComponentInfo = /*#__PURE__*/ (element, params) => {
|
|
|
92
92
|
&& element.setAttribute(cssIdAttribute, params.cssID + '');
|
|
93
93
|
params.name !== undefined && element.setAttribute('name', params.name);
|
|
94
94
|
};
|
|
95
|
-
export const __SetCSSId = /*#__PURE__*/ (elements, cssId) => {
|
|
95
|
+
export const __SetCSSId = /*#__PURE__*/ (elements, cssId, entryName) => {
|
|
96
96
|
for (const element of elements) {
|
|
97
97
|
element.setAttribute(cssIdAttribute, cssId + '');
|
|
98
|
+
entryName && element.setAttribute(lynxEntryNameAttribute, entryName);
|
|
98
99
|
}
|
|
99
100
|
};
|
|
100
101
|
export const __SetClasses = /*#__PURE__*/ (element, classname) => {
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import { type StyleInfo, type CssOGInfo, type PageConfig, type SSRHydrateInfo } from '@lynx-js/web-constants';
|
|
2
|
-
|
|
1
|
+
import { type StyleInfo, type CssOGInfo, type PageConfig, type SSRHydrateInfo, type FlattenedStyleInfo } from '@lynx-js/web-constants';
|
|
2
|
+
/**
|
|
3
|
+
* get Transitive Closure of a Direct Acyclic Graph (DAG)
|
|
4
|
+
* 1. for each css, find all the imported by css files (directly and indirectly)
|
|
5
|
+
* 2. for each css, find all the importing css files (directly and indirectly)
|
|
6
|
+
* 3. return the flattened style info, do not modify the content and rules
|
|
7
|
+
*/
|
|
8
|
+
export declare function flattenStyleInfo(styleInfo: StyleInfo): FlattenedStyleInfo;
|
|
3
9
|
/**
|
|
4
10
|
* apply the lynx css -> web css transformation
|
|
5
11
|
*/
|
|
6
|
-
export declare function transformToWebCss(styleInfo:
|
|
12
|
+
export declare function transformToWebCss(styleInfo: FlattenedStyleInfo): void;
|
|
7
13
|
/**
|
|
8
14
|
* generate those styles applied by <style>...</style>
|
|
9
15
|
*/
|
|
10
|
-
export declare function genCssContent(styleInfo:
|
|
16
|
+
export declare function genCssContent(styleInfo: FlattenedStyleInfo, pageConfig: PageConfig, entryName?: string): string;
|
|
11
17
|
/**
|
|
12
18
|
* generate the css-in-js data
|
|
13
19
|
*/
|
|
14
|
-
export declare function genCssOGInfo(styleInfo:
|
|
15
|
-
export declare function appendStyleElement(styleInfo: StyleInfo, pageConfig: PageConfig, rootDom: Node, document: Document,
|
|
16
|
-
updateCssOGStyle: (uniqueId: number, newClassName: string, cssID: string | null) => void;
|
|
20
|
+
export declare function genCssOGInfo(styleInfo: FlattenedStyleInfo): CssOGInfo;
|
|
21
|
+
export declare function appendStyleElement(styleInfo: StyleInfo, pageConfig: PageConfig, rootDom: Node, document: Document, ssrHydrateInfo?: SSRHydrateInfo): {
|
|
22
|
+
updateCssOGStyle: (uniqueId: number, newClassName: string, cssID: string | null, entryName: string | null) => void;
|
|
23
|
+
updateLazyComponentStyle: (styleInfo: StyleInfo, entryName: string) => void;
|
|
17
24
|
};
|
|
@@ -4,36 +4,94 @@
|
|
|
4
4
|
import { cssIdAttribute, lynxTagAttribute, lynxUniqueIdAttribute, lynxEntryNameAttribute, } from '@lynx-js/web-constants';
|
|
5
5
|
import { transformParsedStyles } from './tokenizer.js';
|
|
6
6
|
import { decodeCssOG } from './decodeCssOG.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
function topologicalSort(styleInfo) {
|
|
8
|
+
/**
|
|
9
|
+
* kahn's algorithm
|
|
10
|
+
* 1. The styleInfo is already equivalent to a adjacency list. (cssId, import)
|
|
11
|
+
* 2. The styleInfo is a DAG therefore we don't need to do cyclic detection
|
|
12
|
+
*/
|
|
13
|
+
const queue = [];
|
|
14
|
+
const inDegreeMap = new Map();
|
|
15
|
+
for (const [cssId, oneStyleInfo] of Object.entries(styleInfo)) {
|
|
16
|
+
!inDegreeMap.has(cssId) && inDegreeMap.set(cssId, 0); // initialize
|
|
17
|
+
for (const importCssId of oneStyleInfo.imports ?? []) {
|
|
18
|
+
const currentInDegree = inDegreeMap.get(importCssId) ?? 0;
|
|
19
|
+
inDegreeMap.set(importCssId, currentInDegree + 1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const [cssId, inDegree] of inDegreeMap.entries()) {
|
|
23
|
+
if (inDegree === 0) {
|
|
24
|
+
queue.push(cssId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const sortedCssIds = [];
|
|
28
|
+
while (queue.length > 0) {
|
|
29
|
+
const currentCssId = queue.shift();
|
|
30
|
+
sortedCssIds.push(currentCssId);
|
|
31
|
+
const currentAdjunction = styleInfo[currentCssId]?.imports;
|
|
32
|
+
if (currentAdjunction) {
|
|
33
|
+
for (const importCssId of currentAdjunction) {
|
|
34
|
+
const importInDegree = inDegreeMap.get(importCssId) - 1;
|
|
35
|
+
inDegreeMap.set(importCssId, importInDegree);
|
|
36
|
+
if (importInDegree === 0) {
|
|
37
|
+
queue.push(importCssId);
|
|
22
38
|
}
|
|
23
39
|
}
|
|
24
|
-
oneInfo.imports = undefined;
|
|
25
40
|
}
|
|
26
|
-
return oneInfo;
|
|
27
41
|
}
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
return sortedCssIds;
|
|
43
|
+
}
|
|
44
|
+
function generateImportByMap(styleInfo, sortedCssIds) {
|
|
45
|
+
const cssIdToImportBy = new Map();
|
|
46
|
+
for (const cssId of sortedCssIds) {
|
|
47
|
+
const currentAdjunction = styleInfo[cssId]?.imports;
|
|
48
|
+
if (currentAdjunction) {
|
|
49
|
+
const currentImportBy = cssIdToImportBy.get(cssId) ?? new Set([cssId]);
|
|
50
|
+
for (const importCssId of currentAdjunction) {
|
|
51
|
+
const importDeps = cssIdToImportBy.get(importCssId)
|
|
52
|
+
?? new Set([importCssId]);
|
|
53
|
+
importDeps.add(cssId);
|
|
54
|
+
cssIdToImportBy.set(importCssId, currentImportBy.union(importDeps));
|
|
55
|
+
}
|
|
56
|
+
cssIdToImportBy.set(cssId, currentImportBy);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return cssIdToImportBy;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* get Transitive Closure of a Direct Acyclic Graph (DAG)
|
|
63
|
+
* 1. for each css, find all the imported by css files (directly and indirectly)
|
|
64
|
+
* 2. for each css, find all the importing css files (directly and indirectly)
|
|
65
|
+
* 3. return the flattened style info, do not modify the content and rules
|
|
66
|
+
*/
|
|
67
|
+
export function flattenStyleInfo(styleInfo) {
|
|
68
|
+
// Step 1. Topological sorting
|
|
69
|
+
const sortedCssIds = topologicalSort(styleInfo);
|
|
70
|
+
// Step 2. generate deps;
|
|
71
|
+
const cssIdToImportBy = generateImportByMap(styleInfo, sortedCssIds);
|
|
72
|
+
sortedCssIds.reverse();
|
|
73
|
+
// Step 3. generate the flattened style info
|
|
74
|
+
return sortedCssIds.map(cssId => {
|
|
75
|
+
const oneInfo = styleInfo[cssId];
|
|
76
|
+
const flattenedInfo = oneInfo
|
|
77
|
+
? {
|
|
78
|
+
content: oneInfo.content,
|
|
79
|
+
rules: oneInfo.rules,
|
|
80
|
+
importBy: Array.from(cssIdToImportBy.get(cssId) ?? [cssId]),
|
|
81
|
+
}
|
|
82
|
+
: {
|
|
83
|
+
content: [],
|
|
84
|
+
rules: [],
|
|
85
|
+
importBy: [cssId],
|
|
86
|
+
};
|
|
87
|
+
return flattenedInfo;
|
|
30
88
|
});
|
|
31
89
|
}
|
|
32
90
|
/**
|
|
33
91
|
* apply the lynx css -> web css transformation
|
|
34
92
|
*/
|
|
35
93
|
export function transformToWebCss(styleInfo) {
|
|
36
|
-
for (const cssInfos of
|
|
94
|
+
for (const cssInfos of styleInfo) {
|
|
37
95
|
for (const rule of cssInfos.rules) {
|
|
38
96
|
const { sel: selectors, decl: declarations } = rule;
|
|
39
97
|
const { transformedStyle, childStyle } = transformParsedStyles(declarations);
|
|
@@ -56,19 +114,13 @@ export function genCssContent(styleInfo, pageConfig, entryName) {
|
|
|
56
114
|
function getExtraSelectors(cssId) {
|
|
57
115
|
let suffix;
|
|
58
116
|
if (!pageConfig.enableRemoveCSSScope) {
|
|
59
|
-
|
|
60
|
-
suffix = `[${cssIdAttribute}="${cssId}"]`;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
// To make sure the Specificity correct
|
|
64
|
-
suffix = `[${lynxTagAttribute}]`;
|
|
65
|
-
}
|
|
117
|
+
suffix = `[${cssIdAttribute}="${cssId}"]`;
|
|
66
118
|
}
|
|
67
119
|
else {
|
|
68
120
|
suffix = `[${lynxTagAttribute}]`;
|
|
69
121
|
}
|
|
70
122
|
if (entryName) {
|
|
71
|
-
suffix = `${suffix}[${lynxEntryNameAttribute}
|
|
123
|
+
suffix = `${suffix}[${lynxEntryNameAttribute}=${JSON.stringify(entryName)}]`;
|
|
72
124
|
}
|
|
73
125
|
else {
|
|
74
126
|
suffix = `${suffix}:not([${lynxEntryNameAttribute}])`;
|
|
@@ -76,13 +128,15 @@ export function genCssContent(styleInfo, pageConfig, entryName) {
|
|
|
76
128
|
return suffix;
|
|
77
129
|
}
|
|
78
130
|
const finalCssContent = [];
|
|
79
|
-
for (const
|
|
80
|
-
const suffix = getExtraSelectors(cssId);
|
|
131
|
+
for (const cssInfos of styleInfo) {
|
|
81
132
|
const declarationContent = cssInfos.rules.map((rule) => {
|
|
82
133
|
const { sel: selectorList, decl: declarations } = rule;
|
|
83
134
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
|
|
84
|
-
const selectorString =
|
|
85
|
-
|
|
135
|
+
const selectorString = cssInfos.importBy.map(cssId => {
|
|
136
|
+
const suffix = getExtraSelectors(cssId);
|
|
137
|
+
return selectorList.map((selectors) => {
|
|
138
|
+
return selectors.toSpliced(-4, 0, [suffix]).flat().join('');
|
|
139
|
+
}).join(',');
|
|
86
140
|
}).join(',');
|
|
87
141
|
const declarationString = declarations.map(([k, v]) => `${k}:${v};`).join('');
|
|
88
142
|
return `${selectorString}{${declarationString}}`;
|
|
@@ -95,10 +149,10 @@ export function genCssContent(styleInfo, pageConfig, entryName) {
|
|
|
95
149
|
* generate the css-in-js data
|
|
96
150
|
*/
|
|
97
151
|
export function genCssOGInfo(styleInfo) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
152
|
+
const cssOGInfo = {};
|
|
153
|
+
for (const oneInfo of styleInfo) {
|
|
154
|
+
oneInfo.rules = oneInfo.rules.filter(oneRule => {
|
|
155
|
+
oneRule.sel = oneRule.sel.filter(selectorList => {
|
|
102
156
|
const [classSelectors, pseudoClassSelectors, pseudoElementSelectors, combinator,] = selectorList;
|
|
103
157
|
if (
|
|
104
158
|
// only one class selector
|
|
@@ -107,23 +161,28 @@ export function genCssOGInfo(styleInfo) {
|
|
|
107
161
|
&& pseudoElementSelectors.length === 0
|
|
108
162
|
&& combinator.length === 0) {
|
|
109
163
|
const selectorName = classSelectors[0].substring(1);
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
164
|
+
for (const cssId of oneInfo.importBy) {
|
|
165
|
+
if (!cssOGInfo[cssId]) {
|
|
166
|
+
cssOGInfo[cssId] = {};
|
|
167
|
+
}
|
|
168
|
+
const currentDeclarations = cssOGInfo[cssId][selectorName];
|
|
169
|
+
if (currentDeclarations) {
|
|
170
|
+
currentDeclarations.push(...oneRule.decl);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
cssOGInfo[cssId][selectorName] = oneRule.decl;
|
|
174
|
+
}
|
|
116
175
|
}
|
|
117
176
|
return false; // remove this selector from style info
|
|
118
177
|
}
|
|
119
178
|
return true;
|
|
120
179
|
});
|
|
121
|
-
return
|
|
180
|
+
return oneRule.sel.length > 0;
|
|
122
181
|
});
|
|
123
|
-
|
|
124
|
-
|
|
182
|
+
}
|
|
183
|
+
return cssOGInfo;
|
|
125
184
|
}
|
|
126
|
-
export function appendStyleElement(styleInfo, pageConfig, rootDom, document,
|
|
185
|
+
export function appendStyleElement(styleInfo, pageConfig, rootDom, document, ssrHydrateInfo) {
|
|
127
186
|
const lynxUniqueIdToStyleRulesIndex = ssrHydrateInfo?.lynxUniqueIdToStyleRulesIndex ?? [];
|
|
128
187
|
/**
|
|
129
188
|
* now create the style content
|
|
@@ -133,23 +192,27 @@ export function appendStyleElement(styleInfo, pageConfig, rootDom, document, ent
|
|
|
133
192
|
* 4. create the style element
|
|
134
193
|
* 5. append the style element to the root dom
|
|
135
194
|
*/
|
|
136
|
-
flattenStyleInfo(styleInfo
|
|
137
|
-
transformToWebCss(
|
|
195
|
+
const flattenedStyleInfo = flattenStyleInfo(styleInfo);
|
|
196
|
+
transformToWebCss(flattenedStyleInfo);
|
|
138
197
|
const cssOGInfo = pageConfig.enableCSSSelector
|
|
139
198
|
? {}
|
|
140
|
-
: genCssOGInfo(
|
|
199
|
+
: genCssOGInfo(flattenedStyleInfo);
|
|
200
|
+
const lazyCSSOGInfo = {};
|
|
141
201
|
let cardStyleElement;
|
|
142
202
|
if (ssrHydrateInfo?.cardStyleElement) {
|
|
143
203
|
cardStyleElement = ssrHydrateInfo.cardStyleElement;
|
|
144
204
|
}
|
|
145
205
|
else {
|
|
146
206
|
cardStyleElement = document.createElement('style');
|
|
147
|
-
cardStyleElement.textContent = genCssContent(
|
|
207
|
+
cardStyleElement.textContent = genCssContent(flattenedStyleInfo, pageConfig, undefined);
|
|
148
208
|
rootDom.appendChild(cardStyleElement);
|
|
149
209
|
}
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
const
|
|
210
|
+
const updateCssOGStyle = (uniqueId, newClassName, cssID, entryName) => {
|
|
211
|
+
const cardStyleElementSheet = cardStyleElement.sheet;
|
|
212
|
+
const styleMap = entryName && lazyCSSOGInfo[entryName]
|
|
213
|
+
? lazyCSSOGInfo[entryName]
|
|
214
|
+
: cssOGInfo;
|
|
215
|
+
const newStyles = decodeCssOG(newClassName, styleMap, cssID);
|
|
153
216
|
if (lynxUniqueIdToStyleRulesIndex[uniqueId] !== undefined) {
|
|
154
217
|
const rule = cardStyleElementSheet
|
|
155
218
|
.cssRules[lynxUniqueIdToStyleRulesIndex[uniqueId]];
|
|
@@ -160,6 +223,15 @@ export function appendStyleElement(styleInfo, pageConfig, rootDom, document, ent
|
|
|
160
223
|
lynxUniqueIdToStyleRulesIndex[uniqueId] = index;
|
|
161
224
|
}
|
|
162
225
|
};
|
|
163
|
-
|
|
226
|
+
const updateLazyComponentStyle = (styleInfo, entryName) => {
|
|
227
|
+
const flattenedStyleInfo = flattenStyleInfo(styleInfo);
|
|
228
|
+
transformToWebCss(flattenedStyleInfo);
|
|
229
|
+
if (!pageConfig.enableCSSSelector) {
|
|
230
|
+
lazyCSSOGInfo[entryName] = genCssOGInfo(flattenedStyleInfo);
|
|
231
|
+
}
|
|
232
|
+
const newStyleSheet = genCssContent(flattenedStyleInfo, pageConfig, entryName);
|
|
233
|
+
cardStyleElement.textContent += newStyleSheet;
|
|
234
|
+
};
|
|
235
|
+
return { updateCssOGStyle, updateLazyComponentStyle };
|
|
164
236
|
}
|
|
165
237
|
//# sourceMappingURL=processStyleInfo.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynx-js/web-mainthread-apis",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "",
|
|
6
6
|
"keywords": [],
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"hyphenate-style-name": "^1.1.0",
|
|
28
|
-
"@lynx-js/web-constants": "0.
|
|
29
|
-
"@lynx-js/web-style-transformer": "0.
|
|
28
|
+
"@lynx-js/web-constants": "0.17.0",
|
|
29
|
+
"@lynx-js/web-style-transformer": "0.17.0"
|
|
30
30
|
}
|
|
31
31
|
}
|