Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feat-optimize-slot
Browse files Browse the repository at this point in the history
  • Loading branch information
Tidyzq committed Sep 4, 2023
2 parents 82eaf51 + 266db83 commit b9f7a17
Show file tree
Hide file tree
Showing 38 changed files with 945 additions and 375 deletions.
77 changes: 77 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: deploy-pages

on:
push:
branches: ["master"]

workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: latest
- name: Setup node ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install
uses: pnpm/action-setup@v2
with:
version: latest
run_install: |
- recursive: true
args: [--frozen-lockfile, --strict-peer-dependencies]
- name: Setup Rust and Cargo
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: wasm32-unknown-unknown
- name: Setup wasm-pack
uses: jetli/[email protected]
with:
version: 'latest'
- name: Build
run: |
pnpm -r run build
- name: Generate docs for glass-easel
working-directory: glass-easel
run: |
npm run doc
- name: Generate docs for glass-easel-miniprogram-adapter
working-directory: glass-easel-miniprogram-adapter
run: |
npm run doc
- name: Collect artifacts
run: |
mkdir github-pages
mkdir github-pages/docs
mv glass-easel/docs github-pages/docs/glass-easel
mv glass-easel-miniprogram-adapter/docs github-pages/docs/glass-easel-miniprogram-adapter
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: 'github-pages'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
10 changes: 9 additions & 1 deletion README-zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,15 @@ npm install --save-dev glass-easel-template-compiler
glass-easel-miniprogram-adapter 接口与 [小程序自定义组件](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/) 接口一致。
[glass-easel-miniprogram-template](./glass-easel-miniprogram-template) 是一个供参考的项目模板。

此外, TypeScript 编写的子模块支持 TSDoc ,可以在子模块代码目录中通过 `npm run doc` 来生成详细的接口文档(生成好的文档位于 `docs` 子目录中); rust 编写的子模块,则可以通过 `cargo doc` 来生成详细的接口文档(与普通 rust crate 类似)。
TypeScript 编写的子模块支持 TSDoc ,其生成文档可供参考:

