Consolidate JavaScript Flavors #1433
88
.eslintrc.cjs
Normal file
88
.eslintrc.cjs
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
ignorePatterns: [
|
||||
'/website',
|
||||
'**/binaries/**',
|
||||
'**/build/**',
|
||||
'**/generated/**',
|
||||
],
|
||||
overrides: [
|
||||
// Catch-all
|
||||
{
|
||||
files: ['**/*.?(m|c){j,t}s?(x)'],
|
||||
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
||||
plugins: ['prettier'],
|
||||
rules: {
|
||||
'no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
|
||||
'no-var': 'error',
|
||||
'prefer-arrow-callback': 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-object-spread': 'error',
|
||||
'prefer-spread': 'error',
|
||||
'require-await': 'error',
|
||||
},
|
||||
env: {
|
||||
es2020: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
},
|
||||
},
|
||||
// ES Modules
|
||||
{
|
||||
files: ['**/*.?(m){j,t}s?(x)'],
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
// CommonJS Modules
|
||||
{
|
||||
files: ['**/*.c{j,t}s?(x)'],
|
||||
env: {
|
||||
commonjs: true,
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'commonjs',
|
||||
},
|
||||
},
|
||||
// TypeScript
|
||||
{
|
||||
files: ['**/*.?(m|c)ts?(x)'],
|
||||
extends: ['plugin:@typescript-eslint/recommended'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: true,
|
||||
},
|
||||
plugins: ['@typescript-eslint'],
|
||||
rules: {
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{argsIgnorePattern: '^_'},
|
||||
],
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
},
|
||||
},
|
||||
// Node
|
||||
{
|
||||
files: ['**/.*rc.(c){j,t}s', '**/*.config.?(c){j,t}s'],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
// Jest
|
||||
{
|
||||
files: ['**/tests/**'],
|
||||
extends: ['plugin:jest/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
76
.eslintrc.js
76
.eslintrc.js
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
ignorePatterns: [
|
||||
'/website',
|
||||
'**/binaries/**',
|
||||
'**/build/**',
|
||||
'**/generated/**',
|
||||
],
|
||||
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
|
||||
plugins: ['prettier'],
|
||||
rules: {
|
||||
'no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
|
||||
'no-var': 'error',
|
||||
'prefer-arrow-callback': 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-object-spread': 'error',
|
||||
'prefer-spread': 'error',
|
||||
'require-await': 'error',
|
||||
},
|
||||
env: {
|
||||
commonjs: true,
|
||||
es2018: true,
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 'latest',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
extends: ['plugin:@typescript-eslint/recommended'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: true,
|
||||
},
|
||||
plugins: ['@typescript-eslint'],
|
||||
rules: {
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{argsIgnorePattern: '^_'},
|
||||
],
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/.eslintrc.js', '**/just.config.js'],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['jest.*', '**/tests/**'],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: ['plugin:jest/recommended'],
|
||||
globals: {
|
||||
getMeasureCounter: 'writable',
|
||||
getMeasureCounterMax: 'writable',
|
||||
getMeasureCounterMin: 'writable',
|
||||
Yoga: 'writable',
|
||||
YGBENCHMARK: 'writable',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
@@ -23,7 +23,7 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, {
|
||||
|
||||
emitPrologue: {
|
||||
value: function () {
|
||||
this.push('import {Yoga} from "../tools/globals";');
|
||||
this.push("import Yoga from 'yoga-layout';");
|
||||
this.push('import {');
|
||||
this.pushIndent();
|
||||
this.push('Align,');
|
||||
|
@@ -31,9 +31,9 @@ add_compile_options(${COMPILE_OPTIONS})
|
||||
|
||||
add_link_options(
|
||||
${COMPILE_OPTIONS}
|
||||
--closure 1
|
||||
--memory-init-file 0
|
||||
--no-entry
|
||||
"SHELL:--closure 1"
|
||||
"SHELL:--memory-init-file 0"
|
||||
"SHELL:--no-entry"
|
||||
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
|
||||
"SHELL:-s ASSERTIONS=0"
|
||||
"SHELL:-s DYNAMIC_EXECUTION=0"
|
||||
@@ -42,8 +42,9 @@ add_link_options(
|
||||
"SHELL:-s FILESYSTEM=0"
|
||||
"SHELL:-s MALLOC='emmalloc'"
|
||||
"SHELL:-s MODULARIZE=1"
|
||||
"SHELL:-s TEXTDECODER=0"
|
||||
"SHELL:-s SINGLE_FILE=1")
|
||||
"SHELL:-s EXPORT_ES6=1"
|
||||
"SHELL:-s WASM=1"
|
||||
"SHELL:-s TEXTDECODER=0")
|
||||
|
||||
link_libraries(embind)
|
||||
|
||||
@@ -51,62 +52,9 @@ add_library(yogaObjLib OBJECT ${SOURCES})
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/binaries)
|
||||
|
||||
add_executable(asmjs-sync-node $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-sync-node PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='node'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
||||
|
||||
add_executable(asmjs-async-node $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-async-node PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='node'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
||||
|
||||
add_executable(asmjs-sync-web $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-sync-web PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
||||
|
||||
add_executable(asmjs-async-web $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-async-web PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
||||
|
||||
add_executable(asmjs-sync $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-sync PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web,node'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
||||
|
||||
add_executable(asmjs-async $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(asmjs-async PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web,node'"
|
||||
"SHELL:-s WASM=0"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
||||
|
||||
add_executable(wasm-sync-node $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(wasm-sync-node PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='node'"
|
||||
"SHELL:-s WASM=1"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
||||
|
||||
add_executable(wasm-async-node $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(wasm-async-node PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='node'"
|
||||
"SHELL:-s WASM=1"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
||||
|
||||
add_executable(wasm-sync-web $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(wasm-sync-web PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web'"
|
||||
"SHELL:-s WASM=1"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=0")
|
||||
|
||||
add_executable(wasm-async-web $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(wasm-async-web PUBLIC
|
||||
"SHELL:-s ENVIRONMENT='web'"
|
||||
"SHELL:-s WASM=1"
|
||||
"SHELL:-s WASM_ASYNC_COMPILATION=1")
|
||||
add_executable(web $<TARGET_OBJECTS:yogaObjLib>)
|
||||
target_link_options(web PRIVATE
|
||||
# SINGLE_FILE=1 combined with ENVIRONMENT='web' creates code that works on
|
||||
# both bundlders and Node.
|
||||
"SHELL:-s SINGLE_FILE=1"
|
||||
"SHELL:-s ENVIRONMENT='web'")
|
||||
|
@@ -1,24 +1,11 @@
|
||||
# yoga-layout
|
||||
|
||||
This package provides prebuilt JavaScript bindings for the Yoga layout engine. Both WebAssembly and asm.js variants are packaged, with the optimal loaded based on platform.
|
||||
This package provides prebuilt WebAssembly bindings for the Yoga layout engine.
|
||||
|
||||
## Usage
|
||||
|
||||
The default entrypoint provides an asynchronous loader function to return a Yoga instance.
|
||||
|
||||
```ts
|
||||
import {loadYoga, Align} from 'yoga-layout';
|
||||
|
||||
const Yoga = await loadYoga();
|
||||
|
||||
const node = Yoga.Node.create();
|
||||
node.setAlignContent(Align.Center);
|
||||
```
|
||||
|
||||
An alternative synchronous API is provided for compatibility, but requires using asm.js in browsers instead of WebAssembly, leading to worse performance and larger assets.
|
||||
|
||||
```ts
|
||||
import Yoga, {Align} from 'yoga-layout/sync';
|
||||
import {Yoga, Align} from 'yoga-layout';
|
||||
|
||||
const node = Yoga.Node.create();
|
||||
node.setAlignContent(Align.Center);
|
||||
@@ -37,20 +24,14 @@ node.freeRecursive();
|
||||
node.free();
|
||||
```
|
||||
|
||||
## Selecting WebAssembly or asm.js
|
||||
|
||||
For better performance and smaller packages, WebAssembly is preferred to asm.js where available. `yoga-layout` tries to provide the right default using [export maps](https://webpack.js.org/guides/package-exports/#conditional-syntax) so that platforms which can take advantage of WebAssembly use it by default.
|
||||
|
||||
Different entrypoints are exposed to choose a flavor explicitly.
|
||||
|
||||
```ts
|
||||
import {loadYoga} from 'yoga-layout/wasm-async';
|
||||
```
|
||||
|
||||
## Using TypeScript
|
||||
|
||||
This package provides out-of-the-box TypeScript typings so long as `tsc` is configured to support ESM resolution. It is recommended to set `moduleResolution: 'bundler'` or `moduleResolution: node16` in your `tsconfig.json` according to your environment.
|
||||
|
||||
## ES Modules
|
||||
|
||||
`yoga-layout` is only provided as an ES Module, relying on top-level await. This allows providing a synchronous API, while still allowing async WebAssembly compilation in browsers, and will allow eventual usage of ESM/WASM interop.
|
||||
|
||||
## Contributing
|
||||
|
||||
### Requirements
|
||||
|
30
javascript/babel.config.cjs
Normal file
30
javascript/babel.config.cjs
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = api => ({
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: [
|
||||
'maintained node versions',
|
||||
'> 0.5%, last 2 versions, Firefox ESR, not dead',
|
||||
],
|
||||
// Do not transform to another module system
|
||||
modules: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
'@babel/preset-typescript',
|
||||
{
|
||||
rewriteImportExtensions: api.env('dist'),
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
@@ -7,9 +7,8 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
presets: [
|
||||
['@babel/preset-env', {targets: 'defaults'}],
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
export default {
|
||||
setupFiles: ['./jest.setup.js'],
|
||||
testRegex: '/tests/.*\\.test\\.ts$',
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
};
|
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {Config} from 'jest';
|
||||
|
||||
const config: Config = {
|
||||
setupFiles: ['./jest.setup.ts'],
|
||||
testRegex: '/tests/.*\\.test\\.[jt]s$',
|
||||
moduleNameMapper: {
|
||||
'yoga-layout':
|
||||
process.env['SYNC'] === '1' && process.env['WASM'] === '1'
|
||||
? 'yoga-layout/wasm-sync'
|
||||
: process.env['SYNC'] === '1'
|
||||
? 'yoga-layout/asmjs-sync'
|
||||
: process.env['WASM'] === '1'
|
||||
? 'yoga-layout/wasm-async'
|
||||
: 'yoga-layout/asmjs-async',
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
@@ -7,11 +7,6 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = async () => {
|
||||
const {loadYoga, default: Yoga} = require('yoga-layout');
|
||||
globalThis.Yoga = Yoga ?? (await loadYoga());
|
||||
};
|
||||
|
||||
Object.defineProperty(globalThis, 'YGBENCHMARK', {
|
||||
get: () => globalThis.test,
|
||||
});
|
@@ -7,7 +7,7 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {
|
||||
const {
|
||||
argv,
|
||||
cleanTask,
|
||||
logger,
|
||||
@@ -18,13 +18,13 @@ import {
|
||||
spawn,
|
||||
task,
|
||||
tscTask,
|
||||
} from 'just-scripts';
|
||||
} = require('just-scripts');
|
||||
|
||||
import {readFile, writeFile} from 'fs/promises';
|
||||
const {readFile, writeFile} = require('fs/promises');
|
||||
|
||||
import glob from 'glob';
|
||||
import path from 'path';
|
||||
import which from 'which';
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const which = require('which');
|
||||
|
||||
const node = process.execPath;
|
||||
|
||||
@@ -32,11 +32,15 @@ option('fix');
|
||||
|
||||
task('clean', cleanTask({paths: ['build', 'dist']}));
|
||||
|
||||
function defineFlavor(flavor: string, env: NodeJS.ProcessEnv) {
|
||||
function defineFlavor(flavor, env) {
|
||||
task(`cmake-build:${flavor}`, cmakeBuildTask({targets: [flavor]}));
|
||||
task(
|
||||
`jest:${flavor}`,
|
||||
jestTask({config: path.join(__dirname, 'jest.config.ts'), env}),
|
||||
jestTask({
|
||||
config: path.join(__dirname, 'jest.config.js'),
|
||||
nodeArgs: ['--experimental-vm-modules'],
|
||||
env,
|
||||
}),
|
||||
);
|
||||
task(
|
||||
`test:${flavor}`,
|
||||
@@ -44,33 +48,17 @@ function defineFlavor(flavor: string, env: NodeJS.ProcessEnv) {
|
||||
);
|
||||
}
|
||||
|
||||
defineFlavor('asmjs-async-node', {WASM: '0', SYNC: '0'});
|
||||
defineFlavor('asmjs-sync-node', {WASM: '0', SYNC: '1'});
|
||||
defineFlavor('asmjs-async-web', {WASM: '0', SYNC: '0'});
|
||||
defineFlavor('asmjs-sync-web', {WASM: '0', SYNC: '1'});
|
||||
defineFlavor('wasm-async-node', {WASM: '1', SYNC: '0'});
|
||||
defineFlavor('wasm-sync-node', {WASM: '1', SYNC: '1'});
|
||||
defineFlavor('wasm-async-web', {WASM: '1', SYNC: '0'});
|
||||
defineFlavor('wasm-sync-web', {WASM: '1', SYNC: '1'});
|
||||
defineFlavor('web');
|
||||
|
||||
task('build', series(emcmakeGenerateTask(), cmakeBuildTask()));
|
||||
|
||||
task(
|
||||
'test',
|
||||
series(
|
||||
emcmakeGenerateTask(),
|
||||
series('cmake-build:asmjs-async-node', 'jest:asmjs-async-node'),
|
||||
series('cmake-build:asmjs-sync-node', 'jest:asmjs-sync-node'),
|
||||
series('cmake-build:wasm-async-node', 'jest:wasm-async-node'),
|
||||
series('cmake-build:wasm-sync-node', 'jest:wasm-sync-node'),
|
||||
),
|
||||
);
|
||||
task('test', series(emcmakeGenerateTask(), 'cmake-build:web', 'jest:web'));
|
||||
|
||||
task(
|
||||
'benchmark',
|
||||
series(
|
||||
emcmakeGenerateTask(),
|
||||
cmakeBuildTask({targets: ['asmjs-sync-node', 'wasm-sync-node']}),
|
||||
cmakeBuildTask({targets: ['web']}),
|
||||
runBenchTask(),
|
||||
),
|
||||
);
|
||||
@@ -95,21 +83,17 @@ task(
|
||||
),
|
||||
);
|
||||
|
||||
function recursiveReplace(
|
||||
obj: Record<string, unknown>,
|
||||
pattern: RegExp,
|
||||
replacement: string,
|
||||
) {
|
||||
function recursiveReplace(obj, pattern, replacement) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (typeof value === 'string') {
|
||||
obj[key] = value.replace(pattern, replacement);
|
||||
} else if (typeof value === 'object' && value != null) {
|
||||
recursiveReplace(value as Record<string, unknown>, pattern, replacement);
|
||||
recursiveReplace(value, pattern, replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function babelTransformTask(opts: {dir: string}) {
|
||||
function babelTransformTask(opts) {
|
||||
return () => {
|
||||
const args = [
|
||||
opts.dir,
|
||||
@@ -117,12 +101,16 @@ function babelTransformTask(opts: {dir: string}) {
|
||||
'--out-dir',
|
||||
opts.dir,
|
||||
'--extensions',
|
||||
'.js,.ts',
|
||||
'.js,.cjs,.mjs,.ts,.cts,.mts',
|
||||
];
|
||||
logger.info(`Transforming "${path.resolve(opts.dir)}"`);
|
||||
|
||||
return spawn(node, [require.resolve('@babel/cli/bin/babel'), ...args], {
|
||||
cwd: __dirname,
|
||||
env: {
|
||||
// Trigger distribution-specific Babel transforms
|
||||
NODE_ENV: 'dist',
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -132,23 +120,15 @@ function runBenchTask() {
|
||||
const files = glob.sync('./tests/Benchmarks/**/*');
|
||||
|
||||
const args = [
|
||||
'--extensions',
|
||||
'.js,.ts',
|
||||
'--config-file',
|
||||
path.join(__dirname, '.babelrc.js'),
|
||||
'--',
|
||||
'--loader=babel-register-esm',
|
||||
'./tests/bin/run-bench.ts',
|
||||
...files,
|
||||
];
|
||||
logger.info(['babel-node', ...args].join(' '));
|
||||
logger.info(['node', ...args].join(' '));
|
||||
|
||||
return spawn(
|
||||
node,
|
||||
[require.resolve('@babel/node/bin/babel-node'), ...args],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
return spawn(node, args, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -170,7 +150,7 @@ function emcmakeGenerateTask() {
|
||||
};
|
||||
}
|
||||
|
||||
function cmakeBuildTask(opts?: {targets?: ReadonlyArray<string>}) {
|
||||
function cmakeBuildTask(opts) {
|
||||
return () => {
|
||||
const cmake = which.sync('cmake');
|
||||
const args = [
|
||||
@@ -184,7 +164,7 @@ function cmakeBuildTask(opts?: {targets?: ReadonlyArray<string>}) {
|
||||
};
|
||||
}
|
||||
|
||||
function clangFormatTask(opts?: {fix?: boolean}) {
|
||||
function clangFormatTask(opts) {
|
||||
return () => {
|
||||
const args = [
|
||||
...(opts?.fix ? ['-i'] : ['--dry-run', '--Werror']),
|
@@ -9,69 +9,38 @@
|
||||
"type": "git",
|
||||
"url": "git@github.com:facebook/yoga.git"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"browser": "./src/entrypoint/wasm-async-web.ts",
|
||||
"node": "./src/entrypoint/wasm-async-node.ts",
|
||||
"default": "./src/entrypoint/asmjs-async-web.ts"
|
||||
},
|
||||
"./sync": {
|
||||
"browser": "./src/entrypoint/asmjs-sync-web.ts",
|
||||
"node": "./src/entrypoint/wasm-sync-node.ts",
|
||||
"default": "./src/entrypoint/asmjs-sync-web.ts"
|
||||
},
|
||||
"./asmjs-async": {
|
||||
"browser": "./src/entrypoint/asmjs-async-web.ts",
|
||||
"node": "./src/entrypoint/asmjs-async-node.ts",
|
||||
"default": "./src/entrypoint/asmjs-async-web.ts"
|
||||
},
|
||||
"./asmjs-sync": {
|
||||
"browser": "./src/entrypoint/asmjs-sync-web.ts",
|
||||
"node": "./src/entrypoint/asmjs-sync-node.ts",
|
||||
"default": "./src/entrypoint/asmjs-sync-web.ts"
|
||||
},
|
||||
"./wasm-async": {
|
||||
"browser": "./src/entrypoint/wasm-async-web.ts",
|
||||
"node": "./src/entrypoint/wasm-async-node.ts",
|
||||
"default": "./src/entrypoint/wasm-async-web.ts"
|
||||
},
|
||||
"./wasm-sync": {
|
||||
"browser": "./src/entrypoint/wasm-sync-web.ts",
|
||||
"node": "./src/entrypoint/wasm-sync-node.ts",
|
||||
"default": "./src/entrypoint/wasm-async-web.ts"
|
||||
}
|
||||
},
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"files": [
|
||||
"binaries/**",
|
||||
"src/**"
|
||||
],
|
||||
"scripts": {
|
||||
"benchmark": "just benchmark",
|
||||
"build": "just build",
|
||||
"clang-format": "just clang-format",
|
||||
"clang-format:fix": "just clang-format --fix",
|
||||
"clean": "just clean",
|
||||
"benchmark": "just benchmark --config just.config.cjs",
|
||||
"build": "just build --config just.config.cjs",
|
||||
"clang-format": "just clang-format --config just.config.cjs",
|
||||
"clang-format:fix": "just clang-format --fix --config just.config.cjs",
|
||||
"clean": "just clean --config just.config.cjs",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepack": "just prepack",
|
||||
"test": "just test",
|
||||
"prepack": "just prepack --config just.config.cjs",
|
||||
"test": "just test --config just.config.cjs",
|
||||
"tsc": "tsc --noEmit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.21.4",
|
||||
"@babel/core": "^7.21.4",
|
||||
"@babel/node": "^7.21.4",
|
||||
"@babel/preset-env": "^7.21.4",
|
||||
"@babel/preset-typescript": "^7.21.4",
|
||||
"@babel/cli": "^7.23.0",
|
||||
"@babel/core": "^7.23.0",
|
||||
"@babel/preset-env": "^7.23.0",
|
||||
"@babel/preset-typescript": "^7.23.0",
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^16.18.25",
|
||||
"@types/which": "^3.0.0",
|
||||
"babel-register-esm": "^1.2.5",
|
||||
"clang-format": "^1.8.0",
|
||||
"glob": "^8.0.3",
|
||||
"jest": "^29.3.1",
|
||||
"just-scripts": "^2.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"which": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
import type {Yoga} from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/asmjs-async-node');
|
||||
|
||||
export async function loadYoga(): Promise<Yoga> {
|
||||
return wrapAssembly(await loadAssembly());
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
import type {Yoga} from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/asmjs-async-web');
|
||||
|
||||
export async function loadYoga(): Promise<Yoga> {
|
||||
return wrapAssembly(await loadAssembly());
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/asmjs-sync-node');
|
||||
const Yoga = wrapAssembly(loadAssembly());
|
||||
export default Yoga;
|
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/asmjs-sync-web');
|
||||
const Yoga = wrapAssembly(loadAssembly());
|
||||
export default Yoga;
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
import type {Yoga} from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/wasm-async-node');
|
||||
|
||||
export async function loadYoga(): Promise<Yoga> {
|
||||
return wrapAssembly(await loadAssembly());
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
import type {Yoga} from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/wasm-async-web');
|
||||
|
||||
export async function loadYoga(): Promise<Yoga> {
|
||||
return wrapAssembly(await loadAssembly());
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
|
||||
const loadAssembly = require('../../binaries/wasm-sync-node');
|
||||
const Yoga = wrapAssembly(loadAssembly());
|
||||
export default Yoga;
|
@@ -7,17 +7,17 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import wrapAssembly from '../wrapAssembly';
|
||||
// @ts-ignore untyped from Emscripten
|
||||
import loadYoga from '../binaries/web.js';
|
||||
import wrapAssembly from './wrapAssembly.ts';
|
||||
|
||||
export * from '../generated/YGEnums';
|
||||
export type {
|
||||
Config,
|
||||
DirtiedFunction,
|
||||
MeasureFunction,
|
||||
Node,
|
||||
Yoga,
|
||||
} from '../wrapAssembly';
|
||||
} from './wrapAssembly.ts';
|
||||
|
||||
const loadAssembly = require('../../binaries/wasm-sync-web');
|
||||
const Yoga = wrapAssembly(loadAssembly());
|
||||
const Yoga = wrapAssembly(await loadYoga());
|
||||
export default Yoga;
|
||||
export * from './generated/YGEnums.ts';
|
@@ -1,146 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import YGEnums, {Unit, Direction} from './generated/YGEnums';
|
||||
|
||||
export default function wrapAssembly(lib) {
|
||||
function patch(prototype, name, fn) {
|
||||
const original = prototype[name];
|
||||
|
||||
prototype[name] = function (...args) {
|
||||
return fn.call(this, original, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
for (const fnName of [
|
||||
'setPosition',
|
||||
'setMargin',
|
||||
'setFlexBasis',
|
||||
'setWidth',
|
||||
'setHeight',
|
||||
'setMinWidth',
|
||||
'setMinHeight',
|
||||
'setMaxWidth',
|
||||
'setMaxHeight',
|
||||
'setPadding',
|
||||
]) {
|
||||
const methods = {
|
||||
[Unit.Point]: lib.Node.prototype[fnName],
|
||||
[Unit.Percent]: lib.Node.prototype[`${fnName}Percent`],
|
||||
[Unit.Auto]: lib.Node.prototype[`${fnName}Auto`],
|
||||
};
|
||||
|
||||
patch(lib.Node.prototype, fnName, function (original, ...args) {
|
||||
// We patch all these functions to add support for the following calls:
|
||||
// .setWidth(100) / .setWidth("100%") / .setWidth(.getWidth()) / .setWidth("auto")
|
||||
|
||||
const value = args.pop();
|
||||
let unit, asNumber;
|
||||
|
||||
if (value === 'auto') {
|
||||
unit = Unit.Auto;
|
||||
asNumber = undefined;
|
||||
} else if (typeof value === 'object') {
|
||||
unit = value.unit;
|
||||
asNumber = value.valueOf();
|
||||
} else {
|
||||
unit =
|
||||
typeof value === 'string' && value.endsWith('%')
|
||||
? Unit.Percent
|
||||
: Unit.Point;
|
||||
asNumber = parseFloat(value);
|
||||
if (!Number.isNaN(value) && Number.isNaN(asNumber)) {
|
||||
throw new Error(`Invalid value ${value} for ${fnName}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!methods[unit])
|
||||
throw new Error(
|
||||
`Failed to execute "${fnName}": Unsupported unit '${value}'`,
|
||||
);
|
||||
|
||||
if (asNumber !== undefined) {
|
||||
return methods[unit].call(this, ...args, asNumber);
|
||||
} else {
|
||||
return methods[unit].call(this, ...args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function wrapMeasureFunction(measureFunction) {
|
||||
return lib.MeasureCallback.implement({
|
||||
measure: (...args) => {
|
||||
const {width, height} = measureFunction(...args);
|
||||
return {
|
||||
width: width ?? NaN,
|
||||
height: height ?? NaN,
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
patch(lib.Node.prototype, 'setMeasureFunc', function (original, measureFunc) {
|
||||
// This patch is just a convenience patch, since it helps write more
|
||||
// idiomatic source code (such as .setMeasureFunc(null))
|
||||
if (measureFunc) {
|
||||
return original.call(this, wrapMeasureFunction(measureFunc));
|
||||
} else {
|
||||
return this.unsetMeasureFunc();
|
||||
}
|
||||
});
|
||||
|
||||
function wrapDirtiedFunc(dirtiedFunction) {
|
||||
return lib.DirtiedCallback.implement({dirtied: dirtiedFunction});
|
||||
}
|
||||
|
||||
patch(lib.Node.prototype, 'setDirtiedFunc', function (original, dirtiedFunc) {
|
||||
original.call(this, wrapDirtiedFunc(dirtiedFunc));
|
||||
});
|
||||
|
||||
patch(lib.Config.prototype, 'free', function () {
|
||||
// Since we handle the memory allocation ourselves (via lib.Config.create),
|
||||
// we also need to handle the deallocation
|
||||
lib.Config.destroy(this);
|
||||
});
|
||||
|
||||
patch(lib.Node, 'create', (_, config) => {
|
||||
// We decide the constructor we want to call depending on the parameters
|
||||
return config
|
||||
? lib.Node.createWithConfig(config)
|
||||
: lib.Node.createDefault();
|
||||
});
|
||||
|
||||
patch(lib.Node.prototype, 'free', function () {
|
||||
// Since we handle the memory allocation ourselves (via lib.Node.create),
|
||||
// we also need to handle the deallocation
|
||||
lib.Node.destroy(this);
|
||||
});
|
||||
|
||||
patch(lib.Node.prototype, 'freeRecursive', function () {
|
||||
for (let t = 0, T = this.getChildCount(); t < T; ++t) {
|
||||
this.getChild(0).freeRecursive();
|
||||
}
|
||||
this.free();
|
||||
});
|
||||
|
||||
patch(
|
||||
lib.Node.prototype,
|
||||
'calculateLayout',
|
||||
function (original, width = NaN, height = NaN, direction = Direction.LTR) {
|
||||
// Just a small patch to add support for the function default parameters
|
||||
return original.call(this, width, height, direction);
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
Config: lib.Config,
|
||||
Node: lib.Node,
|
||||
...YGEnums,
|
||||
};
|
||||
}
|
@@ -6,10 +6,13 @@
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
// @ts-nocheck
|
||||
|
||||
import {Unit, Direction} from './generated/YGEnums.ts';
|
||||
import YGEnums from './generated/YGEnums.ts';
|
||||
|
||||
import type {
|
||||
Align,
|
||||
Direction,
|
||||
Display,
|
||||
Edge,
|
||||
Errata,
|
||||
@@ -20,11 +23,8 @@ import type {
|
||||
MeasureMode,
|
||||
Overflow,
|
||||
PositionType,
|
||||
Unit,
|
||||
Wrap,
|
||||
} from './generated/YGEnums';
|
||||
|
||||
import YGEnums from './generated/YGEnums';
|
||||
} from './generated/YGEnums.ts';
|
||||
|
||||
type Layout = {
|
||||
left: number;
|
||||
@@ -179,5 +179,138 @@ export type Yoga = {
|
||||
};
|
||||
} & typeof YGEnums;
|
||||
|
||||
declare const wrapAsm: (assembly: unknown) => Yoga;
|
||||
export default wrapAsm;
|
||||
export default function wrapAssembly(lib: any): Yoga {
|
||||
function patch(prototype, name, fn) {
|
||||
const original = prototype[name];
|
||||
|
||||
prototype[name] = function (...args) {
|
||||
return fn.call(this, original, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
for (const fnName of [
|
||||
'setPosition',
|
||||
'setMargin',
|
||||
'setFlexBasis',
|
||||
'setWidth',
|
||||
'setHeight',
|
||||
'setMinWidth',
|
||||
'setMinHeight',
|
||||
'setMaxWidth',
|
||||
'setMaxHeight',
|
||||
'setPadding',
|
||||
]) {
|
||||
const methods = {
|
||||
[Unit.Point]: lib.Node.prototype[fnName],
|
||||
[Unit.Percent]: lib.Node.prototype[`${fnName}Percent`],
|
||||
[Unit.Auto]: lib.Node.prototype[`${fnName}Auto`],
|
||||
};
|
||||
|
||||
patch(lib.Node.prototype, fnName, function (original, ...args) {
|
||||
// We patch all these functions to add support for the following calls:
|
||||
// .setWidth(100) / .setWidth("100%") / .setWidth(.getWidth()) / .setWidth("auto")
|
||||
|
||||
const value = args.pop();
|
||||
let unit, asNumber;
|
||||
|
||||
if (value === 'auto') {
|
||||
unit = Unit.Auto;
|
||||
asNumber = undefined;
|
||||
} else if (typeof value === 'object') {
|
||||
unit = value.unit;
|
||||
asNumber = value.valueOf();
|
||||
} else {
|
||||
unit =
|
||||
typeof value === 'string' && value.endsWith('%')
|
||||
? Unit.Percent
|
||||
: Unit.Point;
|
||||
asNumber = parseFloat(value);
|
||||
if (!Number.isNaN(value) && Number.isNaN(asNumber)) {
|
||||
throw new Error(`Invalid value ${value} for ${fnName}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!methods[unit])
|
||||
throw new Error(
|
||||
`Failed to execute "${fnName}": Unsupported unit '${value}'`,
|
||||
);
|
||||
|
||||
if (asNumber !== undefined) {
|
||||
return methods[unit].call(this, ...args, asNumber);
|
||||
} else {
|
||||
return methods[unit].call(this, ...args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function wrapMeasureFunction(measureFunction) {
|
||||
return lib.MeasureCallback.implement({
|
||||
measure: (...args) => {
|
||||
const {width, height} = measureFunction(...args);
|
||||
return {
|
||||
width: width ?? NaN,
|
||||
height: height ?? NaN,
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
patch(lib.Node.prototype, 'setMeasureFunc', function (original, measureFunc) {
|
||||
// This patch is just a convenience patch, since it helps write more
|
||||
// idiomatic source code (such as .setMeasureFunc(null))
|
||||
if (measureFunc) {
|
||||
return original.call(this, wrapMeasureFunction(measureFunc));
|
||||
} else {
|
||||
return this.unsetMeasureFunc();
|
||||
}
|
||||
});
|
||||
|
||||
function wrapDirtiedFunc(dirtiedFunction) {
|
||||
return lib.DirtiedCallback.implement({dirtied: dirtiedFunction});
|
||||
}
|
||||
|
||||
patch(lib.Node.prototype, 'setDirtiedFunc', function (original, dirtiedFunc) {
|
||||
original.call(this, wrapDirtiedFunc(dirtiedFunc));
|
||||
});
|
||||
|
||||
patch(lib.Config.prototype, 'free', function () {
|
||||
// Since we handle the memory allocation ourselves (via lib.Config.create),
|
||||
// we also need to handle the deallocation
|
||||
lib.Config.destroy(this);
|
||||
});
|
||||
|
||||
patch(lib.Node, 'create', (_, config) => {
|
||||
// We decide the constructor we want to call depending on the parameters
|
||||
return config
|
||||
? lib.Node.createWithConfig(config)
|
||||
: lib.Node.createDefault();
|
||||
});
|
||||
|
||||
patch(lib.Node.prototype, 'free', function () {
|
||||
// Since we handle the memory allocation ourselves (via lib.Node.create),
|
||||
// we also need to handle the deallocation
|
||||
lib.Node.destroy(this);
|
||||
});
|
||||
|
||||
patch(lib.Node.prototype, 'freeRecursive', function () {
|
||||
for (let t = 0, T = this.getChildCount(); t < T; ++t) {
|
||||
this.getChild(0).freeRecursive();
|
||||
}
|
||||
this.free();
|
||||
});
|
||||
|
||||
patch(
|
||||
lib.Node.prototype,
|
||||
'calculateLayout',
|
||||
function (original, width = NaN, height = NaN, direction = Direction.LTR) {
|
||||
// Just a small patch to add support for the function default parameters
|
||||
return original.call(this, width, height, direction);
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
Config: lib.Config,
|
||||
Node: lib.Node,
|
||||
...YGEnums,
|
||||
};
|
||||
}
|
@@ -5,8 +5,10 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {getMeasureCounter} from '../tools/MeasureCounter';
|
||||
import {Yoga, YGBENCHMARK} from '../tools/globals';
|
||||
import {getMeasureCounter} from '../tools/MeasureCounter.ts';
|
||||
import {YGBENCHMARK} from '../tools/globals.ts';
|
||||
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
const ITERATIONS = 2000;
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('align_baseline_parent_using_child_in_column_as_reference', () => {
|
||||
const config = Yoga.Config.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('border_start', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('margin_start', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('padding_start', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('dirtied', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('errata_all_contains_example_errata', () => {
|
||||
const config = Yoga.Config.create();
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
test('flex_basis_auto', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,9 +5,9 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
import {getMeasureCounterMax} from './tools/MeasureCounter';
|
||||
import {getMeasureCounterMax} from './tools/MeasureCounter.ts';
|
||||
|
||||
test('measure_once_single_flexible_child', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -5,8 +5,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Yoga} from './tools/globals';
|
||||
import {getMeasureCounter} from './tools/MeasureCounter';
|
||||
import Yoga from 'yoga-layout';
|
||||
import {getMeasureCounter} from './tools/MeasureCounter.ts';
|
||||
|
||||
test('dont_measure_single_grow_shrink_child', () => {
|
||||
const root = Yoga.Node.create();
|
||||
|
@@ -10,9 +10,6 @@
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import YogaAsmjs from 'yoga-layout/asmjs-sync';
|
||||
import YogaWasm from 'yoga-layout/wasm-sync';
|
||||
|
||||
const WARMUP_ITERATIONS = 3;
|
||||
const BENCHMARK_ITERATIONS = 10;
|
||||
|
||||
@@ -20,9 +17,7 @@ const testFiles = process.argv.slice(2);
|
||||
|
||||
const testResults = new Map<string, Map<string, number>>();
|
||||
|
||||
for (const type of ['asmjs', 'wasm']) {
|
||||
globalThis.Yoga = type === 'asmjs' ? YogaAsmjs : YogaWasm;
|
||||
|
||||
for (const type of ['wasm']) {
|
||||
for (const file of testFiles) {
|
||||
globalThis.YGBENCHMARK = (name: string, fn: () => void) => {
|
||||
let testEntry = testResults.get(name);
|
||||
@@ -42,10 +37,7 @@ for (const type of ['asmjs', 'wasm']) {
|
||||
};
|
||||
|
||||
const modulePath = path.resolve(file);
|
||||
|
||||
delete require.cache[require.resolve('../tools/globals')];
|
||||
delete require.cache[modulePath];
|
||||
require(modulePath);
|
||||
await import(modulePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAbsolutePositionTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignContentTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignItemsTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAlignSelfTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAndroidNewsFeed.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGAspectRatioTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGBorderTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGDimensionTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGDisplayTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexDirectionTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGFlexWrapTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGGapTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGJustifyContentTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGMarginTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGMinMaxDimensionTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGPaddingTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGRoundingTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
// @generated by gentest/gentest.rb from gentest/fixtures/YGSizeOverflowTest.html
|
||||
|
||||
import {Yoga} from "../tools/globals";
|
||||
import Yoga from 'yoga-layout';
|
||||
import {
|
||||
Align,
|
||||
Direction,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import type {MeasureFunction} from 'yoga-layout';
|
||||
import {Yoga} from './globals';
|
||||
import Yoga from 'yoga-layout';
|
||||
|
||||
export type MeasureCounter = {
|
||||
inc: MeasureFunction;
|
||||
|
@@ -5,23 +5,15 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type {Yoga} from 'yoga-layout';
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
var Yoga: Yoga | undefined;
|
||||
// eslint-disable-next-line no-var
|
||||
var YGBENCHMARK: (title: string, fn: () => void) => void;
|
||||
}
|
||||
|
||||
if (globalThis.Yoga === undefined) {
|
||||
throw new Error('Expected "Yoga" global to be set');
|
||||
}
|
||||
if (globalThis.YGBENCHMARK === undefined) {
|
||||
throw new Error('Expected "YGBENCHMARK" global to be set');
|
||||
}
|
||||
|
||||
const yoga = globalThis.Yoga;
|
||||
const benchmark = globalThis.YGBENCHMARK;
|
||||
|
||||
export {yoga as Yoga, benchmark as YGBENCHMARK};
|
||||
export {benchmark as YGBENCHMARK};
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2018",
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
@@ -11,15 +11,13 @@
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"baseUrl": ".",
|
||||
"moduleResolution": "nodenext",
|
||||
"allowImportingTsExtensions": true,
|
||||
"paths": {
|
||||
"yoga-layout": ["src"]
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
},
|
||||
"exclude": [
|
||||
"binaries/**/*",
|
||||
"build/**/*"
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"tests/**/*"
|
||||
]
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@ const config = {
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
sidebarPath: require.resolve('./sidebars.cjs'),
|
||||
editUrl: 'https://github.com/facebook/yoga/tree/main/website',
|
||||
},
|
||||
blog: {
|
@@ -11,7 +11,7 @@ import React, {Component} from 'react';
|
||||
import {Row, Col, Button, Tabs} from 'antd';
|
||||
import EditValue from './EditValue';
|
||||
import type {LayoutRecordType} from './LayoutRecord';
|
||||
import type {Direction} from 'yoga-layout/sync';
|
||||
import type {Direction} from 'yoga-layout';
|
||||
import InfoText from './InfoText';
|
||||
import './Editor.css';
|
||||
const TabPane = Tabs.TabPane;
|
||||
|
@@ -10,15 +10,8 @@
|
||||
import {Record, List} from 'immutable';
|
||||
import PositionRecord from './PositionRecord';
|
||||
import type {PositionRecordType} from './PositionRecord';
|
||||
import yoga from 'yoga-layout/sync';
|
||||
|
||||
import type {
|
||||
Align,
|
||||
Justify,
|
||||
FlexDirection,
|
||||
Wrap,
|
||||
PositionType,
|
||||
} from 'yoga-layout/sync';
|
||||
import {Align, Justify, FlexDirection, Wrap, PositionType} from 'yoga-layout';
|
||||
|
||||
export type LayoutRecordType = ReturnType<LayoutRecordFactory>;
|
||||
|
||||
@@ -50,11 +43,11 @@ export type LayoutRecordFactory = Record.Factory<{
|
||||
const r: LayoutRecordFactory = Record({
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
justifyContent: yoga.JUSTIFY_FLEX_START,
|
||||
alignItems: yoga.ALIGN_STRETCH,
|
||||
alignSelf: yoga.ALIGN_AUTO,
|
||||
alignContent: yoga.ALIGN_STRETCH,
|
||||
flexDirection: yoga.FLEX_DIRECTION_ROW,
|
||||
justifyContent: Justify.FlexStart,
|
||||
alignItems: Align.Stretch,
|
||||
alignSelf: Align.Auto,
|
||||
alignContent: Align.Stretch,
|
||||
flexDirection: FlexDirection.Row,
|
||||
padding: PositionRecord(),
|
||||
margin: PositionRecord(),
|
||||
border: PositionRecord(),
|
||||
@@ -64,8 +57,8 @@ const r: LayoutRecordFactory = Record({
|
||||
right: NaN,
|
||||
bottom: NaN,
|
||||
}),
|
||||
positionType: yoga.POSITION_TYPE_RELATIVE,
|
||||
flexWrap: yoga.WRAP_NO_WRAP,
|
||||
positionType: PositionType.Relative,
|
||||
flexWrap: Wrap.NoWrap,
|
||||
flexBasis: 'auto',
|
||||
flexGrow: 0,
|
||||
flexShrink: 1,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import Yoga from 'yoga-layout/sync';
|
||||
import Yoga from 'yoga-layout';
|
||||
import {Radio, Menu, Dropdown, Button, Icon} from 'antd';
|
||||
import './YogaEnumSelect.css';
|
||||
const RadioButton = Radio.Button;
|
||||
|
@@ -8,12 +8,12 @@
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import Yoga from 'yoga-layout/sync';
|
||||
import Yoga from 'yoga-layout';
|
||||
import PositionGuide from './PositionGuide';
|
||||
import PositionRecord from './PositionRecord';
|
||||
import LayoutRecord from './LayoutRecord';
|
||||
import type {LayoutRecordType} from './LayoutRecord';
|
||||
import {Direction, Display, Edge, Node, Wrap} from 'yoga-layout/sync';
|
||||
import {Direction, Display, Edge, Node, Wrap} from 'yoga-layout';
|
||||
|
||||
import './YogaNode.css';
|
||||
|
||||
|
@@ -5,19 +5,14 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.PlaygroundContainer {
|
||||
.PlaygroundContainer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.Playground {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
.playground-background {
|
||||
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||
linear-gradient(-90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||
@@ -41,6 +36,15 @@
|
||||
100px 100px, 100px 100px, 100px 100px;
|
||||
}
|
||||
|
||||
.Playground {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
animation: playground-content-fade-in-frames 50ms ease-in;
|
||||
}
|
||||
|
||||
.Playground > .YogaNode {
|
||||
margin: auto;
|
||||
position: static;
|
||||
@@ -72,3 +76,12 @@
|
||||
.ant-modal-content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@keyframes playground-content-fade-in-frames {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import {Direction} from 'yoga-layout/sync';
|
||||
import {Direction} from 'yoga-layout';
|
||||
import YogaNode from './YogaNode';
|
||||
import Editor from './Editor';
|
||||
import {List, setIn} from 'immutable';
|
||||
@@ -235,52 +235,58 @@ export default class Playground extends Component<Props, State> {
|
||||
: null;
|
||||
|
||||
const playground = (
|
||||
<div
|
||||
className={`Playground ${this.props.renderSidebar ? '' : 'standalone'}`}
|
||||
onMouseDown={this.onMouseDown}
|
||||
style={{height, maxHeight: height}}
|
||||
ref={ref => {
|
||||
this._containerRef = ref;
|
||||
}}>
|
||||
<YogaNode
|
||||
layoutDefinition={layoutDefinition}
|
||||
selectedNodePath={selectedNodePath}
|
||||
onClick={selectedNodePath => this.setState({selectedNodePath})}
|
||||
onDoubleClick={this.onAdd}
|
||||
direction={direction}
|
||||
showGuides={this.props.showGuides}
|
||||
/>
|
||||
{!this.props.renderSidebar && (
|
||||
<Sidebar>
|
||||
{this.state.selectedNodePath ? (
|
||||
<Editor
|
||||
node={selectedNode}
|
||||
selectedNodeIsRoot={
|
||||
selectedNodePath ? selectedNodePath.length === 0 : false
|
||||
}
|
||||
onChangeLayout={this.onChangeLayout}
|
||||
// @ts-ignore
|
||||
onChangeSetting={(key, value) => this.setState({[key]: value})}
|
||||
direction={direction}
|
||||
onRemove={
|
||||
selectedNodePath && selectedNodePath.length > 0
|
||||
? this.onRemove
|
||||
: undefined
|
||||
}
|
||||
onAdd={
|
||||
selectedNodePath &&
|
||||
selectedNodePath.length < this.props.maxDepth
|
||||
? this.onAdd
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="NoContent">
|
||||
Select a node to edit its properties
|
||||
</div>
|
||||
)}
|
||||
</Sidebar>
|
||||
)}
|
||||
<div className="playground-background">
|
||||
<div
|
||||
className={`Playground ${
|
||||
this.props.renderSidebar ? '' : 'standalone'
|
||||
}`}
|
||||
onMouseDown={this.onMouseDown}
|
||||
style={{height, maxHeight: height}}
|
||||
ref={ref => {
|
||||
this._containerRef = ref;
|
||||
}}>
|
||||
<YogaNode
|
||||
layoutDefinition={layoutDefinition}
|
||||
selectedNodePath={selectedNodePath}
|
||||
onClick={selectedNodePath => this.setState({selectedNodePath})}
|
||||
onDoubleClick={this.onAdd}
|
||||
direction={direction}
|
||||
showGuides={this.props.showGuides}
|
||||
/>
|
||||
{!this.props.renderSidebar && (
|
||||
<Sidebar>
|
||||
{this.state.selectedNodePath ? (
|
||||
<Editor
|
||||
node={selectedNode}
|
||||
selectedNodeIsRoot={
|
||||
selectedNodePath ? selectedNodePath.length === 0 : false
|
||||
}
|
||||
onChangeLayout={this.onChangeLayout}
|
||||
// @ts-ignore
|
||||
onChangeSetting={(key, value) =>
|
||||
this.setState({[key]: value})
|
||||
}
|
||||
direction={direction}
|
||||
onRemove={
|
||||
selectedNodePath && selectedNodePath.length > 0
|
||||
? this.onRemove
|
||||
: undefined
|
||||
}
|
||||
onAdd={
|
||||
selectedNodePath &&
|
||||
selectedNodePath.length < this.props.maxDepth
|
||||
? this.onAdd
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="NoContent">
|
||||
Select a node to edit its properties
|
||||
</div>
|
||||
)}
|
||||
</Sidebar>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@@ -28,3 +28,29 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.playgroundFallback {
|
||||
height: 500px;
|
||||
width: 100%;
|
||||
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||
linear-gradient(-90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||
linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
|
||||
linear-gradient(
|
||||
transparent 4px,
|
||||
#f5f5f5 4px,
|
||||
#f5f5f5 97px,
|
||||
transparent 97px
|
||||
),
|
||||
linear-gradient(-90deg, #e5e5e5 1px, transparent 1px),
|
||||
linear-gradient(
|
||||
-90deg,
|
||||
transparent 4px,
|
||||
#f5f5f5 4px,
|
||||
#f5f5f5 97px,
|
||||
transparent 97px
|
||||
),
|
||||
linear-gradient(#e5e5e5 1px, transparent 1px), #f5f5f5;
|
||||
background-size: 10px 10px, 10px 10px, 100px 100px, 100px 100px, 100px 100px,
|
||||
100px 100px, 100px 100px, 100px 100px;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {Suspense} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
@@ -34,6 +34,22 @@ function HomepageHeader() {
|
||||
);
|
||||
}
|
||||
|
||||
const LazyPlayground = React.lazy(() => import('../components/Playground'));
|
||||
|
||||
function ClientPlayground() {
|
||||
const fallback = <div className={styles.playgroundFallback} />;
|
||||
|
||||
return (
|
||||
<BrowserOnly fallback={fallback}>
|
||||
{() => (
|
||||
<Suspense fallback={fallback}>
|
||||
<LazyPlayground />
|
||||
</Suspense>
|
||||
)}
|
||||
</BrowserOnly>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
return (
|
||||
@@ -43,12 +59,7 @@ export default function Home(): JSX.Element {
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageFeatures />
|
||||
<BrowserOnly fallback={null}>
|
||||
{() => {
|
||||
const Playground = require('../components/Playground');
|
||||
return <Playground />;
|
||||
}}
|
||||
</BrowserOnly>
|
||||
<ClientPlayground />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
|
@@ -2,6 +2,10 @@
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
"baseUrl": ".",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user