intlayer-editor 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +8 -8
  2. package/dist/cjs/client/ContentEditionLayout.cjs +19 -13
  3. package/dist/cjs/client/ContentEditionLayout.cjs.map +1 -1
  4. package/dist/cjs/client/ContentEditionLayout.d.ts +1 -0
  5. package/dist/cjs/client/ContentEditorProvider.cjs +47 -0
  6. package/dist/cjs/client/ContentEditorProvider.cjs.map +1 -0
  7. package/dist/cjs/client/ContentEditorProvider.d.ts +23 -0
  8. package/dist/cjs/client/ContentSelectorWrapper.cjs +14 -1
  9. package/dist/cjs/client/ContentSelectorWrapper.cjs.map +1 -1
  10. package/dist/cjs/client/DictionaryEditionDrawer/useEditedContentStore.d.ts +1 -1
  11. package/dist/cjs/client/index.cjs +3 -1
  12. package/dist/cjs/client/index.cjs.map +1 -1
  13. package/dist/cjs/client/index.d.ts +1 -0
  14. package/dist/cjs/server/processEdition.cjs +61 -63
  15. package/dist/cjs/server/processEdition.cjs.map +1 -1
  16. package/dist/esm/client/ContentEditionLayout.d.mts +1 -0
  17. package/dist/esm/client/ContentEditionLayout.mjs +19 -13
  18. package/dist/esm/client/ContentEditionLayout.mjs.map +1 -1
  19. package/dist/esm/client/ContentEditorProvider.d.mts +23 -0
  20. package/dist/esm/client/ContentEditorProvider.mjs +24 -0
  21. package/dist/esm/client/ContentEditorProvider.mjs.map +1 -0
  22. package/dist/esm/client/ContentSelectorWrapper.mjs +15 -2
  23. package/dist/esm/client/ContentSelectorWrapper.mjs.map +1 -1
  24. package/dist/esm/client/DictionaryEditionDrawer/useEditedContentStore.d.mts +1 -1
  25. package/dist/esm/client/index.d.mts +1 -0
  26. package/dist/esm/client/index.mjs +1 -0
  27. package/dist/esm/client/index.mjs.map +1 -1
  28. package/dist/esm/server/processEdition.mjs +61 -63
  29. package/dist/esm/server/processEdition.mjs.map +1 -1
  30. package/package.json +17 -17
package/README.md CHANGED
@@ -10,19 +10,19 @@ For more details on how to install the package, see the relevant section below:
10
10
 
11
11
  ### Integrating with Next.js
12
12
 
13
- For integration with Next.js, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_nextjs.md).
13
+ For integration with Next.js, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/docs/intlayer_with_nextjs_en.md).
14
14
 
15
15
  ### Integrating with Create React App
16
16
 
17
- For integration with Create React App, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_create_react_app.md).
17
+ For integration with Create React App, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/docs/intlayer_with_create_react_app_en.md).
18
18
 
19
19
  ### Integrating with Vite + React
20
20
 
21
- For integration with Vite + React, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_vite+react.md).
21
+ For integration with Vite + React, refer to the [setup guide](https://github.com/aypineau/intlayer/blob/main/docs/docs/intlayer_with_vite+react_en.md).
22
22
 
23
23
  ## How Intlayer Editor Works
24
24
 
25
- Each time you make a change using Intlayer Editor, the server automatically inserts your changes into your [Intlayer declaration files](https://github.com/aypineau/intlayer/blob/main/docs/content_declaration/get_started.md), wherever these files are declared in your project.
25
+ Each time you make a change using Intlayer Editor, the server automatically inserts your changes into your [Intlayer declaration files](https://github.com/aypineau/intlayer/blob/main/docs/docs/content_declaration/get_started_en.md), wherever these files are declared in your project.
26
26
 
27
27
  In this way, you don't have to worry about where the file is declared or about finding your key in your dictionary collection.
28
28
 
@@ -54,7 +54,7 @@ const config: IntlayerConfig = {
54
54
  };
55
55
  ```
56
56
 
57
- To see all available parameters, refer to the [configuration documentation](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md).
57
+ To see all available parameters, refer to the [configuration documentation](https://github.com/aypineau/intlayer/blob/main/docs/docs/configuration_en.md).
58
58
 
59
59
  ### Start Editing
60
60
 
@@ -64,7 +64,7 @@ You can also create a custom script in your `package.json` file:
64
64
 
65
65
  ```json5
66
66
  {
67
- "scripts": {
67
+ scripts: {
68
68
  "start:editor": "npx intlayer-editor start",
69
69
  },
70
70
  }
@@ -74,8 +74,8 @@ To start both the Next.js server and the Intlayer Editor simultaneously, you can
74
74
 
75
75
  ```json5
76
76
  {
77
- "scripts": {
78
- "dev": "next dev",
77
+ scripts: {
78
+ dev: "next dev",
79
79
  "start:editor": "npx intlayer-editor start",
80
80
  "dev:all": "concurrently \"npm run dev:nextjs\" \"npm run dev:intlayer-editor\"",
81
81
  },
@@ -22,25 +22,31 @@ __export(ContentEditionLayout_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(ContentEditionLayout_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_ContentEditorProvider = require('./ContentEditorProvider.cjs');
25
26
  var import_DictionaryEditionDrawer = require('./DictionaryEditionDrawer/index.cjs');
26
27
  var import_DictionaryListDrawer = require('./DictionaryListDrawer/index.cjs');
27
28
  const ContentEditionLayout = ({
28
29
  children,
29
30
  locale,
30
31
  setLocale,
31
- localeList
32
- }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
33
- children,
34
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
35
- import_DictionaryEditionDrawer.DictionaryEditionDrawerController,
36
- {
37
- locale,
38
- localeList,
39
- setLocale
40
- }
41
- ),
42
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_DictionaryListDrawer.DictionaryListDrawer, {})
43
- ] });
32
+ localeList,
33
+ editorEnabled = true
34
+ }) => {
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ContentEditorProvider.IntlayerEditorProvider, { editorEnabled, children: [
36
+ children,
37
+ editorEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
38
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
39
+ import_DictionaryEditionDrawer.DictionaryEditionDrawerController,
40
+ {
41
+ locale,
42
+ localeList,
43
+ setLocale
44
+ }
45
+ ),
46
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_DictionaryListDrawer.DictionaryListDrawer, {})
47
+ ] })
48
+ ] }) });
49
+ };
44
50
  // Annotate the CommonJS export names for ESM import in node:
45
51
  0 && (module.exports = {
46
52
  ContentEditionLayout
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/ContentEditionLayout.tsx"],"sourcesContent":["import type { Locales } from '@intlayer/config/client';\nimport type { FC, ReactNode } from 'react';\nimport { DictionaryEditionDrawerController } from './DictionaryEditionDrawer/index';\nimport { DictionaryListDrawer } from './DictionaryListDrawer/index';\n\nexport type ContentEditionLayoutProps = {\n children?: ReactNode;\n locale: Locales;\n localeList: Locales[];\n setLocale: (locale: Locales) => void;\n};\n\nexport const ContentEditionLayout: FC<ContentEditionLayoutProps> = ({\n children,\n locale,\n setLocale,\n localeList,\n}) => (\n <>\n {children}\n <DictionaryEditionDrawerController\n locale={locale}\n localeList={localeList}\n setLocale={setLocale}\n />\n <DictionaryListDrawer />\n </>\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBE;AAhBF,qCAAkD;AAClD,kCAAqC;AAS9B,MAAM,uBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MACE,4EACG;AAAA;AAAA,EACD;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAAA,EACA,4CAAC,oDAAqB;AAAA,GACxB;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/ContentEditionLayout.tsx"],"sourcesContent":["import type { Locales } from '@intlayer/config/client';\nimport type { FC, ReactNode } from 'react';\nimport { IntlayerEditorProvider } from './ContentEditorProvider';\nimport { DictionaryEditionDrawerController } from './DictionaryEditionDrawer/index';\nimport { DictionaryListDrawer } from './DictionaryListDrawer/index';\n\nexport type ContentEditionLayoutProps = {\n children?: ReactNode;\n locale: Locales;\n localeList: Locales[];\n setLocale: (locale: Locales) => void;\n editorEnabled?: boolean;\n};\n\nexport const ContentEditionLayout: FC<ContentEditionLayoutProps> = ({\n children,\n locale,\n setLocale,\n localeList,\n editorEnabled = true,\n}) => {\n return (\n <>\n <IntlayerEditorProvider editorEnabled={editorEnabled}>\n {children}\n\n {editorEnabled && (\n <>\n <DictionaryEditionDrawerController\n locale={locale}\n localeList={localeList}\n setLocale={setLocale}\n />\n <DictionaryListDrawer />\n </>\n )}\n </IntlayerEditorProvider>\n </>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BU;AAzBV,mCAAuC;AACvC,qCAAkD;AAClD,kCAAqC;AAU9B,MAAM,uBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAClB,MAAM;AACJ,SACE,2EACE,uDAAC,uDAAuB,eACrB;AAAA;AAAA,IAEA,iBACC,4EACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MACA,4CAAC,oDAAqB;AAAA,OACxB;AAAA,KAEJ,GACF;AAEJ;","names":[]}
@@ -6,6 +6,7 @@ type ContentEditionLayoutProps = {
6
6
  locale: Locales;
7
7
  localeList: Locales[];
8
8
  setLocale: (locale: Locales) => void;
9
+ editorEnabled?: boolean;
9
10
  };
10
11
  declare const ContentEditionLayout: FC<ContentEditionLayoutProps>;
11
12
 
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var ContentEditorProvider_exports = {};
21
+ __export(ContentEditorProvider_exports, {
22
+ IntlayerEditorContext: () => IntlayerEditorContext,
23
+ IntlayerEditorProvider: () => IntlayerEditorProvider,
24
+ useIntlayerEditorContext: () => useIntlayerEditorContext
25
+ });
26
+ module.exports = __toCommonJS(ContentEditorProvider_exports);
27
+ var import_jsx_runtime = require("react/jsx-runtime");
28
+ var import_client = require("@intlayer/config/client");
29
+ var import_react = require("react");
30
+ const IntlayerEditorContext = (0, import_react.createContext)({
31
+ editorEnabled: false
32
+ });
33
+ const useIntlayerEditorContext = () => (0, import_react.useContext)(IntlayerEditorContext);
34
+ const {
35
+ editor: { enabled }
36
+ } = (0, import_client.getConfiguration)();
37
+ const IntlayerEditorProvider = ({
38
+ children,
39
+ editorEnabled = enabled
40
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IntlayerEditorContext.Provider, { value: { editorEnabled }, children });
41
+ // Annotate the CommonJS export names for ESM import in node:
42
+ 0 && (module.exports = {
43
+ IntlayerEditorContext,
44
+ IntlayerEditorProvider,
45
+ useIntlayerEditorContext
46
+ });
47
+ //# sourceMappingURL=ContentEditorProvider.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/client/ContentEditorProvider.tsx"],"sourcesContent":["'use client';\n\nimport { getConfiguration } from '@intlayer/config/client';\nimport {\n type PropsWithChildren,\n createContext,\n useContext,\n type FC,\n} from 'react';\n\ntype IntlayerEditorValue = {\n editorEnabled: boolean;\n};\n\n/**\n * Context that store the current locale on the client side\n */\nexport const IntlayerEditorContext = createContext<IntlayerEditorValue>({\n editorEnabled: false,\n});\n\n/**\n * Hook that provides the current locale\n */\nexport const useIntlayerEditorContext = () => useContext(IntlayerEditorContext);\n\nexport type IntlayerEditorProviderProps = PropsWithChildren & {\n editorEnabled?: boolean;\n};\n\nconst {\n editor: { enabled },\n} = getConfiguration();\n\n/**\n * Provider that store the current locale on the client side\n */\nexport const IntlayerEditorProvider: FC<IntlayerEditorProviderProps> = ({\n children,\n editorEnabled = enabled,\n}) => (\n <IntlayerEditorContext.Provider value={{ editorEnabled }}>\n {children}\n </IntlayerEditorContext.Provider>\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCE;AAvCF,oBAAiC;AACjC,mBAKO;AASA,MAAM,4BAAwB,4BAAmC;AAAA,EACtE,eAAe;AACjB,CAAC;AAKM,MAAM,2BAA2B,UAAM,yBAAW,qBAAqB;AAM9E,MAAM;AAAA,EACJ,QAAQ,EAAE,QAAQ;AACpB,QAAI,gCAAiB;AAKd,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA,gBAAgB;AAClB,MACE,4CAAC,sBAAsB,UAAtB,EAA+B,OAAO,EAAE,cAAc,GACpD,UACH;","names":[]}
@@ -0,0 +1,23 @@
1
+ import * as react from 'react';
2
+ import { PropsWithChildren, FC } from 'react';
3
+
4
+ type IntlayerEditorValue = {
5
+ editorEnabled: boolean;
6
+ };
7
+ /**
8
+ * Context that store the current locale on the client side
9
+ */
10
+ declare const IntlayerEditorContext: react.Context<IntlayerEditorValue>;
11
+ /**
12
+ * Hook that provides the current locale
13
+ */
14
+ declare const useIntlayerEditorContext: () => IntlayerEditorValue;
15
+ type IntlayerEditorProviderProps = PropsWithChildren & {
16
+ editorEnabled?: boolean;
17
+ };
18
+ /**
19
+ * Provider that store the current locale on the client side
20
+ */
21
+ declare const IntlayerEditorProvider: FC<IntlayerEditorProviderProps>;
22
+
23
+ export { IntlayerEditorContext, IntlayerEditorProvider, type IntlayerEditorProviderProps, useIntlayerEditorContext };
@@ -26,6 +26,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
26
26
  var import_core = require("@intlayer/core");
27
27
  var import_design_system = require("@intlayer/design-system");
28
28
  var import_react = require("react");
29
+ var import_ContentEditorProvider = require('./ContentEditorProvider.cjs');
29
30
  var import_useDictionaryEditionDrawer = require('./DictionaryEditionDrawer/useDictionaryEditionDrawer.cjs');
30
31
  const ContentSelectorWrapper = ({
31
32
  children,
@@ -35,6 +36,7 @@ const ContentSelectorWrapper = ({
35
36
  }) => {
36
37
  const { open, getEditedContentValue, focusedContent, isOpen } = (0, import_useDictionaryEditionDrawer.useDictionaryEditionDrawer)(dictionaryId);
37
38
  const editedValue = getEditedContentValue(dictionaryPath, keyPath);
39
+ const { editorEnabled } = (0, import_react.useContext)(import_ContentEditorProvider.IntlayerEditorContext);
38
40
  const handleSelect = (0, import_react.useCallback)(
39
41
  () => open({
40
42
  dictionaryId,
@@ -44,7 +46,18 @@ const ContentSelectorWrapper = ({
44
46
  [dictionaryId, dictionaryPath, keyPath, open]
45
47
  );
46
48
  const isSelected = (isOpen && (focusedContent?.keyPath?.length ?? 0) > 0 && (0, import_core.isSameKeyPath)(focusedContent?.keyPath ?? [], keyPath)) ?? false;
47
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_design_system.ContentSelector, { onSelect: handleSelect, isSelecting: isSelected, children: editedValue ?? children });
49
+ if (!editorEnabled) {
50
+ return children;
51
+ }
52
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
53
+ import_design_system.ContentSelector,
54
+ {
55
+ onSelect: handleSelect,
56
+ isSelecting: isSelected,
57
+ popoverContent: "Long press to edit",
58
+ children: editedValue ?? children
59
+ }
60
+ );
48
61
  };
49
62
  // Annotate the CommonJS export names for ESM import in node:
50
63
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/ContentSelectorWrapper.tsx"],"sourcesContent":["'use client';\n\nimport { isSameKeyPath, type KeyPath } from '@intlayer/core';\nimport { ContentSelector } from '@intlayer/design-system';\nimport { useCallback, type FC, type ReactNode } from 'react';\nimport { useDictionaryEditionDrawer } from './DictionaryEditionDrawer/useDictionaryEditionDrawer';\n\ntype ContentSelectorWrapperProps = {\n children: ReactNode;\n dictionaryId: string;\n dictionaryPath: string;\n keyPath: KeyPath[];\n};\n\nexport const ContentSelectorWrapper: FC<ContentSelectorWrapperProps> = ({\n children,\n dictionaryId,\n dictionaryPath,\n keyPath,\n}) => {\n const { open, getEditedContentValue, focusedContent, isOpen } =\n useDictionaryEditionDrawer(dictionaryId);\n const editedValue = getEditedContentValue(dictionaryPath, keyPath);\n\n const handleSelect = useCallback(\n () =>\n open({\n dictionaryId,\n dictionaryPath,\n keyPath,\n }),\n [dictionaryId, dictionaryPath, keyPath, open]\n );\n\n const isSelected =\n (isOpen &&\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent?.keyPath ?? [], keyPath)) ??\n false;\n\n return (\n <ContentSelector onSelect={handleSelect} isSelecting={isSelected}>\n {editedValue ?? children}\n </ContentSelector>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCI;AAvCJ,kBAA4C;AAC5C,2BAAgC;AAChC,mBAAqD;AACrD,wCAA2C;AASpC,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,uBAAuB,gBAAgB,OAAO,QAC1D,8DAA2B,YAAY;AACzC,QAAM,cAAc,sBAAsB,gBAAgB,OAAO;AAEjE,QAAM,mBAAe;AAAA,IACnB,MACE,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,CAAC,cAAc,gBAAgB,SAAS,IAAI;AAAA,EAC9C;AAEA,QAAM,cACH,WACE,gBAAgB,SAAS,UAAU,KAAK,SACzC,2BAAc,gBAAgB,WAAW,CAAC,GAAG,OAAO,MACtD;AAEF,SACE,4CAAC,wCAAgB,UAAU,cAAc,aAAa,YACnD,yBAAe,UAClB;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/ContentSelectorWrapper.tsx"],"sourcesContent":["'use client';\n\nimport { isSameKeyPath, type KeyPath } from '@intlayer/core';\nimport { ContentSelector } from '@intlayer/design-system';\nimport { useCallback, useContext, type FC, type ReactNode } from 'react';\nimport { IntlayerEditorContext } from './ContentEditorProvider';\nimport { useDictionaryEditionDrawer } from './DictionaryEditionDrawer/useDictionaryEditionDrawer';\n\ntype ContentSelectorWrapperProps = {\n children: ReactNode;\n dictionaryId: string;\n dictionaryPath: string;\n keyPath: KeyPath[];\n};\n\nexport const ContentSelectorWrapper: FC<ContentSelectorWrapperProps> = ({\n children,\n dictionaryId,\n dictionaryPath,\n keyPath,\n}) => {\n const { open, getEditedContentValue, focusedContent, isOpen } =\n useDictionaryEditionDrawer(dictionaryId);\n const editedValue = getEditedContentValue(dictionaryPath, keyPath);\n const { editorEnabled } = useContext(IntlayerEditorContext);\n\n const handleSelect = useCallback(\n () =>\n open({\n dictionaryId,\n dictionaryPath,\n keyPath,\n }),\n [dictionaryId, dictionaryPath, keyPath, open]\n );\n\n const isSelected =\n (isOpen &&\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent?.keyPath ?? [], keyPath)) ??\n false;\n\n if (!editorEnabled) {\n return children;\n }\n\n return (\n <ContentSelector\n onSelect={handleSelect}\n isSelecting={isSelected}\n popoverContent=\"Long press to edit\"\n >\n {editedValue ?? children}\n </ContentSelector>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CI;AA7CJ,kBAA4C;AAC5C,2BAAgC;AAChC,mBAAiE;AACjE,mCAAsC;AACtC,wCAA2C;AASpC,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,uBAAuB,gBAAgB,OAAO,QAC1D,8DAA2B,YAAY;AACzC,QAAM,cAAc,sBAAsB,gBAAgB,OAAO;AACjE,QAAM,EAAE,cAAc,QAAI,yBAAW,kDAAqB;AAE1D,QAAM,mBAAe;AAAA,IACnB,MACE,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,CAAC,cAAc,gBAAgB,SAAS,IAAI;AAAA,EAC9C;AAEA,QAAM,cACH,WACE,gBAAgB,SAAS,UAAU,KAAK,SACzC,2BAAc,gBAAgB,WAAW,CAAC,GAAG,OAAO,MACtD;AAEF,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,aAAa;AAAA,MACb,gBAAe;AAAA,MAEd,yBAAe;AAAA;AAAA,EAClB;AAEJ;","names":[]}
@@ -17,7 +17,7 @@ declare const useEditedContentStore: zustand.UseBoundStore<Omit<zustand.StoreApi
17
17
  persist: {
18
18
  setOptions: (options: Partial<zustand_middleware.PersistOptions<EditedContentStore, EditedContentStore>>) => void;
19
19
  clearStorage: () => void;
20
- rehydrate: () => void | Promise<void>;
20
+ rehydrate: () => Promise<void> | void;
21
21
  hasHydrated: () => boolean;
22
22
  onHydrate: (fn: (state: EditedContentStore) => void) => () => void;
23
23
  onFinishHydration: (fn: (state: EditedContentStore) => void) => () => void;
@@ -20,12 +20,14 @@ __reExport(client_exports, require('./DictionaryListDrawer/index.cjs'), module.e
20
20
  __reExport(client_exports, require('./ContentEditionLayout.cjs'), module.exports);
21
21
  __reExport(client_exports, require('./useEditorServer.cjs'), module.exports);
22
22
  __reExport(client_exports, require('./renderContentEditor.cjs'), module.exports);
23
+ __reExport(client_exports, require('./ContentEditorProvider.cjs'), module.exports);
23
24
  // Annotate the CommonJS export names for ESM import in node:
24
25
  0 && (module.exports = {
25
26
  ...require('./DictionaryEditionDrawer/index.cjs'),
26
27
  ...require('./DictionaryListDrawer/index.cjs'),
27
28
  ...require('./ContentEditionLayout.cjs'),
28
29
  ...require('./useEditorServer.cjs'),
29
- ...require('./renderContentEditor.cjs')
30
+ ...require('./renderContentEditor.cjs'),
31
+ ...require('./ContentEditorProvider.cjs')
30
32
  });
31
33
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/index.ts"],"sourcesContent":["export * from './DictionaryEditionDrawer/index';\nexport * from './DictionaryListDrawer/index';\nexport * from './ContentEditionLayout';\nexport * from './useEditorServer';\nexport * from './renderContentEditor';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,2BAAc,4CAAd;AACA,2BAAc,yCADd;AAEA,2BAAc,mCAFd;AAGA,2BAAc,8BAHd;AAIA,2BAAc,kCAJd;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/index.ts"],"sourcesContent":["export * from './DictionaryEditionDrawer/index';\nexport * from './DictionaryListDrawer/index';\nexport * from './ContentEditionLayout';\nexport * from './useEditorServer';\nexport * from './renderContentEditor';\nexport * from './ContentEditorProvider';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,2BAAc,4CAAd;AACA,2BAAc,yCADd;AAEA,2BAAc,mCAFd;AAGA,2BAAc,8BAHd;AAIA,2BAAc,kCAJd;AAKA,2BAAc,oCALd;","names":[]}
@@ -6,6 +6,7 @@ export { dictionaryListDrawerIdentifier, useDictionaryListDrawer } from './Dicti
6
6
  export { ContentEditionLayout, ContentEditionLayoutProps } from './ContentEditionLayout.js';
7
7
  export { useEditorServer } from './useEditorServer.js';
8
8
  export { IntlayerEditorElementProps, renderIntlayerEditor } from './renderContentEditor.js';
9
+ export { IntlayerEditorContext, IntlayerEditorProvider, IntlayerEditorProviderProps, useIntlayerEditorContext } from './ContentEditorProvider.js';
9
10
  import '@intlayer/config/client';
10
11
  import 'react';
11
12
  import '@intlayer/core';
@@ -32,64 +32,54 @@ const { default: generate } = requireFunction("@babel/generator");
32
32
  const findNestedProperty = (obj, keyPath) => {
33
33
  let currentObj = obj;
34
34
  for (const key of keyPath) {
35
- let foundProperty;
36
- if (
37
- // if the keyPath is an object, select the related node
38
- key.type === "ObjectExpression"
39
- ) {
40
- const result = currentObj.properties.find(
41
- (prop) => "key" in prop && prop.key.name === key.key
42
- );
43
- if (result && "value" in result) {
44
- currentObj = result.value;
45
- foundProperty = result;
46
- } else {
47
- return void 0;
48
- }
49
- }
50
- if (
51
- // if the keyPath is an array, select the related node
52
- key.type === "ArrayExpression"
53
- ) {
54
- const result = currentObj.elements[key.key];
55
- currentObj = result;
56
- }
57
- if (
58
- // if the keypath is a translation or enumeration node, go across the function and select the related node
59
- Object.values(import_core.NodeType).includes(
60
- key.type
61
- )
62
- ) {
63
- const argument = currentObj.arguments[0];
64
- const identifierResult = argument.properties.find(
65
- (prop) => "key" in prop && prop.key.name === key.key
66
- );
67
- const stringResult = argument.properties.find(
68
- (prop) => "key" in prop && prop.key.value === key.key
69
- );
70
- if (stringResult) {
71
- if ("value" in stringResult) {
72
- currentObj = stringResult.value;
73
- }
74
- foundProperty = stringResult;
75
- } else if (identifierResult) {
76
- if ("name" in identifierResult) {
77
- currentObj = identifierResult.name;
78
- }
79
- foundProperty = identifierResult;
80
- } else {
81
- return void 0;
82
- }
83
- }
35
+ const nextProperty = getNextProperty(currentObj, key);
36
+ if (!nextProperty)
37
+ throw new Error("Could not find the specified key path.");
38
+ currentObj = nextProperty;
84
39
  }
85
40
  return currentObj;
86
41
  };
42
+ const getNextProperty = (obj, key) => {
43
+ if (key.type === "ObjectExpression") {
44
+ return findInObjectExpression(
45
+ obj,
46
+ key
47
+ );
48
+ }
49
+ if (key.type === "ArrayExpression") {
50
+ return obj.elements[key.key];
51
+ }
52
+ if (Object.values(import_core.NodeType).includes(key.type)) {
53
+ return findInTranslationOrEnumerationNode(
54
+ obj,
55
+ key
56
+ );
57
+ }
58
+ return void 0;
59
+ };
60
+ const findInObjectExpression = (obj, key) => {
61
+ const result = obj.properties.find(
62
+ (prop) => "key" in prop && prop.key.name === key.key
63
+ );
64
+ return result && "value" in result ? result.value : void 0;
65
+ };
66
+ const findInTranslationOrEnumerationNode = (obj, key) => {
67
+ const argument = obj.arguments[0];
68
+ const identifierResult = argument.properties.find(
69
+ (prop) => "key" in prop && prop.key.name === key.key
70
+ );
71
+ const stringResult = identifierResult.value;
72
+ return stringResult ? identifierResult : identifierResult && "name" in identifierResult ? identifierResult.name : void 0;
73
+ };
87
74
  const findAndUpdate = (objExpr, keyPath, newValue) => {
88
75
  const lastKey = keyPath[keyPath.length - 1];
89
76
  if (lastKey) {
90
77
  const propertyToUpdate = findNestedProperty(objExpr, keyPath);
91
- if (propertyToUpdate && "value" in propertyToUpdate) {
92
- propertyToUpdate.value = newValue;
78
+ if (!propertyToUpdate) {
79
+ throw new Error("Could not find the specified key path.");
80
+ }
81
+ if ("value" in propertyToUpdate) {
82
+ propertyToUpdate.value.value = newValue;
93
83
  }
94
84
  }
95
85
  };
@@ -135,21 +125,29 @@ const traverseNode = (node, keyPath, newValue) => {
135
125
  const processEdition = async (editedContent) => {
136
126
  for (const dictionaryPath of Object.keys(editedContent)) {
137
127
  const fileContent = (0, import_fs.readFileSync)(dictionaryPath, "utf-8");
138
- const parsed = (0, import_parser.parse)(fileContent, {
139
- sourceType: "module",
140
- plugins: ["jsx", "typescript"]
141
- });
128
+ const parsedBase = parseFileContent(fileContent);
129
+ const parsed = parseFileContent(fileContent);
142
130
  for (const { keyPath, newValue } of editedContent[dictionaryPath]) {
143
131
  traverseNode(parsed.program, keyPath, newValue);
144
132
  }
145
- const updatedContent = generate(parsed).code;
146
- if (fileContent === updatedContent) {
147
- console.info(`Could not find specified key path in ${dictionaryPath}.`);
148
- } else {
149
- const formattedContent = await (0, import_formatPrettier.format)(updatedContent);
150
- (0, import_fs.writeFileSync)(dictionaryPath, formattedContent, "utf-8");
151
- console.info("Updated the file successfully.");
152
- }
133
+ await writeUpdatedContent(dictionaryPath, parsedBase, parsed);
134
+ }
135
+ };
136
+ const parseFileContent = (fileContent) => (0, import_parser.parse)(fileContent, {
137
+ sourceType: "module",
138
+ plugins: ["jsx", "typescript"]
139
+ });
140
+ const writeUpdatedContent = async (dictionaryPath, parsedBase, parsed) => {
141
+ const baseContent = generate(parsedBase).code;
142
+ const updatedContent = generate(parsed).code;
143
+ if (baseContent === updatedContent) {
144
+ console.info(
145
+ `No change made on the dictionary - dictionaryPath: ${dictionaryPath}.`
146
+ );
147
+ } else {
148
+ const formattedContent = await (0, import_formatPrettier.format)(updatedContent);
149
+ (0, import_fs.writeFileSync)(dictionaryPath, formattedContent, "utf-8");
150
+ console.info("Updated the file successfully.");
153
151
  }
154
152
  };
155
153
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/processEdition.ts"],"sourcesContent":["/* eslint-disable sonarjs/cognitive-complexity */\nimport { readFileSync, writeFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport { parse } from '@babel/parser';\nimport type {\n ObjectExpression,\n VariableDeclarator,\n Program,\n Identifier,\n StringLiteral,\n AssignmentExpression,\n ObjectProperty,\n CallExpression,\n ObjectMethod,\n SpreadElement,\n ArrayExpression,\n PrivateName,\n} from '@babel/types';\nimport {\n NodeType,\n type KeyPath,\n type ArrayExpressionNode,\n type ObjectExpressionNode,\n type TranslationOrEnumerationNode,\n} from '@intlayer/core';\nimport type { EditedContent } from '../client/index';\nimport { format } from './formatPrettier';\n\nconst requireFunction =\n typeof import.meta.url === 'undefined'\n ? require\n : createRequire(import.meta.url);\n\nconst { default: generate } = requireFunction('@babel/generator');\n\ntype ObjectOrArrayExpression = ObjectExpression | ArrayExpression;\n\n/**\n * Helper function to find a nested property in an ObjectExpression based on a key path\n */\nconst findNestedProperty = (\n obj: ObjectOrArrayExpression,\n keyPath: KeyPath[]\n): ObjectOrArrayExpression | undefined => {\n let currentObj: ObjectOrArrayExpression = obj;\n\n for (const key of keyPath) {\n let foundProperty:\n | ObjectProperty\n | ObjectMethod\n | SpreadElement\n | undefined;\n\n if (\n // if the keyPath is an object, select the related node\n (key as ObjectExpressionNode).type === 'ObjectExpression'\n ) {\n const result = (currentObj as ObjectExpression).properties.find(\n (prop) =>\n 'key' in prop &&\n (prop.key as Identifier).name === (key as ObjectExpressionNode).key\n );\n\n if (result && 'value' in result) {\n currentObj = result.value as ObjectExpression;\n foundProperty = result;\n } else {\n return undefined;\n }\n }\n\n if (\n // if the keyPath is an array, select the related node\n (key as ArrayExpressionNode).type === 'ArrayExpression'\n ) {\n const result = (currentObj as ArrayExpression).elements[\n (key as ArrayExpressionNode).key\n ] as unknown as ObjectProperty;\n\n currentObj = result as unknown as ObjectExpression;\n }\n\n if (\n // if the keypath is a translation or enumeration node, go across the function and select the related node\n Object.values(NodeType).includes(\n (key as TranslationOrEnumerationNode).type\n )\n ) {\n const argument = (currentObj as unknown as CallExpression)\n .arguments[0] as ObjectExpression;\n\n const identifierResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n );\n\n const stringResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as StringLiteral).value === key.key\n );\n\n if (stringResult) {\n // Correspond to StringLiteral oject property (e.g., { 'key': 'value' })\n if ('value' in stringResult) {\n currentObj = stringResult.value as ObjectExpression;\n }\n foundProperty = stringResult;\n } else if (identifierResult) {\n // Correspond to Identifier object property (e.g., { key: 'value' })\n if ('name' in identifierResult) {\n currentObj = identifierResult.name as ObjectExpression;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n foundProperty = identifierResult;\n } else {\n return undefined;\n }\n }\n }\n\n return currentObj;\n};\n\n/**\n * Find and update specific content based on key path\n */\nconst findAndUpdate = (\n objExpr: ObjectExpression,\n keyPath: KeyPath[],\n newValue: string\n) => {\n const lastKey = keyPath[keyPath.length - 1]; // Get the last key in the path\n\n if (lastKey) {\n const propertyToUpdate = findNestedProperty(objExpr, keyPath); // Traverse the key path\n\n if (propertyToUpdate && 'value' in propertyToUpdate) {\n (propertyToUpdate as unknown as StringLiteral).value = newValue; // Update the value of the specified key\n }\n }\n};\n\n/**\n * Traverse the AST and update based on key path and new value\n */\nconst traverseNode = (node: Program, keyPath: KeyPath[], newValue: string) => {\n if (Array.isArray(node.body)) {\n (node.body as unknown as Program[]).forEach((subNode) =>\n traverseNode(subNode, keyPath, newValue)\n );\n } else if (node.body) {\n traverseNode(node.body, keyPath, newValue);\n }\n\n if (\n // For ES Module (e.g., `const variable = ...; export default variable`)\n 'declarations' in node\n ) {\n (node.declarations as VariableDeclarator[]).forEach((declaration) => {\n if (declaration.init?.type === 'ObjectExpression') {\n findAndUpdate(declaration.init, keyPath, newValue);\n }\n });\n }\n\n if (\n // For ES Module (e.g., `export default { ... }`)\n 'declaration' in node &&\n (node.declaration as ObjectExpression).type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n node.declaration as ObjectExpression,\n keyPath,\n newValue\n );\n }\n\n if (\n // For CommonJS (e.g., `module.exports = ...`)\n 'expression' in node &&\n (node.expression as AssignmentExpression).right.type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n (node.expression as AssignmentExpression).right as ObjectExpression,\n keyPath,\n newValue\n );\n }\n};\n\n/**\n * Edit the content of a file based on the key path and new value\n */\nexport const processEdition = async (editedContent: EditedContent) => {\n // Loop into each dictionary path\n for (const dictionaryPath of Object.keys(editedContent)) {\n // Read the file\n const fileContent = readFileSync(dictionaryPath, 'utf-8');\n\n // Parse the content with TypeScript support\n const parsed = parse(fileContent, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n // Loop into each key path and new value\n for (const { keyPath, newValue } of editedContent[dictionaryPath]) {\n // Update values based on key paths\n traverseNode(parsed.program, keyPath, newValue);\n }\n\n // Generate the updated code\n const updatedContent = generate(parsed).code;\n\n if (fileContent === updatedContent) {\n console.info(`Could not find specified key path in ${dictionaryPath}.`);\n } else {\n const formattedContent = await format(updatedContent);\n\n // Write back to the file\n writeFileSync(dictionaryPath, formattedContent, 'utf-8');\n\n console.info('Updated the file successfully.');\n }\n }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/server/processEdition.ts"],"sourcesContent":["/* eslint-disable sonarjs/cognitive-complexity */\nimport { readFileSync, writeFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport { parse } from '@babel/parser';\nimport type {\n ObjectExpression,\n VariableDeclarator,\n Program,\n Identifier,\n StringLiteral,\n AssignmentExpression,\n ObjectProperty,\n CallExpression,\n ArrayExpression,\n} from '@babel/types';\nimport {\n NodeType,\n type KeyPath,\n type ArrayExpressionNode,\n type ObjectExpressionNode,\n type TranslationOrEnumerationNode,\n} from '@intlayer/core';\nimport type { EditedContent } from '../client/index';\nimport { format } from './formatPrettier';\n\nconst requireFunction =\n typeof import.meta.url === 'undefined'\n ? require\n : createRequire(import.meta.url);\n\nconst { default: generate } = requireFunction('@babel/generator');\n\ntype ObjectOrArrayExpression = ObjectExpression | ArrayExpression;\n\n/**\n * Helper function to find a nested property in an ObjectExpression based on a key path\n */\nconst findNestedProperty = (\n obj: ObjectOrArrayExpression,\n keyPath: KeyPath[]\n): ObjectOrArrayExpression | undefined => {\n let currentObj: ObjectOrArrayExpression = obj;\n\n for (const key of keyPath) {\n const nextProperty = getNextProperty(currentObj, key);\n\n if (!nextProperty)\n throw new Error('Could not find the specified key path.');\n\n currentObj = nextProperty;\n }\n\n return currentObj;\n};\n\nconst getNextProperty = (\n obj: ObjectOrArrayExpression,\n key: KeyPath\n): ObjectOrArrayExpression | undefined => {\n if ((key as ObjectExpressionNode).type === 'ObjectExpression') {\n return findInObjectExpression(\n obj as ObjectExpression,\n key as ObjectExpressionNode\n );\n }\n\n if ((key as ArrayExpressionNode).type === 'ArrayExpression') {\n return (obj as ArrayExpression).elements[\n (key as ArrayExpressionNode).key\n ] as ObjectOrArrayExpression;\n }\n\n if (\n Object.values(NodeType).includes((key as TranslationOrEnumerationNode).type)\n ) {\n return findInTranslationOrEnumerationNode(\n obj as unknown as CallExpression,\n key as TranslationOrEnumerationNode\n );\n }\n\n return undefined;\n};\n\nconst findInObjectExpression = (\n obj: ObjectExpression,\n key: ObjectExpressionNode\n): ObjectOrArrayExpression | undefined => {\n const result = obj.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n );\n\n return result && 'value' in result\n ? (result.value as ObjectOrArrayExpression)\n : undefined;\n};\n\nconst findInTranslationOrEnumerationNode = (\n obj: CallExpression,\n key: TranslationOrEnumerationNode\n): ObjectOrArrayExpression | undefined => {\n const argument = obj.arguments[0] as ObjectExpression;\n const identifierResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n ) as ObjectProperty;\n\n const stringResult = identifierResult.value as StringLiteral;\n\n return stringResult\n ? (identifierResult as unknown as ObjectOrArrayExpression)\n : identifierResult && 'name' in identifierResult\n ? (identifierResult.name as ObjectOrArrayExpression)\n : undefined;\n};\n\n/**\n * Find and update specific content based on key path\n */\nconst findAndUpdate = (\n objExpr: ObjectExpression,\n keyPath: KeyPath[],\n newValue: string\n) => {\n const lastKey = keyPath[keyPath.length - 1]; // Get the last key in the path\n\n if (lastKey) {\n const propertyToUpdate = findNestedProperty(objExpr, keyPath); // Traverse the key path\n\n if (!propertyToUpdate) {\n throw new Error('Could not find the specified key path.');\n }\n\n if ('value' in propertyToUpdate) {\n (propertyToUpdate.value as StringLiteral).value = newValue; // Update the value of the specified key\n }\n }\n};\n\n/**\n * Traverse the AST and update based on key path and new value\n */\nconst traverseNode = (node: Program, keyPath: KeyPath[], newValue: string) => {\n if (Array.isArray(node.body)) {\n node.body.forEach((subNode) =>\n traverseNode(subNode as unknown as Program, keyPath, newValue)\n );\n } else if (node.body) {\n traverseNode(node.body as Program, keyPath, newValue);\n }\n\n if (\n // For ES Module (e.g., `const variable = ...; export default variable`)\n 'declarations' in node\n ) {\n (node.declarations as VariableDeclarator[]).forEach((declaration) => {\n if (declaration.init?.type === 'ObjectExpression') {\n findAndUpdate(declaration.init, keyPath, newValue);\n }\n });\n }\n\n if (\n // For ES Module (e.g., `export default { ... }`)\n 'declaration' in node &&\n (node.declaration as ObjectExpression).type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n node.declaration as ObjectExpression,\n keyPath,\n newValue\n );\n }\n\n if (\n // For CommonJS (e.g., `module.exports = ...`)\n 'expression' in node &&\n (node.expression as AssignmentExpression).right.type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n (node.expression as AssignmentExpression).right as ObjectExpression,\n keyPath,\n newValue\n );\n }\n};\n\n/**\n * Edit the content of a file based on the key path and new value\n */\nexport const processEdition = async (editedContent: EditedContent) => {\n for (const dictionaryPath of Object.keys(editedContent)) {\n const fileContent = readFileSync(dictionaryPath, 'utf-8');\n const parsedBase = parseFileContent(fileContent);\n const parsed = parseFileContent(fileContent);\n\n for (const { keyPath, newValue } of editedContent[dictionaryPath]) {\n traverseNode(parsed.program, keyPath, newValue);\n }\n\n await writeUpdatedContent(dictionaryPath, parsedBase, parsed);\n }\n};\n\nconst parseFileContent = (fileContent: string) =>\n parse(fileContent, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\nconst writeUpdatedContent = async (\n dictionaryPath: string,\n parsedBase: ReturnType<typeof parseFileContent>,\n parsed: ReturnType<typeof parseFileContent>\n) => {\n const baseContent = generate(parsedBase).code;\n const updatedContent = generate(parsed).code;\n\n if (baseContent === updatedContent) {\n console.info(\n `No change made on the dictionary - dictionaryPath: ${dictionaryPath}.`\n );\n } else {\n const formattedContent = await format(updatedContent);\n writeFileSync(dictionaryPath, formattedContent, 'utf-8');\n console.info('Updated the file successfully.');\n }\n};\n"],"mappings":"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","names":[]}
@@ -6,6 +6,7 @@ type ContentEditionLayoutProps = {
6
6
  locale: Locales;
7
7
  localeList: Locales[];
8
8
  setLocale: (locale: Locales) => void;
9
+ editorEnabled?: boolean;
9
10
  };
10
11
  declare const ContentEditionLayout: FC<ContentEditionLayoutProps>;
11
12
 
@@ -1,23 +1,29 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { IntlayerEditorProvider } from './ContentEditorProvider.mjs';
2
3
  import { DictionaryEditionDrawerController } from './DictionaryEditionDrawer/index.mjs';
3
4
  import { DictionaryListDrawer } from './DictionaryListDrawer/index.mjs';
4
5
  const ContentEditionLayout = ({
5
6
  children,
6
7
  locale,
7
8
  setLocale,
8
- localeList
9
- }) => /* @__PURE__ */ jsxs(Fragment, { children: [
10
- children,
11
- /* @__PURE__ */ jsx(
12
- DictionaryEditionDrawerController,
13
- {
14
- locale,
15
- localeList,
16
- setLocale
17
- }
18
- ),
19
- /* @__PURE__ */ jsx(DictionaryListDrawer, {})
20
- ] });
9
+ localeList,
10
+ editorEnabled = true
11
+ }) => {
12
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(IntlayerEditorProvider, { editorEnabled, children: [
13
+ children,
14
+ editorEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
15
+ /* @__PURE__ */ jsx(
16
+ DictionaryEditionDrawerController,
17
+ {
18
+ locale,
19
+ localeList,
20
+ setLocale
21
+ }
22
+ ),
23
+ /* @__PURE__ */ jsx(DictionaryListDrawer, {})
24
+ ] })
25
+ ] }) });
26
+ };
21
27
  export {
22
28
  ContentEditionLayout
23
29
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/ContentEditionLayout.tsx"],"sourcesContent":["import type { Locales } from '@intlayer/config/client';\nimport type { FC, ReactNode } from 'react';\nimport { DictionaryEditionDrawerController } from './DictionaryEditionDrawer/index';\nimport { DictionaryListDrawer } from './DictionaryListDrawer/index';\n\nexport type ContentEditionLayoutProps = {\n children?: ReactNode;\n locale: Locales;\n localeList: Locales[];\n setLocale: (locale: Locales) => void;\n};\n\nexport const ContentEditionLayout: FC<ContentEditionLayoutProps> = ({\n children,\n locale,\n setLocale,\n localeList,\n}) => (\n <>\n {children}\n <DictionaryEditionDrawerController\n locale={locale}\n localeList={localeList}\n setLocale={setLocale}\n />\n <DictionaryListDrawer />\n </>\n);\n"],"mappings":"AAkBE,mBAEE,KAFF;AAhBF,SAAS,yCAAyC;AAClD,SAAS,4BAA4B;AAS9B,MAAM,uBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MACE,iCACG;AAAA;AAAA,EACD;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAAA,EACA,oBAAC,wBAAqB;AAAA,GACxB;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/ContentEditionLayout.tsx"],"sourcesContent":["import type { Locales } from '@intlayer/config/client';\nimport type { FC, ReactNode } from 'react';\nimport { IntlayerEditorProvider } from './ContentEditorProvider';\nimport { DictionaryEditionDrawerController } from './DictionaryEditionDrawer/index';\nimport { DictionaryListDrawer } from './DictionaryListDrawer/index';\n\nexport type ContentEditionLayoutProps = {\n children?: ReactNode;\n locale: Locales;\n localeList: Locales[];\n setLocale: (locale: Locales) => void;\n editorEnabled?: boolean;\n};\n\nexport const ContentEditionLayout: FC<ContentEditionLayoutProps> = ({\n children,\n locale,\n setLocale,\n localeList,\n editorEnabled = true,\n}) => {\n return (\n <>\n <IntlayerEditorProvider editorEnabled={editorEnabled}>\n {children}\n\n {editorEnabled && (\n <>\n <DictionaryEditionDrawerController\n locale={locale}\n localeList={localeList}\n setLocale={setLocale}\n />\n <DictionaryListDrawer />\n </>\n )}\n </IntlayerEditorProvider>\n </>\n );\n};\n"],"mappings":"AA2BU,mBACE,KADF;AAzBV,SAAS,8BAA8B;AACvC,SAAS,yCAAyC;AAClD,SAAS,4BAA4B;AAU9B,MAAM,uBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAClB,MAAM;AACJ,SACE,gCACE,+BAAC,0BAAuB,eACrB;AAAA;AAAA,IAEA,iBACC,iCACE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MACA,oBAAC,wBAAqB;AAAA,OACxB;AAAA,KAEJ,GACF;AAEJ;","names":[]}
@@ -0,0 +1,23 @@
1
+ import * as react from 'react';
2
+ import { PropsWithChildren, FC } from 'react';
3
+
4
+ type IntlayerEditorValue = {
5
+ editorEnabled: boolean;
6
+ };
7
+ /**
8
+ * Context that store the current locale on the client side
9
+ */
10
+ declare const IntlayerEditorContext: react.Context<IntlayerEditorValue>;
11
+ /**
12
+ * Hook that provides the current locale
13
+ */
14
+ declare const useIntlayerEditorContext: () => IntlayerEditorValue;
15
+ type IntlayerEditorProviderProps = PropsWithChildren & {
16
+ editorEnabled?: boolean;
17
+ };
18
+ /**
19
+ * Provider that store the current locale on the client side
20
+ */
21
+ declare const IntlayerEditorProvider: FC<IntlayerEditorProviderProps>;
22
+
23
+ export { IntlayerEditorContext, IntlayerEditorProvider, type IntlayerEditorProviderProps, useIntlayerEditorContext };
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { getConfiguration } from "@intlayer/config/client";
4
+ import {
5
+ createContext,
6
+ useContext
7
+ } from "react";
8
+ const IntlayerEditorContext = createContext({
9
+ editorEnabled: false
10
+ });
11
+ const useIntlayerEditorContext = () => useContext(IntlayerEditorContext);
12
+ const {
13
+ editor: { enabled }
14
+ } = getConfiguration();
15
+ const IntlayerEditorProvider = ({
16
+ children,
17
+ editorEnabled = enabled
18
+ }) => /* @__PURE__ */ jsx(IntlayerEditorContext.Provider, { value: { editorEnabled }, children });
19
+ export {
20
+ IntlayerEditorContext,
21
+ IntlayerEditorProvider,
22
+ useIntlayerEditorContext
23
+ };
24
+ //# sourceMappingURL=ContentEditorProvider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/client/ContentEditorProvider.tsx"],"sourcesContent":["'use client';\n\nimport { getConfiguration } from '@intlayer/config/client';\nimport {\n type PropsWithChildren,\n createContext,\n useContext,\n type FC,\n} from 'react';\n\ntype IntlayerEditorValue = {\n editorEnabled: boolean;\n};\n\n/**\n * Context that store the current locale on the client side\n */\nexport const IntlayerEditorContext = createContext<IntlayerEditorValue>({\n editorEnabled: false,\n});\n\n/**\n * Hook that provides the current locale\n */\nexport const useIntlayerEditorContext = () => useContext(IntlayerEditorContext);\n\nexport type IntlayerEditorProviderProps = PropsWithChildren & {\n editorEnabled?: boolean;\n};\n\nconst {\n editor: { enabled },\n} = getConfiguration();\n\n/**\n * Provider that store the current locale on the client side\n */\nexport const IntlayerEditorProvider: FC<IntlayerEditorProviderProps> = ({\n children,\n editorEnabled = enabled,\n}) => (\n <IntlayerEditorContext.Provider value={{ editorEnabled }}>\n {children}\n </IntlayerEditorContext.Provider>\n);\n"],"mappings":";AAyCE;AAvCF,SAAS,wBAAwB;AACjC;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AASA,MAAM,wBAAwB,cAAmC;AAAA,EACtE,eAAe;AACjB,CAAC;AAKM,MAAM,2BAA2B,MAAM,WAAW,qBAAqB;AAM9E,MAAM;AAAA,EACJ,QAAQ,EAAE,QAAQ;AACpB,IAAI,iBAAiB;AAKd,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA,gBAAgB;AAClB,MACE,oBAAC,sBAAsB,UAAtB,EAA+B,OAAO,EAAE,cAAc,GACpD,UACH;","names":[]}
@@ -2,7 +2,8 @@
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { isSameKeyPath } from "@intlayer/core";
4
4
  import { ContentSelector } from "@intlayer/design-system";
5
- import { useCallback } from "react";
5
+ import { useCallback, useContext } from "react";
6
+ import { IntlayerEditorContext } from './ContentEditorProvider.mjs';
6
7
  import { useDictionaryEditionDrawer } from './DictionaryEditionDrawer/useDictionaryEditionDrawer.mjs';
7
8
  const ContentSelectorWrapper = ({
8
9
  children,
@@ -12,6 +13,7 @@ const ContentSelectorWrapper = ({
12
13
  }) => {
13
14
  const { open, getEditedContentValue, focusedContent, isOpen } = useDictionaryEditionDrawer(dictionaryId);
14
15
  const editedValue = getEditedContentValue(dictionaryPath, keyPath);
16
+ const { editorEnabled } = useContext(IntlayerEditorContext);
15
17
  const handleSelect = useCallback(
16
18
  () => open({
17
19
  dictionaryId,
@@ -21,7 +23,18 @@ const ContentSelectorWrapper = ({
21
23
  [dictionaryId, dictionaryPath, keyPath, open]
22
24
  );
23
25
  const isSelected = (isOpen && (focusedContent?.keyPath?.length ?? 0) > 0 && isSameKeyPath(focusedContent?.keyPath ?? [], keyPath)) ?? false;
24
- return /* @__PURE__ */ jsx(ContentSelector, { onSelect: handleSelect, isSelecting: isSelected, children: editedValue ?? children });
26
+ if (!editorEnabled) {
27
+ return children;
28
+ }
29
+ return /* @__PURE__ */ jsx(
30
+ ContentSelector,
31
+ {
32
+ onSelect: handleSelect,
33
+ isSelecting: isSelected,
34
+ popoverContent: "Long press to edit",
35
+ children: editedValue ?? children
36
+ }
37
+ );
25
38
  };
26
39
  export {
27
40
  ContentSelectorWrapper
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/ContentSelectorWrapper.tsx"],"sourcesContent":["'use client';\n\nimport { isSameKeyPath, type KeyPath } from '@intlayer/core';\nimport { ContentSelector } from '@intlayer/design-system';\nimport { useCallback, type FC, type ReactNode } from 'react';\nimport { useDictionaryEditionDrawer } from './DictionaryEditionDrawer/useDictionaryEditionDrawer';\n\ntype ContentSelectorWrapperProps = {\n children: ReactNode;\n dictionaryId: string;\n dictionaryPath: string;\n keyPath: KeyPath[];\n};\n\nexport const ContentSelectorWrapper: FC<ContentSelectorWrapperProps> = ({\n children,\n dictionaryId,\n dictionaryPath,\n keyPath,\n}) => {\n const { open, getEditedContentValue, focusedContent, isOpen } =\n useDictionaryEditionDrawer(dictionaryId);\n const editedValue = getEditedContentValue(dictionaryPath, keyPath);\n\n const handleSelect = useCallback(\n () =>\n open({\n dictionaryId,\n dictionaryPath,\n keyPath,\n }),\n [dictionaryId, dictionaryPath, keyPath, open]\n );\n\n const isSelected =\n (isOpen &&\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent?.keyPath ?? [], keyPath)) ??\n false;\n\n return (\n <ContentSelector onSelect={handleSelect} isSelecting={isSelected}>\n {editedValue ?? children}\n </ContentSelector>\n );\n};\n"],"mappings":";AAyCI;AAvCJ,SAAS,qBAAmC;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAA4C;AACrD,SAAS,kCAAkC;AASpC,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,uBAAuB,gBAAgB,OAAO,IAC1D,2BAA2B,YAAY;AACzC,QAAM,cAAc,sBAAsB,gBAAgB,OAAO;AAEjE,QAAM,eAAe;AAAA,IACnB,MACE,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,CAAC,cAAc,gBAAgB,SAAS,IAAI;AAAA,EAC9C;AAEA,QAAM,cACH,WACE,gBAAgB,SAAS,UAAU,KAAK,KACzC,cAAc,gBAAgB,WAAW,CAAC,GAAG,OAAO,MACtD;AAEF,SACE,oBAAC,mBAAgB,UAAU,cAAc,aAAa,YACnD,yBAAe,UAClB;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/ContentSelectorWrapper.tsx"],"sourcesContent":["'use client';\n\nimport { isSameKeyPath, type KeyPath } from '@intlayer/core';\nimport { ContentSelector } from '@intlayer/design-system';\nimport { useCallback, useContext, type FC, type ReactNode } from 'react';\nimport { IntlayerEditorContext } from './ContentEditorProvider';\nimport { useDictionaryEditionDrawer } from './DictionaryEditionDrawer/useDictionaryEditionDrawer';\n\ntype ContentSelectorWrapperProps = {\n children: ReactNode;\n dictionaryId: string;\n dictionaryPath: string;\n keyPath: KeyPath[];\n};\n\nexport const ContentSelectorWrapper: FC<ContentSelectorWrapperProps> = ({\n children,\n dictionaryId,\n dictionaryPath,\n keyPath,\n}) => {\n const { open, getEditedContentValue, focusedContent, isOpen } =\n useDictionaryEditionDrawer(dictionaryId);\n const editedValue = getEditedContentValue(dictionaryPath, keyPath);\n const { editorEnabled } = useContext(IntlayerEditorContext);\n\n const handleSelect = useCallback(\n () =>\n open({\n dictionaryId,\n dictionaryPath,\n keyPath,\n }),\n [dictionaryId, dictionaryPath, keyPath, open]\n );\n\n const isSelected =\n (isOpen &&\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(focusedContent?.keyPath ?? [], keyPath)) ??\n false;\n\n if (!editorEnabled) {\n return children;\n }\n\n return (\n <ContentSelector\n onSelect={handleSelect}\n isSelecting={isSelected}\n popoverContent=\"Long press to edit\"\n >\n {editedValue ?? children}\n </ContentSelector>\n );\n};\n"],"mappings":";AA+CI;AA7CJ,SAAS,qBAAmC;AAC5C,SAAS,uBAAuB;AAChC,SAAS,aAAa,kBAA2C;AACjE,SAAS,6BAA6B;AACtC,SAAS,kCAAkC;AASpC,MAAM,yBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,MAAM,uBAAuB,gBAAgB,OAAO,IAC1D,2BAA2B,YAAY;AACzC,QAAM,cAAc,sBAAsB,gBAAgB,OAAO;AACjE,QAAM,EAAE,cAAc,IAAI,WAAW,qBAAqB;AAE1D,QAAM,eAAe;AAAA,IACnB,MACE,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH,CAAC,cAAc,gBAAgB,SAAS,IAAI;AAAA,EAC9C;AAEA,QAAM,cACH,WACE,gBAAgB,SAAS,UAAU,KAAK,KACzC,cAAc,gBAAgB,WAAW,CAAC,GAAG,OAAO,MACtD;AAEF,MAAI,CAAC,eAAe;AAClB,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,aAAa;AAAA,MACb,gBAAe;AAAA,MAEd,yBAAe;AAAA;AAAA,EAClB;AAEJ;","names":[]}
@@ -17,7 +17,7 @@ declare const useEditedContentStore: zustand.UseBoundStore<Omit<zustand.StoreApi
17
17
  persist: {
18
18
  setOptions: (options: Partial<zustand_middleware.PersistOptions<EditedContentStore, EditedContentStore>>) => void;
19
19
  clearStorage: () => void;
20
- rehydrate: () => void | Promise<void>;
20
+ rehydrate: () => Promise<void> | void;
21
21
  hasHydrated: () => boolean;
22
22
  onHydrate: (fn: (state: EditedContentStore) => void) => () => void;
23
23
  onFinishHydration: (fn: (state: EditedContentStore) => void) => () => void;
@@ -6,6 +6,7 @@ export { dictionaryListDrawerIdentifier, useDictionaryListDrawer } from './Dicti
6
6
  export { ContentEditionLayout, ContentEditionLayoutProps } from './ContentEditionLayout.mjs';
7
7
  export { useEditorServer } from './useEditorServer.mjs';
8
8
  export { IntlayerEditorElementProps, renderIntlayerEditor } from './renderContentEditor.mjs';
9
+ export { IntlayerEditorContext, IntlayerEditorProvider, IntlayerEditorProviderProps, useIntlayerEditorContext } from './ContentEditorProvider.mjs';
9
10
  import '@intlayer/config/client';
10
11
  import 'react';
11
12
  import '@intlayer/core';
@@ -3,4 +3,5 @@ export * from './DictionaryListDrawer/index.mjs';
3
3
  export * from './ContentEditionLayout.mjs';
4
4
  export * from './useEditorServer.mjs';
5
5
  export * from './renderContentEditor.mjs';
6
+ export * from './ContentEditorProvider.mjs';
6
7
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/index.ts"],"sourcesContent":["export * from './DictionaryEditionDrawer/index';\nexport * from './DictionaryListDrawer/index';\nexport * from './ContentEditionLayout';\nexport * from './useEditorServer';\nexport * from './renderContentEditor';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/index.ts"],"sourcesContent":["export * from './DictionaryEditionDrawer/index';\nexport * from './DictionaryListDrawer/index';\nexport * from './ContentEditionLayout';\nexport * from './useEditorServer';\nexport * from './renderContentEditor';\nexport * from './ContentEditorProvider';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -10,64 +10,54 @@ const { default: generate } = requireFunction("@babel/generator");
10
10
  const findNestedProperty = (obj, keyPath) => {
11
11
  let currentObj = obj;
12
12
  for (const key of keyPath) {
13
- let foundProperty;
14
- if (
15
- // if the keyPath is an object, select the related node
16
- key.type === "ObjectExpression"
17
- ) {
18
- const result = currentObj.properties.find(
19
- (prop) => "key" in prop && prop.key.name === key.key
20
- );
21
- if (result && "value" in result) {
22
- currentObj = result.value;
23
- foundProperty = result;
24
- } else {
25
- return void 0;
26
- }
27
- }
28
- if (
29
- // if the keyPath is an array, select the related node
30
- key.type === "ArrayExpression"
31
- ) {
32
- const result = currentObj.elements[key.key];
33
- currentObj = result;
34
- }
35
- if (
36
- // if the keypath is a translation or enumeration node, go across the function and select the related node
37
- Object.values(NodeType).includes(
38
- key.type
39
- )
40
- ) {
41
- const argument = currentObj.arguments[0];
42
- const identifierResult = argument.properties.find(
43
- (prop) => "key" in prop && prop.key.name === key.key
44
- );
45
- const stringResult = argument.properties.find(
46
- (prop) => "key" in prop && prop.key.value === key.key
47
- );
48
- if (stringResult) {
49
- if ("value" in stringResult) {
50
- currentObj = stringResult.value;
51
- }
52
- foundProperty = stringResult;
53
- } else if (identifierResult) {
54
- if ("name" in identifierResult) {
55
- currentObj = identifierResult.name;
56
- }
57
- foundProperty = identifierResult;
58
- } else {
59
- return void 0;
60
- }
61
- }
13
+ const nextProperty = getNextProperty(currentObj, key);
14
+ if (!nextProperty)
15
+ throw new Error("Could not find the specified key path.");
16
+ currentObj = nextProperty;
62
17
  }
63
18
  return currentObj;
64
19
  };
20
+ const getNextProperty = (obj, key) => {
21
+ if (key.type === "ObjectExpression") {
22
+ return findInObjectExpression(
23
+ obj,
24
+ key
25
+ );
26
+ }
27
+ if (key.type === "ArrayExpression") {
28
+ return obj.elements[key.key];
29
+ }
30
+ if (Object.values(NodeType).includes(key.type)) {
31
+ return findInTranslationOrEnumerationNode(
32
+ obj,
33
+ key
34
+ );
35
+ }
36
+ return void 0;
37
+ };
38
+ const findInObjectExpression = (obj, key) => {
39
+ const result = obj.properties.find(
40
+ (prop) => "key" in prop && prop.key.name === key.key
41
+ );
42
+ return result && "value" in result ? result.value : void 0;
43
+ };
44
+ const findInTranslationOrEnumerationNode = (obj, key) => {
45
+ const argument = obj.arguments[0];
46
+ const identifierResult = argument.properties.find(
47
+ (prop) => "key" in prop && prop.key.name === key.key
48
+ );
49
+ const stringResult = identifierResult.value;
50
+ return stringResult ? identifierResult : identifierResult && "name" in identifierResult ? identifierResult.name : void 0;
51
+ };
65
52
  const findAndUpdate = (objExpr, keyPath, newValue) => {
66
53
  const lastKey = keyPath[keyPath.length - 1];
67
54
  if (lastKey) {
68
55
  const propertyToUpdate = findNestedProperty(objExpr, keyPath);
69
- if (propertyToUpdate && "value" in propertyToUpdate) {
70
- propertyToUpdate.value = newValue;
56
+ if (!propertyToUpdate) {
57
+ throw new Error("Could not find the specified key path.");
58
+ }
59
+ if ("value" in propertyToUpdate) {
60
+ propertyToUpdate.value.value = newValue;
71
61
  }
72
62
  }
73
63
  };
@@ -113,21 +103,29 @@ const traverseNode = (node, keyPath, newValue) => {
113
103
  const processEdition = async (editedContent) => {
114
104
  for (const dictionaryPath of Object.keys(editedContent)) {
115
105
  const fileContent = readFileSync(dictionaryPath, "utf-8");
116
- const parsed = parse(fileContent, {
117
- sourceType: "module",
118
- plugins: ["jsx", "typescript"]
119
- });
106
+ const parsedBase = parseFileContent(fileContent);
107
+ const parsed = parseFileContent(fileContent);
120
108
  for (const { keyPath, newValue } of editedContent[dictionaryPath]) {
121
109
  traverseNode(parsed.program, keyPath, newValue);
122
110
  }
123
- const updatedContent = generate(parsed).code;
124
- if (fileContent === updatedContent) {
125
- console.info(`Could not find specified key path in ${dictionaryPath}.`);
126
- } else {
127
- const formattedContent = await format(updatedContent);
128
- writeFileSync(dictionaryPath, formattedContent, "utf-8");
129
- console.info("Updated the file successfully.");
130
- }
111
+ await writeUpdatedContent(dictionaryPath, parsedBase, parsed);
112
+ }
113
+ };
114
+ const parseFileContent = (fileContent) => parse(fileContent, {
115
+ sourceType: "module",
116
+ plugins: ["jsx", "typescript"]
117
+ });
118
+ const writeUpdatedContent = async (dictionaryPath, parsedBase, parsed) => {
119
+ const baseContent = generate(parsedBase).code;
120
+ const updatedContent = generate(parsed).code;
121
+ if (baseContent === updatedContent) {
122
+ console.info(
123
+ `No change made on the dictionary - dictionaryPath: ${dictionaryPath}.`
124
+ );
125
+ } else {
126
+ const formattedContent = await format(updatedContent);
127
+ writeFileSync(dictionaryPath, formattedContent, "utf-8");
128
+ console.info("Updated the file successfully.");
131
129
  }
132
130
  };
133
131
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/processEdition.ts"],"sourcesContent":["/* eslint-disable sonarjs/cognitive-complexity */\nimport { readFileSync, writeFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport { parse } from '@babel/parser';\nimport type {\n ObjectExpression,\n VariableDeclarator,\n Program,\n Identifier,\n StringLiteral,\n AssignmentExpression,\n ObjectProperty,\n CallExpression,\n ObjectMethod,\n SpreadElement,\n ArrayExpression,\n PrivateName,\n} from '@babel/types';\nimport {\n NodeType,\n type KeyPath,\n type ArrayExpressionNode,\n type ObjectExpressionNode,\n type TranslationOrEnumerationNode,\n} from '@intlayer/core';\nimport type { EditedContent } from '../client/index';\nimport { format } from './formatPrettier';\n\nconst requireFunction =\n typeof import.meta.url === 'undefined'\n ? require\n : createRequire(import.meta.url);\n\nconst { default: generate } = requireFunction('@babel/generator');\n\ntype ObjectOrArrayExpression = ObjectExpression | ArrayExpression;\n\n/**\n * Helper function to find a nested property in an ObjectExpression based on a key path\n */\nconst findNestedProperty = (\n obj: ObjectOrArrayExpression,\n keyPath: KeyPath[]\n): ObjectOrArrayExpression | undefined => {\n let currentObj: ObjectOrArrayExpression = obj;\n\n for (const key of keyPath) {\n let foundProperty:\n | ObjectProperty\n | ObjectMethod\n | SpreadElement\n | undefined;\n\n if (\n // if the keyPath is an object, select the related node\n (key as ObjectExpressionNode).type === 'ObjectExpression'\n ) {\n const result = (currentObj as ObjectExpression).properties.find(\n (prop) =>\n 'key' in prop &&\n (prop.key as Identifier).name === (key as ObjectExpressionNode).key\n );\n\n if (result && 'value' in result) {\n currentObj = result.value as ObjectExpression;\n foundProperty = result;\n } else {\n return undefined;\n }\n }\n\n if (\n // if the keyPath is an array, select the related node\n (key as ArrayExpressionNode).type === 'ArrayExpression'\n ) {\n const result = (currentObj as ArrayExpression).elements[\n (key as ArrayExpressionNode).key\n ] as unknown as ObjectProperty;\n\n currentObj = result as unknown as ObjectExpression;\n }\n\n if (\n // if the keypath is a translation or enumeration node, go across the function and select the related node\n Object.values(NodeType).includes(\n (key as TranslationOrEnumerationNode).type\n )\n ) {\n const argument = (currentObj as unknown as CallExpression)\n .arguments[0] as ObjectExpression;\n\n const identifierResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n );\n\n const stringResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as StringLiteral).value === key.key\n );\n\n if (stringResult) {\n // Correspond to StringLiteral oject property (e.g., { 'key': 'value' })\n if ('value' in stringResult) {\n currentObj = stringResult.value as ObjectExpression;\n }\n foundProperty = stringResult;\n } else if (identifierResult) {\n // Correspond to Identifier object property (e.g., { key: 'value' })\n if ('name' in identifierResult) {\n currentObj = identifierResult.name as ObjectExpression;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n foundProperty = identifierResult;\n } else {\n return undefined;\n }\n }\n }\n\n return currentObj;\n};\n\n/**\n * Find and update specific content based on key path\n */\nconst findAndUpdate = (\n objExpr: ObjectExpression,\n keyPath: KeyPath[],\n newValue: string\n) => {\n const lastKey = keyPath[keyPath.length - 1]; // Get the last key in the path\n\n if (lastKey) {\n const propertyToUpdate = findNestedProperty(objExpr, keyPath); // Traverse the key path\n\n if (propertyToUpdate && 'value' in propertyToUpdate) {\n (propertyToUpdate as unknown as StringLiteral).value = newValue; // Update the value of the specified key\n }\n }\n};\n\n/**\n * Traverse the AST and update based on key path and new value\n */\nconst traverseNode = (node: Program, keyPath: KeyPath[], newValue: string) => {\n if (Array.isArray(node.body)) {\n (node.body as unknown as Program[]).forEach((subNode) =>\n traverseNode(subNode, keyPath, newValue)\n );\n } else if (node.body) {\n traverseNode(node.body, keyPath, newValue);\n }\n\n if (\n // For ES Module (e.g., `const variable = ...; export default variable`)\n 'declarations' in node\n ) {\n (node.declarations as VariableDeclarator[]).forEach((declaration) => {\n if (declaration.init?.type === 'ObjectExpression') {\n findAndUpdate(declaration.init, keyPath, newValue);\n }\n });\n }\n\n if (\n // For ES Module (e.g., `export default { ... }`)\n 'declaration' in node &&\n (node.declaration as ObjectExpression).type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n node.declaration as ObjectExpression,\n keyPath,\n newValue\n );\n }\n\n if (\n // For CommonJS (e.g., `module.exports = ...`)\n 'expression' in node &&\n (node.expression as AssignmentExpression).right.type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n (node.expression as AssignmentExpression).right as ObjectExpression,\n keyPath,\n newValue\n );\n }\n};\n\n/**\n * Edit the content of a file based on the key path and new value\n */\nexport const processEdition = async (editedContent: EditedContent) => {\n // Loop into each dictionary path\n for (const dictionaryPath of Object.keys(editedContent)) {\n // Read the file\n const fileContent = readFileSync(dictionaryPath, 'utf-8');\n\n // Parse the content with TypeScript support\n const parsed = parse(fileContent, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n // Loop into each key path and new value\n for (const { keyPath, newValue } of editedContent[dictionaryPath]) {\n // Update values based on key paths\n traverseNode(parsed.program, keyPath, newValue);\n }\n\n // Generate the updated code\n const updatedContent = generate(parsed).code;\n\n if (fileContent === updatedContent) {\n console.info(`Could not find specified key path in ${dictionaryPath}.`);\n } else {\n const formattedContent = await format(updatedContent);\n\n // Write back to the file\n writeFileSync(dictionaryPath, formattedContent, 'utf-8');\n\n console.info('Updated the file successfully.');\n }\n }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/server/processEdition.ts"],"sourcesContent":["/* eslint-disable sonarjs/cognitive-complexity */\nimport { readFileSync, writeFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport { parse } from '@babel/parser';\nimport type {\n ObjectExpression,\n VariableDeclarator,\n Program,\n Identifier,\n StringLiteral,\n AssignmentExpression,\n ObjectProperty,\n CallExpression,\n ArrayExpression,\n} from '@babel/types';\nimport {\n NodeType,\n type KeyPath,\n type ArrayExpressionNode,\n type ObjectExpressionNode,\n type TranslationOrEnumerationNode,\n} from '@intlayer/core';\nimport type { EditedContent } from '../client/index';\nimport { format } from './formatPrettier';\n\nconst requireFunction =\n typeof import.meta.url === 'undefined'\n ? require\n : createRequire(import.meta.url);\n\nconst { default: generate } = requireFunction('@babel/generator');\n\ntype ObjectOrArrayExpression = ObjectExpression | ArrayExpression;\n\n/**\n * Helper function to find a nested property in an ObjectExpression based on a key path\n */\nconst findNestedProperty = (\n obj: ObjectOrArrayExpression,\n keyPath: KeyPath[]\n): ObjectOrArrayExpression | undefined => {\n let currentObj: ObjectOrArrayExpression = obj;\n\n for (const key of keyPath) {\n const nextProperty = getNextProperty(currentObj, key);\n\n if (!nextProperty)\n throw new Error('Could not find the specified key path.');\n\n currentObj = nextProperty;\n }\n\n return currentObj;\n};\n\nconst getNextProperty = (\n obj: ObjectOrArrayExpression,\n key: KeyPath\n): ObjectOrArrayExpression | undefined => {\n if ((key as ObjectExpressionNode).type === 'ObjectExpression') {\n return findInObjectExpression(\n obj as ObjectExpression,\n key as ObjectExpressionNode\n );\n }\n\n if ((key as ArrayExpressionNode).type === 'ArrayExpression') {\n return (obj as ArrayExpression).elements[\n (key as ArrayExpressionNode).key\n ] as ObjectOrArrayExpression;\n }\n\n if (\n Object.values(NodeType).includes((key as TranslationOrEnumerationNode).type)\n ) {\n return findInTranslationOrEnumerationNode(\n obj as unknown as CallExpression,\n key as TranslationOrEnumerationNode\n );\n }\n\n return undefined;\n};\n\nconst findInObjectExpression = (\n obj: ObjectExpression,\n key: ObjectExpressionNode\n): ObjectOrArrayExpression | undefined => {\n const result = obj.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n );\n\n return result && 'value' in result\n ? (result.value as ObjectOrArrayExpression)\n : undefined;\n};\n\nconst findInTranslationOrEnumerationNode = (\n obj: CallExpression,\n key: TranslationOrEnumerationNode\n): ObjectOrArrayExpression | undefined => {\n const argument = obj.arguments[0] as ObjectExpression;\n const identifierResult = argument.properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n ) as ObjectProperty;\n\n const stringResult = identifierResult.value as StringLiteral;\n\n return stringResult\n ? (identifierResult as unknown as ObjectOrArrayExpression)\n : identifierResult && 'name' in identifierResult\n ? (identifierResult.name as ObjectOrArrayExpression)\n : undefined;\n};\n\n/**\n * Find and update specific content based on key path\n */\nconst findAndUpdate = (\n objExpr: ObjectExpression,\n keyPath: KeyPath[],\n newValue: string\n) => {\n const lastKey = keyPath[keyPath.length - 1]; // Get the last key in the path\n\n if (lastKey) {\n const propertyToUpdate = findNestedProperty(objExpr, keyPath); // Traverse the key path\n\n if (!propertyToUpdate) {\n throw new Error('Could not find the specified key path.');\n }\n\n if ('value' in propertyToUpdate) {\n (propertyToUpdate.value as StringLiteral).value = newValue; // Update the value of the specified key\n }\n }\n};\n\n/**\n * Traverse the AST and update based on key path and new value\n */\nconst traverseNode = (node: Program, keyPath: KeyPath[], newValue: string) => {\n if (Array.isArray(node.body)) {\n node.body.forEach((subNode) =>\n traverseNode(subNode as unknown as Program, keyPath, newValue)\n );\n } else if (node.body) {\n traverseNode(node.body as Program, keyPath, newValue);\n }\n\n if (\n // For ES Module (e.g., `const variable = ...; export default variable`)\n 'declarations' in node\n ) {\n (node.declarations as VariableDeclarator[]).forEach((declaration) => {\n if (declaration.init?.type === 'ObjectExpression') {\n findAndUpdate(declaration.init, keyPath, newValue);\n }\n });\n }\n\n if (\n // For ES Module (e.g., `export default { ... }`)\n 'declaration' in node &&\n (node.declaration as ObjectExpression).type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n node.declaration as ObjectExpression,\n keyPath,\n newValue\n );\n }\n\n if (\n // For CommonJS (e.g., `module.exports = ...`)\n 'expression' in node &&\n (node.expression as AssignmentExpression).right.type === 'ObjectExpression'\n ) {\n return findAndUpdate(\n (node.expression as AssignmentExpression).right as ObjectExpression,\n keyPath,\n newValue\n );\n }\n};\n\n/**\n * Edit the content of a file based on the key path and new value\n */\nexport const processEdition = async (editedContent: EditedContent) => {\n for (const dictionaryPath of Object.keys(editedContent)) {\n const fileContent = readFileSync(dictionaryPath, 'utf-8');\n const parsedBase = parseFileContent(fileContent);\n const parsed = parseFileContent(fileContent);\n\n for (const { keyPath, newValue } of editedContent[dictionaryPath]) {\n traverseNode(parsed.program, keyPath, newValue);\n }\n\n await writeUpdatedContent(dictionaryPath, parsedBase, parsed);\n }\n};\n\nconst parseFileContent = (fileContent: string) =>\n parse(fileContent, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\nconst writeUpdatedContent = async (\n dictionaryPath: string,\n parsedBase: ReturnType<typeof parseFileContent>,\n parsed: ReturnType<typeof parseFileContent>\n) => {\n const baseContent = generate(parsedBase).code;\n const updatedContent = generate(parsed).code;\n\n if (baseContent === updatedContent) {\n console.info(\n `No change made on the dictionary - dictionaryPath: ${dictionaryPath}.`\n );\n } else {\n const formattedContent = await format(updatedContent);\n writeFileSync(dictionaryPath, formattedContent, 'utf-8');\n console.info('Updated the file successfully.');\n }\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intlayer-editor",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "private": false,
5
5
  "description": "IntLayer Editor is a tool that allow you to edit your IntLayer declaration files using a graphical interface.",
6
6
  "keywords": [
@@ -53,19 +53,19 @@
53
53
  "dependencies": {
54
54
  "@types/body-parser": "^1.19.5",
55
55
  "body-parser": "^1.20.2",
56
- "commander": "^12.0.0",
56
+ "commander": "^12.1.0",
57
57
  "express": "^4.19.2",
58
58
  "lucide-react": "^0.376.0",
59
59
  "magic-regexp": "^0.8.0",
60
- "react": "^18.2.0",
61
- "react-dom": "^18.2.0",
62
- "webpack": "^5.91.0",
60
+ "react": "^18.3.1",
61
+ "react-dom": "^18.3.1",
62
+ "webpack": "^5.92.1",
63
63
  "zustand": "^4.5.2",
64
- "@intlayer/config": "^2.0.1",
65
- "@intlayer/core": "^2.0.1",
66
- "@intlayer/design-system": "^2.0.1",
67
- "@intlayer/dictionaries-entry": "^2.0.1",
68
- "intlayer": "^2.0.1"
64
+ "@intlayer/config": "^2.0.2",
65
+ "@intlayer/core": "^2.0.2",
66
+ "@intlayer/design-system": "^2.0.2",
67
+ "@intlayer/dictionaries-entry": "^2.0.2",
68
+ "intlayer": "^2.0.2"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@babel/generator": "7.24.4",
@@ -75,15 +75,15 @@
75
75
  "@changesets/cli": "2.27.1",
76
76
  "@types/babel__generator": "^7.6.8",
77
77
  "@types/express": "^4.17.21",
78
- "@types/node": "^20.12.7",
79
- "@types/react": "^18.2.79",
80
- "@types/react-dom": "^18.2.25",
78
+ "@types/node": "^20.14.9",
79
+ "@types/react": "^18.3.3",
80
+ "@types/react-dom": "^18.3.0",
81
81
  "rimraf": "5.0.5",
82
82
  "ts-node": "^10.9.2",
83
- "tsup": "^8.0.2",
84
- "typescript": "^5.4.5",
85
- "@utils/eslint-config": "^1.0.1",
86
- "@utils/ts-config": "^1.0.1"
83
+ "tsup": "^8.1.0",
84
+ "typescript": "^5.5.2",
85
+ "@utils/eslint-config": "^1.0.2",
86
+ "@utils/ts-config": "^1.0.2"
87
87
  },
88
88
  "engines": {
89
89
  "node": ">=14.18"