* [glass-easel TSDoc 接口文档](https://wechat-miniprogram.github.io/glass-easel/docs/glass-easel)
* [glass-easel-miniprogram-adapter TSDoc 接口文档](https://wechat-miniprogram.github.io/glass-easel/docs/glass-easel-miniprogram-adapter)

对于 rust 编写的子模块, cargo doc 生成文档可供参考:

* [位于 docs.rs 的 glass-easel-template-compiler 接口文档](https://docs.rs/glass-easel-template-compiler/latest/glass_easel_template_compiler/)
* [位于 docs.rs 的 glass-easel-stylesheet-compiler 接口文档](https://docs.rs/glass-easel-stylesheet-compiler/latest/glass_easel_stylesheet_compiler/)

## 常见问题

Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,15 @@ npm install --save-dev glass-easel-template-compiler
The interface of [glass-easel-miniprogram-adapter](./glass-easel-miniprogram-adapter) is the same as the custom component interface of MiniProgram.
[glass-easel-miniprogram-template](./glass-easel-miniprogram-template) is a project template.

Furthermore, TypeScript modules contains TSDoc documents, which can be built with `npm run doc` (generated documents are in the `docs` directory); rust module documents can be retrived through `cargo doc` (like common rust crates).
TypeScript modules support TSDoc. The auto-generated documents are in GitHub pages.

* [TSDoc documents for glass-easel](https://wechat-miniprogram.github.io/glass-easel/docs/glass-easel)
* [TSDoc documents for glass-easel-miniprogram-adapter](https://wechat-miniprogram.github.io/glass-easel/docs/glass-easel-miniprogram-adapter)

For the rust interface, see the generated documents in docs.rs.

* [glass-easel-template-compiler documents in docs.rs](https://docs.rs/glass-easel-template-compiler/latest/glass_easel_template_compiler/)
* [glass-easel-stylesheet-compiler documents in docs.rs](https://docs.rs/glass-easel-stylesheet-compiler/latest/glass_easel_stylesheet_compiler/)

## F.A.Q.

Expand All @@ -91,7 +99,7 @@ However, no MiniProgram code can use any _glass-easel_ submodules currently, bec

No. This module is the framework itself. Components like `<view />` `<image />` are not included.

This is because the implamentation of the components are complex and deeply coupled with WeChat environment interfaces. We cannot simply reuse the code in web environments.
This is because the implementation of the components are complex and deeply coupled with WeChat environment interfaces. We cannot simply reuse the code in web environments.

We will consider do another implementation on web in future.

Expand Down
12 changes: 12 additions & 0 deletions glass-easel-miniprogram-adapter/src/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,20 @@ export class Root {
*
* This component, the `parent` and the `placeholder` MUST be in the same context.
* The `parent` MUST be a parent node of the `placeholder` .
* This also triggers `attached` lifetimes for components.
*/
attach(parent: glassEasel.GeneralBackendElement, placeholder: glassEasel.GeneralBackendElement) {
glassEasel.Element.replaceDocumentElement(this._$comp, parent, placeholder)
}

/**
* Release the root component
*
* Some backends require this explicit call to avoid memory leaks.
* This also triggers `detached` lifetimes for components.
*/
release() {
glassEasel.Element.pretendDetached(this._$comp)
this._$comp.destroyBackendElement()
}
}
2 changes: 1 addition & 1 deletion glass-easel-miniprogram-adapter/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class ComponentCaller<
TMethod extends MethodList,
TComponentExport,
> {
/** @internal */
/** The corresponding `Component` */
_$!: glassEasel.Component<TData, TProperty, TMethod>
/** @internal */
_$export?: (source: GeneralComponent | null) => TComponentExport
Expand Down
13 changes: 8 additions & 5 deletions glass-easel-miniprogram-adapter/src/intersection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,25 @@ export class IntersectionObserver {
targetSelector: string,
listener: (status: glassEasel.backend.IntersectionStatus) => void,
) {
const shadowRoot = this._$comp._$.getShadowRoot()
let targets: glassEasel.Element[]
if (this._$observeAll) {
targets = this._$comp._$.querySelectorAll(targetSelector)
if (!shadowRoot) {
targets = []
} else if (this._$observeAll) {
targets = shadowRoot.querySelectorAll(targetSelector)
} else {
const elem = this._$comp._$.querySelector(targetSelector)
const elem = shadowRoot.querySelector(targetSelector)
if (elem === null) {
targets = []
} else {
targets = [elem]
}
}
let relativeElement: glassEasel.Element | null
if (this._$selector === null) {
if (this._$selector === null || !shadowRoot) {
relativeElement = null
} else {
const rel = this._$comp._$.querySelector(this._$selector)
const rel = shadowRoot.querySelector(this._$selector)
if (rel === null) {
// TODO warn no matched relative element
} else {
Expand Down
37 changes: 8 additions & 29 deletions glass-easel-miniprogram-adapter/tests/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,49 +53,28 @@ describe('env', () => {
)
})

test('add global components', () => {
test('using behaviors', () => {
const env = new MiniProgramEnv()
const globalCodeSpace = env.getGlobalCodeSpace()
const def = globalCodeSpace
.getComponentSpace()
.define('external')
.options({
virtualHost: true,
})
.template(
tmpl(`
<span class="inner" />
`),
)
.registerComponent()
const codeSpace = env.createCodeSpace('', true)
codeSpace.getComponentSpace().setGlobalUsingComponent('external', def)

codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
external: 'external',
},
})
codeSpace.addComponentStaticConfig('path/to/comp', {})

codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
<div class="outer">
<external />
</div>
`),
<div>{{ num }}</div>
`),
)

codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
codeSpace.componentEnv('path/to/comp', ({ Behavior, Component }) => {
const beh = Behavior({ data: { num: 123 } })
Component().behavior(beh).register()
})

const backend = new glassEasel.domlikeBackend.CurrentWindowBackendContext()
const ab = env.associateBackend(backend)
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe(
'<div class="outer"><span class="inner"></span></div>',
)
expect(domHtml(root.getComponent())).toBe('<div>123</div>')
})

test('multiple code spaces', () => {
Expand Down
4 changes: 2 additions & 2 deletions glass-easel-miniprogram-adapter/tests/selector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,10 @@ describe('intersection observer', () => {
.register()
})

const ab = env.associateBackend()
const backendContext = new glassEasel.composedBackend.EmptyComposedBackendContext()
const ab = env.associateBackend(backendContext)
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
glassEasel.Element.pretendAttached(root.getComponent())
expect(domHtml(root.getComponent())).toBe('<div><div></div><div></div></div>')
})
})

Expand Down
4 changes: 2 additions & 2 deletions glass-easel-template-compiler/src/cbinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl StrRef {
impl Drop for StrRef {
fn drop(&mut self) {
unsafe {
drop(slice::from_raw_parts_mut(self.buf, self.len));
let _ = Box::from_raw(slice::from_raw_parts_mut(self.buf, self.len));
}
}
}
Expand Down Expand Up @@ -329,7 +329,7 @@ impl TmplGroup {
impl Drop for TmplGroup {
fn drop(&mut self) {
unsafe {
drop(&mut *(self.inner as *mut group::TmplGroup));
let _ = Box::from_raw(&mut *(self.inner as *mut group::TmplGroup));
}
}
}
8 changes: 7 additions & 1 deletion glass-easel-template-compiler/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,9 +1026,10 @@ impl TmplExpr {
scopes: &Vec<ScopeVar>,
) -> Result<TmplExprProcGen, TmplError> {
let mut value = String::new();
let level = self.level();
let (pas, sub_p) =
self.to_proc_gen_rec_and_combine_paths(w, scopes, TmplExprLevel::Cond, &mut value)?;
Ok(TmplExprProcGen { pas, sub_p, value })
Ok(TmplExprProcGen { pas, sub_p, value, level })
}

// this function finds which keys can be put into the binding map,
Expand Down Expand Up @@ -1208,6 +1209,7 @@ pub(crate) struct TmplExprProcGen {
pas: PathAnalysisState,
sub_p: Vec<PathSliceList>,
value: String,
level: TmplExprLevel,
}

impl TmplExprProcGen {
Expand Down Expand Up @@ -1249,4 +1251,8 @@ impl TmplExprProcGen {
write!(w, "{}", self.value)?;
Ok(())
}

pub(crate) fn above_cond_expr(&self) -> bool {
self.level >= TmplExprLevel::Cond
}
}
4 changes: 2 additions & 2 deletions glass-easel-template-compiler/src/js_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct TmplGroup {

fn convert_str_arr(arr: &Vec<String>) -> js_sys::Array {
let ret = js_sys::Array::new_with_length(arr.len() as u32);
for item in arr {
ret.push(&JsValue::from(item));
for (index, item) in arr.iter().enumerate() {
ret.set(index as u32, JsValue::from(item));
}
ret
}
Expand Down
12 changes: 9 additions & 3 deletions glass-easel-template-compiler/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,13 @@ impl TmplElement {
write!(w, "{}?{}:", gen_lit_str(&v), index + 1)?;
}
CondItem::Dynamic(p) => {
p.value_expr(w)?;
if p.above_cond_expr() {
w.paren(|w| {
p.value_expr(w)
})?;
} else {
p.value_expr(w)?;
}
write!(w, "?{}:", index + 1)?;
}
}
Expand Down Expand Up @@ -1101,9 +1107,9 @@ impl TmplElement {
var_key, var_target, var_target
)?;
p.value_expr(w)?;
write!(w, ",U?")?;
write!(w, ",K||(U?")?;
p.lvalue_state_expr(w, scopes)?;
write!(w, ":undefined).C(C,T,E,B,F,S,J)")?;
write!(w, ":undefined)).C(C,T,E,B,F,S,J)")?;
Ok(())
})
}
Expand Down
10 changes: 6 additions & 4 deletions glass-easel/guide/zh_CN/data_management/data_observer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

## 监听数据字段变化

通过数据监听器,可以在某些属性或数据字段被设置时触发一个函数
通过数据监听器,可以在某些属性或数据字段被设置时触发一个响应函数

例如,可以在 `a``b` 两个字段中任何一个被设置时,触发一个函数:
这个响应函数会在属性或数据字段应用到模板前被调用,可以在总体上减少模板更新次数从而提升性能。

在这个响应函数中,可以使用 `updateData` 来更新其他的数据字段,这些数据字段会响应函数执行完毕后生效。注意,虽然也可以使用 `setData` ,但数据监听器中的 `setData` 并不会立刻应用到模板上,而是像 `updateData` 一样、等到数据监听器执行完毕后才应用到模板上。

例如,可以在 `a``b` 两个字段中任何一个被设置时,触发一个响应函数:

```js
// 使用 Definition API 添加数据监听器
Expand All @@ -21,8 +25,6 @@ export const addComponent = componentSpace.defineComponent({
observers: {
'a, b': function () {
// 数据监听器中,最好使用 updateData 而非 setData
// (事实上,使用 setData 将与 updateData 等效)
// 数据监听器执行完后,会自动将更新应用到模板上
this.updateData({
sum: this.data.a + this.data.b,
})
Expand Down
4 changes: 2 additions & 2 deletions glass-easel/src/backend/mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ export type CSSRule = {
weightLowBits: number
}

export type GetMatchedRulesResponese = {
export type GetMatchedRulesResponses = {
inline: CSSProperty[]
rules: CSSRule[]
}

export type GetAllComputedStylesResponese = {
export type GetAllComputedStylesResponses = {
properties: CSSProperty[]
}

Expand Down
Loading

0 comments on commit b9f7a17

Please sign in to comment.