Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Release #6954

Merged
merged 6 commits into from
Jul 25, 2024
Merged

Release #6954

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/plugin-i18n/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
"peerDependencies": {
"@ice/app": "^3.4.10",
"@ice/runtime": "^1.4.10"
"@ice/runtime": "^1.4.11"
},
"publishConfig": {
"access": "public"
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-intl/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @ice/plugin-intl

## 1.1.0

### Minor Changes

- 2626dcdc: feat: support the simple mode of intl solution

## 1.0.2

fix: compat with the navigator language return with underslash.
Expand Down
46 changes: 46 additions & 0 deletions packages/plugin-intl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,49 @@ function alertMessage() {
alert(intl.formatMessage({ id: 'app.welcome' }));
}
```

## Simple mode

Simple mode for remove the dependency of `react-intl`:

Define the plugin in `ice.config.mts`:

```ts
import { defineConfig } from '@ice/app';
import intl from '@ice/plugin-intl';

export default defineConfig({
plugins: [
// Add intlSolution to remove the dependency of react-intl
intl({ intlSolution: 'simple' }),
],
});
```

When you use the `simple` mode, you can only use the `intl.formateMessage` function to get the locale message:

```tsx
import { ice } from 'ice';

export default function Home() {
console.log(intl.formatMessage({ id: 'new' }));
return <h1>home</h1>;
}
```

Function `intl.formatMessage` is limited, you can only use the syntax below to get the locale message:

Simple Usage:

```tsx
intl.formatMessage({ id: 'app.welcome', defaultMessage: 'Welcome to my application!' });
intl.formatMessage('app.welcome');
```

With Variables:

```tsx
intl.formatMessage({ id: 'app.welcome' }, { name: 'icejs' });
```

> Caution: the message Syntax only support the pattern like `{name}`.
5 changes: 3 additions & 2 deletions packages/plugin-intl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/plugin-intl",
"version": "1.0.2",
"version": "1.1.0",
"description": "react intl plugin for ice.js 3.",
"files": [
"esm",
Expand All @@ -15,6 +15,7 @@
"exports": {
".": "./esm/index.js",
"./runtime": "./esm/runtime.js",
"./runtime-simple": "./esm/runtime-simple.js",
"./types": "./esm/types.js"
},
"sideEffects": false,
Expand All @@ -28,7 +29,7 @@
},
"devDependencies": {
"@ice/app": "^3.4.9",
"@ice/runtime": "^1.4.8",
"@ice/runtime": "^1.4.11",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0"
},
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-intl/runtime-simple.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './esm/runtime-simple';
19 changes: 14 additions & 5 deletions packages/plugin-intl/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ interface PluginOptions {
localeMessagesKey?: string;
defaultLocaleKey?: string;
useCDN?: boolean;
intlSolution?: 'react-intl' | 'simple';
}

const plugin: Plugin<PluginOptions> = ({
localeMessagesKey = '__LOCALE_MESSAGES__',
defaultLocaleKey = '__DEFAULT_LOCALE__',
useCDN = false,
intlSolution = 'react-intl',
} = {}) => ({
name: 'plugin-intl',
setup: ({ generator, context, createLogger, watch }) => {
Expand Down Expand Up @@ -83,12 +85,19 @@ const plugin: Plugin<PluginOptions> = ({
}

// Add intl export from ice.
generator.addExport({
specifier: ['useIntl', 'intl'],
source: '@ice/plugin-intl/runtime',
});
if (intlSolution === 'simple') {
generator.addExport({
specifier: ['intl'],
source: '@ice/plugin-intl/runtime-simple',
});
} else {
generator.addExport({
specifier: ['useIntl', 'intl'],
source: '@ice/plugin-intl/runtime',
});
}
},
runtime: '@ice/plugin-intl/runtime',
runtime: intlSolution === 'simple' ? '@ice/plugin-intl/runtime-simple' : '@ice/plugin-intl/runtime',
});

export default plugin;
15 changes: 15 additions & 0 deletions packages/plugin-intl/src/intl-until.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const EXPORT_NAME = 'locale';

export const getDefaultLocale = () => {
// @ts-ignore
const defaultLocale = (typeof window !== 'undefined' && window.__ICE_DEFAULT_LOCALE__) ||
(typeof navigator !== 'undefined' && navigator.language) ||
'zh-CN';
return defaultLocale.replace('_', '-');
};

export const getLocaleMessages = () => {
// @ts-ignore
const localeMessages = typeof window === 'undefined' ? global.__ICE_LOCALE_MESSAGES__ : window.__ICE_LOCALE_MESSAGES__;
return localeMessages || {};
};
46 changes: 46 additions & 0 deletions packages/plugin-intl/src/runtime-simple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { RuntimePlugin } from '@ice/runtime/types';
import { getDefaultLocale, getLocaleMessages, EXPORT_NAME } from './intl-until.js';

let currentLocale = getDefaultLocale();
let localeMessages = getLocaleMessages();

const runtime: RuntimePlugin = async ({
appContext,
}) => {
const { appExport } = appContext;
const { getLocale, ...l } = appExport?.[EXPORT_NAME] || {};
if (Object.keys(l)?.length > 0) {
console.error('The locale config is not supported in the simple mode.');
}
const locale = getLocale ? getLocale() : getDefaultLocale();
currentLocale = locale;
// Refresh locale messages for server side because of import hoisting.
localeMessages = getLocaleMessages();
};

interface MessageDescriptor {
id: string;
defaultMessage?: string;
}

const intl = {
formatMessage: (message: MessageDescriptor | string, values?: Record<string, string>) => {
let messageId = typeof message === 'string' ? message : message.id;
const defaultMessage = typeof message === 'string' ? message : message.defaultMessage;
let content = localeMessages?.[currentLocale]?.[messageId];
if (!content) {
console.error(`Message with id "${messageId}" not found in locale "${currentLocale}"`);
return defaultMessage || messageId;
}
if (values) {
Object.keys(values).forEach((key) => {
content = content.replace(new RegExp(`{${key}}`, 'g'), values[key]);
});
}
return content;
},
};

export { intl };

export default runtime;
16 changes: 1 addition & 15 deletions packages/plugin-intl/src/runtime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,11 @@ import * as React from 'react';
import { createIntl, createIntlCache, RawIntlProvider, useIntl } from 'react-intl';
import type { IntlShape } from 'react-intl';
import type { RuntimePlugin } from '@ice/runtime/types';
import { getDefaultLocale, getLocaleMessages, EXPORT_NAME } from './intl-until.js';
import type { LocaleConfig } from './types.js';

const EXPORT_NAME = 'locale';
const cache = createIntlCache();

const getDefaultLocale = () => {
// @ts-ignore
const defaultLocale = (typeof window !== 'undefined' && window.__ICE_DEFAULT_LOCALE__) ||
(typeof navigator !== 'undefined' && navigator.language) ||
'zh-CN';
return defaultLocale.replace('_', '-');
};

const getLocaleMessages = () => {
// @ts-ignore
const localeMessages = typeof window === 'undefined' ? global.__ICE_LOCALE_MESSAGES__ : window.__ICE_LOCALE_MESSAGES__;
return localeMessages || {};
};

const defaultLocale = getDefaultLocale();
let intl: IntlShape = createIntl({
locale: defaultLocale,
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-jsx-plus/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.0.4

### Patch Changes

- aaea501d: fix: allow decorators-legacy syntax in js file

## 1.0.3

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-jsx-plus/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/plugin-jsx-plus",
"version": "1.0.3",
"version": "1.0.4",
"description": "JSX Plus support for ice.js",
"license": "MIT",
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-jsx-plus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const babelTransformOptions = {
'topLevelAwait',
'classProperties',
'classPrivateMethods',
'decorators-legacy', // allowing decorators by default
],
generatorOpts: {
decoratorsBeforeExport: true,
Expand Down Expand Up @@ -107,7 +108,6 @@ const plugin: Plugin<JSXPlusOptions> = (options: JSXPlusOptions = {}) => ({
if (/\.tsx?$/.test(id)) {
// When routes file is a typescript file, add ts parser plugins.
options.parserOpts.plugins.push('typescript');
options.parserOpts.plugins.push('decorators-legacy'); // allowing decorators by default
}

const { code, map } = transformSync(source, options);
Expand Down
5 changes: 4 additions & 1 deletion packages/plugin-request/src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { AxiosRequestConfig } from 'axios';
import { request } from './request.js';

interface RequestResult<R, P extends any[]> extends Result<R, P> {
request: (...args: P) => Promise<R>;
request: Result<R, P>['run'];
requestAsync: Result<R, P>['runAsync'];
}

export function useRequest<TData, TParams extends any[] = []>(
Expand Down Expand Up @@ -35,6 +36,8 @@ export function useRequest<TData, TParams extends any[] = []>(
...req,
// Modify ahooks' useRequest `run` as `request`
request: req.run,
// Modify ahooks' useRequest `runAsync` as `requestAsync`
requestAsync: req.runAsync,
} as RequestResult<TData, TParams>;
}

Expand Down
6 changes: 6 additions & 0 deletions packages/runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @ice/runtime

## 1.4.11

### Patch Changes

- 7992d405: fix: throw error for better debugging

## 1.4.10

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/runtime",
"version": "1.4.10",
"version": "1.4.11",
"description": "Runtime module for ice.js",
"type": "module",
"types": "./esm/index.d.ts",
Expand Down
3 changes: 2 additions & 1 deletion packages/runtime/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export async function loadRouteModule(route: RouteModule, routeModulesCache = {}
return routeModule;
} catch (error) {
console.error(`Failed to load route module: ${id}.`);
console.error(error);
// Re-throw error for better debugging.
throw error;
}
}

Expand Down
25 changes: 14 additions & 11 deletions packages/runtime/tests/routes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,20 @@ describe('routes', () => {
});

it('load error module', async () => {
const routeModule = await loadRouteModules([{
id: 'error',
// @ts-ignore
lazy: async () => {
throw new Error('err');
return {};
},
}], {});
expect(routeModule).toStrictEqual({
error: undefined,
});
// `toThrowError` seems not working with async function.
try {
await loadRouteModules([{
id: 'error',
// @ts-ignore
lazy: async () => {
throw new Error('err');
return {};
},
}], {});
expect(true).toBe(false);
} catch (err) {
expect(true).toBe(true);
}
});

it('load async route', async () => {
Expand Down
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading