Consolidate JavaScript Flavors (#1433)
Summary: Fixes https://github.com/facebook/yoga/issues/1417 This dramatically simplifies the matrix of Node vs web, ASM vs WASM, sync vs async compilation, or CommonJS vs ES Modules. We have one variant, using wasm, with ESModule top-level await to do async compilation. Web/node share the same binary, and we base64 encode the WASM into a wrapper JS file for compatibility with Node and bundlers. This has some downsides, like requiring an environment with top level await, but also has upsides, like a consistent, sync looking API compatible with older Yoga, and mitigating TypeScript issues with package exports and typings resolution. As part of this work I also removed `ts-node` from the toolchain (at the cost of a couple of config files needing to be vanilla JS). Pull Request resolved: https://github.com/facebook/yoga/pull/1433 Test Plan: 1. `yarn test` 2. `yarn lint` 3. `yarn tsc` 4. `yarn benchmark` 5. `yarn build` website-next 6. `yarn lint` website-next 7. Locally test website-next 8. Examine package artifact created by GitHub 9. All Automation passes Reviewed By: yungsters Differential Revision: D50453324 Pulled By: NickGerleman fbshipit-source-id: fe1192acc69e57fa69a1ff056dd7b5844d2198d5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b19a07cff9
commit
ef1d772447
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],
|
||||
{
|
||||
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,
|
||||
};
|
||||
}
|
@@ -7,9 +7,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 +24,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 +180,139 @@ export type Yoga = {
|
||||
};
|
||||
} & typeof YGEnums;
|
||||
|
||||
declare const wrapAsm: (assembly: unknown) => Yoga;
|
||||
export default wrapAsm;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
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';
|
||||
|
||||
|
@@ -12,12 +12,7 @@
|
||||
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,8 +235,11 @@ export default class Playground extends Component<Props, State> {
|
||||
: null;
|
||||
|
||||
const playground = (
|
||||
<div className="playground-background">
|
||||
<div
|
||||
className={`Playground ${this.props.renderSidebar ? '' : 'standalone'}`}
|
||||
className={`Playground ${
|
||||
this.props.renderSidebar ? '' : 'standalone'
|
||||
}`}
|
||||
onMouseDown={this.onMouseDown}
|
||||
style={{height, maxHeight: height}}
|
||||
ref={ref => {
|
||||
@@ -260,7 +263,9 @@ export default class Playground extends Component<Props, State> {
|
||||
}
|
||||
onChangeLayout={this.onChangeLayout}
|
||||
// @ts-ignore
|
||||
onChangeSetting={(key, value) => this.setState({[key]: value})}
|
||||
onChangeSetting={(key, value) =>
|
||||
this.setState({[key]: value})
|
||||
}
|
||||
direction={direction}
|
||||
onRemove={
|
||||
selectedNodePath && selectedNodePath.length > 0
|
||||
@@ -282,6 +287,7 @@ export default class Playground extends Component<Props, State> {
|
||||
</Sidebar>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (this.props.renderSidebar) {
|
||||
|
@@ -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