intlayer-editor 2.0.0
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.
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/bin/start-server.js +16 -0
- package/dist/cjs/client/ContentEditionLayout.cjs +46 -0
- package/dist/cjs/client/ContentEditionLayout.cjs.map +1 -0
- package/dist/cjs/client/ContentEditionLayout.d.ts +12 -0
- package/dist/cjs/client/ContentSelectorWrapper.cjs +49 -0
- package/dist/cjs/client/ContentSelectorWrapper.cjs.map +1 -0
- package/dist/cjs/client/ContentSelectorWrapper.d.ts +12 -0
- package/dist/cjs/client/EditionPanel/EditionPanel.cjs +101 -0
- package/dist/cjs/client/EditionPanel/EditionPanel.cjs.map +1 -0
- package/dist/cjs/client/EditionPanel/EditionPanel.d.ts +11 -0
- package/dist/cjs/client/EditionPanel/index.cjs +27 -0
- package/dist/cjs/client/EditionPanel/index.cjs.map +1 -0
- package/dist/cjs/client/EditionPanel/index.d.ts +9 -0
- package/dist/cjs/client/EditionPanel/useEditedContentStore.cjs +90 -0
- package/dist/cjs/client/EditionPanel/useEditedContentStore.cjs.map +1 -0
- package/dist/cjs/client/EditionPanel/useEditedContentStore.d.ts +28 -0
- package/dist/cjs/client/EditionPanel/useEditionPanelStore.cjs +33 -0
- package/dist/cjs/client/EditionPanel/useEditionPanelStore.cjs.map +1 -0
- package/dist/cjs/client/EditionPanel/useEditionPanelStore.d.ts +16 -0
- package/dist/cjs/client/index.cjs +29 -0
- package/dist/cjs/client/index.cjs.map +1 -0
- package/dist/cjs/client/index.d.ts +13 -0
- package/dist/cjs/client/renderContentSelector.cjs +39 -0
- package/dist/cjs/client/renderContentSelector.cjs.map +1 -0
- package/dist/cjs/client/renderContentSelector.d.ts +6 -0
- package/dist/cjs/client/useEditorServer.cjs +53 -0
- package/dist/cjs/client/useEditorServer.cjs.map +1 -0
- package/dist/cjs/client/useEditorServer.d.ts +5 -0
- package/dist/cjs/server/content-editor.cjs +156 -0
- package/dist/cjs/server/content-editor.cjs.map +1 -0
- package/dist/cjs/server/content-editor.d.ts +12 -0
- package/dist/cjs/server/index.cjs +68 -0
- package/dist/cjs/server/index.cjs.map +1 -0
- package/dist/cjs/server/index.d.ts +3 -0
- package/dist/esm/client/ContentEditionLayout.d.mts +12 -0
- package/dist/esm/client/ContentEditionLayout.mjs +22 -0
- package/dist/esm/client/ContentEditionLayout.mjs.map +1 -0
- package/dist/esm/client/ContentSelectorWrapper.d.mts +12 -0
- package/dist/esm/client/ContentSelectorWrapper.mjs +25 -0
- package/dist/esm/client/ContentSelectorWrapper.mjs.map +1 -0
- package/dist/esm/client/EditionPanel/EditionPanel.d.mts +11 -0
- package/dist/esm/client/EditionPanel/EditionPanel.mjs +72 -0
- package/dist/esm/client/EditionPanel/EditionPanel.mjs.map +1 -0
- package/dist/esm/client/EditionPanel/index.d.mts +9 -0
- package/dist/esm/client/EditionPanel/index.mjs +4 -0
- package/dist/esm/client/EditionPanel/index.mjs.map +1 -0
- package/dist/esm/client/EditionPanel/useEditedContentStore.d.mts +28 -0
- package/dist/esm/client/EditionPanel/useEditedContentStore.mjs +66 -0
- package/dist/esm/client/EditionPanel/useEditedContentStore.mjs.map +1 -0
- package/dist/esm/client/EditionPanel/useEditionPanelStore.d.mts +16 -0
- package/dist/esm/client/EditionPanel/useEditionPanelStore.mjs +9 -0
- package/dist/esm/client/EditionPanel/useEditionPanelStore.mjs.map +1 -0
- package/dist/esm/client/index.d.mts +13 -0
- package/dist/esm/client/index.mjs +5 -0
- package/dist/esm/client/index.mjs.map +1 -0
- package/dist/esm/client/renderContentSelector.d.mts +6 -0
- package/dist/esm/client/renderContentSelector.mjs +15 -0
- package/dist/esm/client/renderContentSelector.mjs.map +1 -0
- package/dist/esm/client/useEditorServer.d.mts +5 -0
- package/dist/esm/client/useEditorServer.mjs +29 -0
- package/dist/esm/client/useEditorServer.mjs.map +1 -0
- package/dist/esm/server/content-editor.d.mts +12 -0
- package/dist/esm/server/content-editor.mjs +123 -0
- package/dist/esm/server/content-editor.mjs.map +1 -0
- package/dist/esm/server/index.d.mts +3 -0
- package/dist/esm/server/index.mjs +34 -0
- package/dist/esm/server/index.mjs.map +1 -0
- package/package.json +109 -0
- package/src/client/ContentEditionLayout.tsx +26 -0
- package/src/client/ContentSelectorWrapper.tsx +38 -0
- package/src/client/EditionPanel/EditionPanel.tsx +90 -0
- package/src/client/EditionPanel/index.ts +3 -0
- package/src/client/EditionPanel/useEditedContentStore.ts +98 -0
- package/src/client/EditionPanel/useEditionPanelStore.ts +19 -0
- package/src/client/index.ts +4 -0
- package/src/client/renderContentSelector.tsx +17 -0
- package/src/client/useEditorServer.ts +31 -0
- package/src/server/content-editor.ts +209 -0
- package/src/server/index.ts +40 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
useRightDrawerStore,
|
|
5
|
+
RightDrawer,
|
|
6
|
+
DictionaryEditor,
|
|
7
|
+
LocaleSwitcher
|
|
8
|
+
} from "@intlayer/design-system";
|
|
9
|
+
import dictionaries from "@intlayer/dictionaries-entry";
|
|
10
|
+
import { useEffect } from "react";
|
|
11
|
+
import { useEditorServer } from '../useEditorServer.mjs';
|
|
12
|
+
import { useEditedContentStore } from './useEditedContentStore.mjs';
|
|
13
|
+
import { useEditionPanelStore } from './useEditionPanelStore.mjs';
|
|
14
|
+
const EditionPanel = ({
|
|
15
|
+
locale,
|
|
16
|
+
localeList,
|
|
17
|
+
setLocale
|
|
18
|
+
}) => {
|
|
19
|
+
const { open } = useRightDrawerStore();
|
|
20
|
+
const { focusedContent, setFocusedContent } = useEditionPanelStore();
|
|
21
|
+
const { editedContent, addEditedContent, clearEditedDictionaryContent } = useEditedContentStore();
|
|
22
|
+
const { editContentRequest } = useEditorServer();
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (focusedContent !== null) {
|
|
25
|
+
open();
|
|
26
|
+
}
|
|
27
|
+
}, [focusedContent, open]);
|
|
28
|
+
if (!focusedContent) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const dictionary = dictionaries[focusedContent.dictionaryId];
|
|
32
|
+
if (!dictionary?.filePath) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const dictionaryPath = dictionary.filePath;
|
|
36
|
+
const editedDictionaryContent = editedContent[dictionaryPath] ?? [];
|
|
37
|
+
return /* @__PURE__ */ jsx(
|
|
38
|
+
RightDrawer,
|
|
39
|
+
{
|
|
40
|
+
title: dictionary.id,
|
|
41
|
+
label: `Edit dictionary ${dictionary.id}`,
|
|
42
|
+
header: /* @__PURE__ */ jsx(
|
|
43
|
+
LocaleSwitcher,
|
|
44
|
+
{
|
|
45
|
+
setLocale,
|
|
46
|
+
locale,
|
|
47
|
+
localeList
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
children: /* @__PURE__ */ jsx(
|
|
51
|
+
DictionaryEditor,
|
|
52
|
+
{
|
|
53
|
+
dictionary,
|
|
54
|
+
locale,
|
|
55
|
+
focusedKeyPath: focusedContent.keyPath,
|
|
56
|
+
editedContent: editedDictionaryContent,
|
|
57
|
+
onFocusKeyPath: (keyPath) => setFocusedContent({ ...focusedContent, keyPath }),
|
|
58
|
+
onContentChange: (keyPath, newValue) => addEditedContent(dictionaryPath, keyPath, newValue),
|
|
59
|
+
onValidEdition: editContentRequest,
|
|
60
|
+
onCancelEdition: () => {
|
|
61
|
+
clearEditedDictionaryContent(dictionaryPath);
|
|
62
|
+
setFocusedContent(null);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
export {
|
|
70
|
+
EditionPanel
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=EditionPanel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/EditionPanel/EditionPanel.tsx"],"sourcesContent":["'use client';\n\nimport type { Locales } from '@intlayer/config/client';\nimport type { ContentModule } from '@intlayer/core';\nimport {\n useRightDrawerStore,\n RightDrawer,\n DictionaryEditor,\n LocaleSwitcher,\n} from '@intlayer/design-system';\n/**\n * @intlayer/dictionaries-entry is a package that only returns the dictionary entry path.\n * Using an external package allow to alias it in the bundle configuration (such as webpack).\n * The alias allow hot reload the app (such as nextjs) on any dictionary change.\n */\nimport dictionaries from '@intlayer/dictionaries-entry';\nimport { type FC, useEffect } from 'react';\nimport { useEditorServer } from '../useEditorServer';\nimport { useEditedContentStore } from './useEditedContentStore';\nimport { useEditionPanelStore } from './useEditionPanelStore';\n\ntype EditionPanelProps = {\n locale: Locales;\n localeList: Locales[];\n setLocale: (locale: Locales) => void;\n};\n\nexport const EditionPanel: FC<EditionPanelProps> = ({\n locale,\n localeList,\n setLocale,\n}) => {\n const { open } = useRightDrawerStore();\n const { focusedContent, setFocusedContent } = useEditionPanelStore();\n const { editedContent, addEditedContent, clearEditedDictionaryContent } =\n useEditedContentStore();\n const { editContentRequest } = useEditorServer();\n\n // Use effect to react to changes in focusedContent\n useEffect(() => {\n if (focusedContent !== null) {\n open(); // Call the open function from useRightDrawerStore\n }\n }, [focusedContent, open]); // Depend on focusedContent and open to trigger the effect\n\n if (!focusedContent) {\n return null;\n }\n\n const dictionary: ContentModule = dictionaries[focusedContent.dictionaryId];\n\n if (!dictionary?.filePath) {\n return null;\n }\n\n const dictionaryPath = dictionary.filePath;\n const editedDictionaryContent = editedContent[dictionaryPath] ?? [];\n\n return (\n <RightDrawer\n title={dictionary.id}\n label={`Edit dictionary ${dictionary.id}`}\n header={\n <LocaleSwitcher\n setLocale={setLocale}\n locale={locale}\n localeList={localeList}\n />\n }\n >\n <DictionaryEditor\n dictionary={dictionary}\n locale={locale}\n focusedKeyPath={focusedContent.keyPath}\n editedContent={editedDictionaryContent}\n onFocusKeyPath={(keyPath) =>\n setFocusedContent({ ...focusedContent, keyPath })\n }\n onContentChange={(keyPath, newValue) =>\n addEditedContent(dictionaryPath, keyPath, newValue)\n }\n onValidEdition={editContentRequest}\n onCancelEdition={() => {\n clearEditedDictionaryContent(dictionaryPath);\n setFocusedContent(null);\n }}\n />\n </RightDrawer>\n );\n};\n"],"mappings":";AA+DQ;AA3DR;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAMP,OAAO,kBAAkB;AACzB,SAAkB,iBAAiB;AACnC,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AAQ9B,MAAM,eAAsC,CAAC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,KAAK,IAAI,oBAAoB;AACrC,QAAM,EAAE,gBAAgB,kBAAkB,IAAI,qBAAqB;AACnE,QAAM,EAAE,eAAe,kBAAkB,6BAA6B,IACpE,sBAAsB;AACxB,QAAM,EAAE,mBAAmB,IAAI,gBAAgB;AAG/C,YAAU,MAAM;AACd,QAAI,mBAAmB,MAAM;AAC3B,WAAK;AAAA,IACP;AAAA,EACF,GAAG,CAAC,gBAAgB,IAAI,CAAC;AAEzB,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,aAA4B,aAAa,eAAe,YAAY;AAE1E,MAAI,CAAC,YAAY,UAAU;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,WAAW;AAClC,QAAM,0BAA0B,cAAc,cAAc,KAAK,CAAC;AAElE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,WAAW;AAAA,MAClB,OAAO,mBAAmB,WAAW,EAAE;AAAA,MACvC,QACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MAGF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,gBAAgB,eAAe;AAAA,UAC/B,eAAe;AAAA,UACf,gBAAgB,CAAC,YACf,kBAAkB,EAAE,GAAG,gBAAgB,QAAQ,CAAC;AAAA,UAElD,iBAAiB,CAAC,SAAS,aACzB,iBAAiB,gBAAgB,SAAS,QAAQ;AAAA,UAEpD,gBAAgB;AAAA,UAChB,iBAAiB,MAAM;AACrB,yCAA6B,cAAc;AAC3C,8BAAkB,IAAI;AAAA,UACxB;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { EditionPanel } from './EditionPanel.mjs';
|
|
2
|
+
export { useEditionPanelStore } from './useEditionPanelStore.mjs';
|
|
3
|
+
export { EditedContent, useEditedContentStore } from './useEditedContentStore.mjs';
|
|
4
|
+
import '@intlayer/config/client';
|
|
5
|
+
import 'react';
|
|
6
|
+
import 'zustand';
|
|
7
|
+
import '@intlayer/core';
|
|
8
|
+
import 'zustand/middleware';
|
|
9
|
+
import '@intlayer/design-system';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/EditionPanel/index.ts"],"sourcesContent":["export * from './EditionPanel';\nexport * from './useEditionPanelStore';\nexport * from './useEditedContentStore';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as zustand_middleware from 'zustand/middleware';
|
|
2
|
+
import * as zustand from 'zustand';
|
|
3
|
+
import { KeyPath } from '@intlayer/core';
|
|
4
|
+
import { FileContent } from '@intlayer/design-system';
|
|
5
|
+
|
|
6
|
+
type DictionaryPath = string;
|
|
7
|
+
type EditedContent = Record<DictionaryPath, FileContent[]>;
|
|
8
|
+
type EditedContentStore = {
|
|
9
|
+
editedContent: EditedContent;
|
|
10
|
+
addEditedContent: (dictionaryPath: DictionaryPath, keyPath: KeyPath[], newValue: string) => void;
|
|
11
|
+
removeEditedContent: (dictionaryPath: DictionaryPath, keyPath: KeyPath[]) => void;
|
|
12
|
+
clearEditedDictionaryContent: (dictionaryPath: DictionaryPath) => void;
|
|
13
|
+
clearEditedContent: () => void;
|
|
14
|
+
getEditedContentValue: (dictionaryPath: DictionaryPath, keyPath: KeyPath[]) => string | undefined;
|
|
15
|
+
};
|
|
16
|
+
declare const useEditedContentStore: zustand.UseBoundStore<Omit<zustand.StoreApi<EditedContentStore>, "persist"> & {
|
|
17
|
+
persist: {
|
|
18
|
+
setOptions: (options: Partial<zustand_middleware.PersistOptions<EditedContentStore, EditedContentStore>>) => void;
|
|
19
|
+
clearStorage: () => void;
|
|
20
|
+
rehydrate: () => void | Promise<void>;
|
|
21
|
+
hasHydrated: () => boolean;
|
|
22
|
+
onHydrate: (fn: (state: EditedContentStore) => void) => () => void;
|
|
23
|
+
onFinishHydration: (fn: (state: EditedContentStore) => void) => () => void;
|
|
24
|
+
getOptions: () => Partial<zustand_middleware.PersistOptions<EditedContentStore, EditedContentStore>>;
|
|
25
|
+
};
|
|
26
|
+
}>;
|
|
27
|
+
|
|
28
|
+
export { type EditedContent, useEditedContentStore };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { persist, createJSONStorage } from "zustand/middleware";
|
|
3
|
+
const isSameKeyPath = (keyPath1, keyPath2) => keyPath1.every(
|
|
4
|
+
(element, index) => keyPath2[index] && keyPath2[index].key === element.key && keyPath2[index].type === element.type
|
|
5
|
+
);
|
|
6
|
+
const useEditedContentStore = create(
|
|
7
|
+
persist(
|
|
8
|
+
(set, get) => ({
|
|
9
|
+
editedContent: {},
|
|
10
|
+
addEditedContent: (dictionaryPath, keyPath, newValue) => {
|
|
11
|
+
set((state) => {
|
|
12
|
+
const editedContent = state.editedContent[dictionaryPath] ?? [];
|
|
13
|
+
return {
|
|
14
|
+
editedContent: {
|
|
15
|
+
...state.editedContent,
|
|
16
|
+
[dictionaryPath]: [
|
|
17
|
+
...editedContent.filter(
|
|
18
|
+
(content) => !isSameKeyPath(content.keyPath, keyPath)
|
|
19
|
+
),
|
|
20
|
+
{
|
|
21
|
+
keyPath,
|
|
22
|
+
newValue
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
removeEditedContent: (dictionaryPath, keyPath) => {
|
|
30
|
+
set((state) => {
|
|
31
|
+
const editedContent = state.editedContent[dictionaryPath] ?? [];
|
|
32
|
+
return {
|
|
33
|
+
editedContent: {
|
|
34
|
+
...state.editedContent,
|
|
35
|
+
[dictionaryPath]: editedContent.filter(
|
|
36
|
+
(content) => content.keyPath !== keyPath
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
clearEditedDictionaryContent: (dictionaryPath) => {
|
|
43
|
+
set((state) => ({
|
|
44
|
+
editedContent: {
|
|
45
|
+
...state.editedContent,
|
|
46
|
+
[dictionaryPath]: []
|
|
47
|
+
}
|
|
48
|
+
}));
|
|
49
|
+
},
|
|
50
|
+
clearEditedContent: () => {
|
|
51
|
+
set({ editedContent: {} });
|
|
52
|
+
},
|
|
53
|
+
getEditedContentValue: (dictionaryPath, keyPath) => get().editedContent[dictionaryPath]?.find(
|
|
54
|
+
(content) => isSameKeyPath(content.keyPath, keyPath)
|
|
55
|
+
)?.newValue
|
|
56
|
+
}),
|
|
57
|
+
{
|
|
58
|
+
name: "edited-content-store",
|
|
59
|
+
storage: createJSONStorage(() => sessionStorage)
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
export {
|
|
64
|
+
useEditedContentStore
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=useEditedContentStore.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/EditionPanel/useEditedContentStore.ts"],"sourcesContent":["import type { KeyPath } from '@intlayer/core';\nimport type { FileContent } from '@intlayer/design-system';\nimport { create } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\n\ntype DictionaryPath = string;\n\nexport type EditedContent = Record<DictionaryPath, FileContent[]>;\n\ntype EditedContentStore = {\n editedContent: EditedContent;\n addEditedContent: (\n dictionaryPath: DictionaryPath,\n keyPath: KeyPath[],\n newValue: string\n ) => void;\n removeEditedContent: (\n dictionaryPath: DictionaryPath,\n keyPath: KeyPath[]\n ) => void;\n clearEditedDictionaryContent: (dictionaryPath: DictionaryPath) => void;\n clearEditedContent: () => void;\n getEditedContentValue: (\n dictionaryPath: DictionaryPath,\n keyPath: KeyPath[]\n ) => string | undefined;\n};\n\nconst isSameKeyPath = (keyPath1: KeyPath[], keyPath2: KeyPath[]) =>\n keyPath1.every(\n (element, index) =>\n keyPath2[index] &&\n keyPath2[index].key === element.key &&\n keyPath2[index].type === element.type\n );\n\nexport const useEditedContentStore = create(\n persist<EditedContentStore>(\n (set, get) => ({\n editedContent: {},\n addEditedContent: (dictionaryPath, keyPath, newValue) => {\n set((state) => {\n const editedContent = state.editedContent[dictionaryPath] ?? [];\n return {\n editedContent: {\n ...state.editedContent,\n [dictionaryPath]: [\n ...editedContent.filter(\n (content) => !isSameKeyPath(content.keyPath, keyPath)\n ),\n {\n keyPath,\n newValue,\n },\n ],\n },\n };\n });\n },\n\n removeEditedContent: (dictionaryPath, keyPath) => {\n set((state) => {\n const editedContent = state.editedContent[dictionaryPath] ?? [];\n return {\n editedContent: {\n ...state.editedContent,\n [dictionaryPath]: editedContent.filter(\n (content) => content.keyPath !== keyPath\n ),\n },\n };\n });\n },\n\n clearEditedDictionaryContent: (dictionaryPath) => {\n set((state) => ({\n editedContent: {\n ...state.editedContent,\n [dictionaryPath]: [],\n },\n }));\n },\n\n clearEditedContent: () => {\n set({ editedContent: {} });\n },\n\n getEditedContentValue: (dictionaryPath, keyPath): string | undefined =>\n get().editedContent[dictionaryPath]?.find((content) =>\n isSameKeyPath(content.keyPath, keyPath)\n )?.newValue,\n }),\n {\n name: 'edited-content-store',\n storage: createJSONStorage(() => sessionStorage),\n }\n )\n);\n"],"mappings":"AAEA,SAAS,cAAc;AACvB,SAAS,SAAS,yBAAyB;AAyB3C,MAAM,gBAAgB,CAAC,UAAqB,aAC1C,SAAS;AAAA,EACP,CAAC,SAAS,UACR,SAAS,KAAK,KACd,SAAS,KAAK,EAAE,QAAQ,QAAQ,OAChC,SAAS,KAAK,EAAE,SAAS,QAAQ;AACrC;AAEK,MAAM,wBAAwB;AAAA,EACnC;AAAA,IACE,CAAC,KAAK,SAAS;AAAA,MACb,eAAe,CAAC;AAAA,MAChB,kBAAkB,CAAC,gBAAgB,SAAS,aAAa;AACvD,YAAI,CAAC,UAAU;AACb,gBAAM,gBAAgB,MAAM,cAAc,cAAc,KAAK,CAAC;AAC9D,iBAAO;AAAA,YACL,eAAe;AAAA,cACb,GAAG,MAAM;AAAA,cACT,CAAC,cAAc,GAAG;AAAA,gBAChB,GAAG,cAAc;AAAA,kBACf,CAAC,YAAY,CAAC,cAAc,QAAQ,SAAS,OAAO;AAAA,gBACtD;AAAA,gBACA;AAAA,kBACE;AAAA,kBACA;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MAEA,qBAAqB,CAAC,gBAAgB,YAAY;AAChD,YAAI,CAAC,UAAU;AACb,gBAAM,gBAAgB,MAAM,cAAc,cAAc,KAAK,CAAC;AAC9D,iBAAO;AAAA,YACL,eAAe;AAAA,cACb,GAAG,MAAM;AAAA,cACT,CAAC,cAAc,GAAG,cAAc;AAAA,gBAC9B,CAAC,YAAY,QAAQ,YAAY;AAAA,cACnC;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MAEA,8BAA8B,CAAC,mBAAmB;AAChD,YAAI,CAAC,WAAW;AAAA,UACd,eAAe;AAAA,YACb,GAAG,MAAM;AAAA,YACT,CAAC,cAAc,GAAG,CAAC;AAAA,UACrB;AAAA,QACF,EAAE;AAAA,MACJ;AAAA,MAEA,oBAAoB,MAAM;AACxB,YAAI,EAAE,eAAe,CAAC,EAAE,CAAC;AAAA,MAC3B;AAAA,MAEA,uBAAuB,CAAC,gBAAgB,YACtC,IAAI,EAAE,cAAc,cAAc,GAAG;AAAA,QAAK,CAAC,YACzC,cAAc,QAAQ,SAAS,OAAO;AAAA,MACxC,GAAG;AAAA,IACP;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,SAAS,kBAAkB,MAAM,cAAc;AAAA,IACjD;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as zustand from 'zustand';
|
|
2
|
+
import { KeyPath } from '@intlayer/core';
|
|
3
|
+
|
|
4
|
+
type DictionaryPath = string;
|
|
5
|
+
type FileContent = {
|
|
6
|
+
dictionaryPath: DictionaryPath;
|
|
7
|
+
dictionaryId: string;
|
|
8
|
+
keyPath: KeyPath[];
|
|
9
|
+
};
|
|
10
|
+
type EditionPanelStore = {
|
|
11
|
+
focusedContent: FileContent | null;
|
|
12
|
+
setFocusedContent: (content: FileContent | null) => void;
|
|
13
|
+
};
|
|
14
|
+
declare const useEditionPanelStore: zustand.UseBoundStore<zustand.StoreApi<EditionPanelStore>>;
|
|
15
|
+
|
|
16
|
+
export { useEditionPanelStore };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
const useEditionPanelStore = create((set) => ({
|
|
3
|
+
focusedContent: null,
|
|
4
|
+
setFocusedContent: (content) => set({ focusedContent: content })
|
|
5
|
+
}));
|
|
6
|
+
export {
|
|
7
|
+
useEditionPanelStore
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useEditionPanelStore.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/client/EditionPanel/useEditionPanelStore.ts"],"sourcesContent":["import type { KeyPath } from '@intlayer/core';\nimport { create } from 'zustand';\n\ntype DictionaryPath = string;\ntype FileContent = {\n dictionaryPath: DictionaryPath;\n dictionaryId: string;\n keyPath: KeyPath[];\n};\n\ntype EditionPanelStore = {\n focusedContent: FileContent | null;\n setFocusedContent: (content: FileContent | null) => void;\n};\n\nexport const useEditionPanelStore = create<EditionPanelStore>((set) => ({\n focusedContent: null,\n setFocusedContent: (content) => set({ focusedContent: content }),\n}));\n"],"mappings":"AACA,SAAS,cAAc;AAchB,MAAM,uBAAuB,OAA0B,CAAC,SAAS;AAAA,EACtE,gBAAgB;AAAA,EAChB,mBAAmB,CAAC,YAAY,IAAI,EAAE,gBAAgB,QAAQ,CAAC;AACjE,EAAE;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { renderContentEditor } from './renderContentSelector.mjs';
|
|
2
|
+
export { EditionPanel } from './EditionPanel/EditionPanel.mjs';
|
|
3
|
+
export { useEditionPanelStore } from './EditionPanel/useEditionPanelStore.mjs';
|
|
4
|
+
export { EditedContent, useEditedContentStore } from './EditionPanel/useEditedContentStore.mjs';
|
|
5
|
+
export { ContentEditionLayout, ContentEditionLayoutProps } from './ContentEditionLayout.mjs';
|
|
6
|
+
export { useEditorServer } from './useEditorServer.mjs';
|
|
7
|
+
import 'react/jsx-runtime';
|
|
8
|
+
import '@intlayer/core';
|
|
9
|
+
import '@intlayer/config/client';
|
|
10
|
+
import 'react';
|
|
11
|
+
import 'zustand';
|
|
12
|
+
import 'zustand/middleware';
|
|
13
|
+
import '@intlayer/design-system';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/client/index.ts"],"sourcesContent":["export * from './renderContentSelector';\nexport * from './EditionPanel/index';\nexport * from './ContentEditionLayout';\nexport * from './useEditorServer';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { KeyPath } from '@intlayer/core';
|
|
3
|
+
|
|
4
|
+
declare const renderContentEditor: (content: string, dictionaryId: string, dictionaryPath: string, keyPath: KeyPath[]) => react_jsx_runtime.JSX.Element;
|
|
5
|
+
|
|
6
|
+
export { renderContentEditor };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ContentSelectorWrapper } from './ContentSelectorWrapper.mjs';
|
|
3
|
+
const renderContentEditor = (content, dictionaryId, dictionaryPath, keyPath) => /* @__PURE__ */ jsx(
|
|
4
|
+
ContentSelectorWrapper,
|
|
5
|
+
{
|
|
6
|
+
dictionaryId,
|
|
7
|
+
dictionaryPath,
|
|
8
|
+
keyPath,
|
|
9
|
+
children: content
|
|
10
|
+
}
|
|
11
|
+
);
|
|
12
|
+
export {
|
|
13
|
+
renderContentEditor
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=renderContentSelector.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/client/renderContentSelector.tsx"],"sourcesContent":["import type { KeyPath } from '@intlayer/core';\nimport { ContentSelectorWrapper } from './ContentSelectorWrapper';\n\nexport const renderContentEditor = (\n content: string,\n dictionaryId: string,\n dictionaryPath: string,\n keyPath: KeyPath[]\n) => (\n <ContentSelectorWrapper\n dictionaryId={dictionaryId}\n dictionaryPath={dictionaryPath}\n keyPath={keyPath}\n >\n {content}\n </ContentSelectorWrapper>\n);\n"],"mappings":"AASE;AARF,SAAS,8BAA8B;AAEhC,MAAM,sBAAsB,CACjC,SACA,cACA,gBACA,YAEA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IAEC;AAAA;AACH;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getConfiguration } from "@intlayer/config/client";
|
|
2
|
+
import { useEditedContentStore } from './EditionPanel/useEditedContentStore.mjs';
|
|
3
|
+
const useEditorServer = () => {
|
|
4
|
+
const { editedContent, clearEditedContent } = useEditedContentStore();
|
|
5
|
+
const editContentRequest = async () => {
|
|
6
|
+
const {
|
|
7
|
+
editor: { port }
|
|
8
|
+
} = getConfiguration();
|
|
9
|
+
await fetch(`http://localhost:${port}`, {
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/json"
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify(editedContent)
|
|
15
|
+
}).then((response) => {
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error("Failed to edit content");
|
|
18
|
+
}
|
|
19
|
+
clearEditedContent();
|
|
20
|
+
}).catch((error) => {
|
|
21
|
+
console.error("Failed to edit content:", error);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
return { editContentRequest };
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
useEditorServer
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=useEditorServer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/client/useEditorServer.ts"],"sourcesContent":["import { getConfiguration } from '@intlayer/config/client';\nimport { useEditedContentStore } from './EditionPanel/useEditedContentStore';\n\nexport const useEditorServer = () => {\n const { editedContent, clearEditedContent } = useEditedContentStore();\n\n const editContentRequest = async () => {\n const {\n editor: { port },\n } = getConfiguration();\n\n await fetch(`http://localhost:${port}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(editedContent),\n })\n .then((response) => {\n if (!response.ok) {\n throw new Error('Failed to edit content');\n }\n clearEditedContent();\n })\n .catch((error) => {\n console.error('Failed to edit content:', error);\n });\n };\n\n return { editContentRequest };\n};\n"],"mappings":"AAAA,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AAE/B,MAAM,kBAAkB,MAAM;AACnC,QAAM,EAAE,eAAe,mBAAmB,IAAI,sBAAsB;AAEpE,QAAM,qBAAqB,YAAY;AACrC,UAAM;AAAA,MACJ,QAAQ,EAAE,KAAK;AAAA,IACjB,IAAI,iBAAiB;AAErB,UAAM,MAAM,oBAAoB,IAAI,IAAI;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,aAAa;AAAA,IACpC,CAAC,EACE,KAAK,CAAC,aAAa;AAClB,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AACA,yBAAmB;AAAA,IACrB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,cAAQ,MAAM,2BAA2B,KAAK;AAAA,IAChD,CAAC;AAAA,EACL;AAEA,SAAO,EAAE,mBAAmB;AAC9B;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EditedContent } from '../client/EditionPanel/useEditedContentStore.mjs';
|
|
2
|
+
import 'zustand/middleware';
|
|
3
|
+
import 'zustand';
|
|
4
|
+
import '@intlayer/core';
|
|
5
|
+
import '@intlayer/design-system';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Edit the content of a file based on the key path and new value
|
|
9
|
+
*/
|
|
10
|
+
declare const editContent: (editedContent: EditedContent) => Promise<void>;
|
|
11
|
+
|
|
12
|
+
export { editContent };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
import { parse } from "@babel/parser";
|
|
4
|
+
import {
|
|
5
|
+
NodeType
|
|
6
|
+
} from "@intlayer/core";
|
|
7
|
+
import prettier from "prettier";
|
|
8
|
+
const requireFunction = typeof import.meta.url === "undefined" ? require : createRequire(import.meta.url);
|
|
9
|
+
const { default: generate } = requireFunction("@babel/generator");
|
|
10
|
+
const findNestedProperty = (obj, keyPath) => {
|
|
11
|
+
let currentObj = obj;
|
|
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
|
+
foundProperty = currentObj.properties.find(
|
|
19
|
+
(prop) => "key" in prop && prop.key.name === key.key
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
if (
|
|
23
|
+
// if the keypath is a translation or enumeration node, go across the function and select the related node
|
|
24
|
+
Object.values(NodeType).includes(
|
|
25
|
+
key.type
|
|
26
|
+
)
|
|
27
|
+
) {
|
|
28
|
+
foundProperty = currentObj.arguments[0].properties.find(
|
|
29
|
+
(prop) => "key" in prop && prop.key.name === key.key
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (foundProperty && "value" in foundProperty) {
|
|
33
|
+
currentObj = foundProperty.value;
|
|
34
|
+
} else {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return currentObj;
|
|
39
|
+
};
|
|
40
|
+
const findAndUpdate = (objExpr, keyPath, newValue) => {
|
|
41
|
+
const lastKey = keyPath[keyPath.length - 1];
|
|
42
|
+
if (lastKey) {
|
|
43
|
+
const propertyToUpdate = findNestedProperty(objExpr, keyPath);
|
|
44
|
+
if (propertyToUpdate && "value" in propertyToUpdate) {
|
|
45
|
+
propertyToUpdate.value = newValue;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const traverseNode = (node, keyPath, newValue) => {
|
|
50
|
+
if (Array.isArray(node.body)) {
|
|
51
|
+
node.body.forEach(
|
|
52
|
+
(subNode) => traverseNode(subNode, keyPath, newValue)
|
|
53
|
+
);
|
|
54
|
+
} else if (node.body) {
|
|
55
|
+
traverseNode(node.body, keyPath, newValue);
|
|
56
|
+
}
|
|
57
|
+
if (
|
|
58
|
+
// For ES Module (e.g., `const variable = ...; export default variable`)
|
|
59
|
+
"declarations" in node
|
|
60
|
+
) {
|
|
61
|
+
node.declarations.forEach((declaration) => {
|
|
62
|
+
if (declaration.init?.type === "ObjectExpression") {
|
|
63
|
+
findAndUpdate(declaration.init, keyPath, newValue);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (
|
|
68
|
+
// For ES Module (e.g., `export default { ... }`)
|
|
69
|
+
"declaration" in node && node.declaration.type === "ObjectExpression"
|
|
70
|
+
) {
|
|
71
|
+
return findAndUpdate(
|
|
72
|
+
node.declaration,
|
|
73
|
+
keyPath,
|
|
74
|
+
newValue
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (
|
|
78
|
+
// For CommonJS (e.g., `module.exports = ...`)
|
|
79
|
+
"expression" in node && node.expression.right.type === "ObjectExpression"
|
|
80
|
+
) {
|
|
81
|
+
return findAndUpdate(
|
|
82
|
+
node.expression.right,
|
|
83
|
+
keyPath,
|
|
84
|
+
newValue
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const format = async (content) => {
|
|
89
|
+
let options = {};
|
|
90
|
+
try {
|
|
91
|
+
options = await prettier.resolveConfig(content, {
|
|
92
|
+
editorconfig: true
|
|
93
|
+
}) ?? {};
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error("Failed to resolve Prettier configuration:", error);
|
|
96
|
+
}
|
|
97
|
+
const config = { ...options, parser: "typescript" };
|
|
98
|
+
return prettier.format(content, config);
|
|
99
|
+
};
|
|
100
|
+
const editContent = async (editedContent) => {
|
|
101
|
+
for (const dictionaryPath of Object.keys(editedContent)) {
|
|
102
|
+
const fileContent = readFileSync(dictionaryPath, "utf-8");
|
|
103
|
+
const parsed = parse(fileContent, {
|
|
104
|
+
sourceType: "module",
|
|
105
|
+
plugins: ["jsx", "typescript"]
|
|
106
|
+
});
|
|
107
|
+
for (const { keyPath, newValue } of editedContent[dictionaryPath]) {
|
|
108
|
+
traverseNode(parsed.program, keyPath, newValue);
|
|
109
|
+
}
|
|
110
|
+
const updatedContent = generate(parsed).code;
|
|
111
|
+
if (fileContent === updatedContent) {
|
|
112
|
+
console.info(`Could not find specified key path in ${dictionaryPath}.`);
|
|
113
|
+
} else {
|
|
114
|
+
const formattedContent = await format(updatedContent);
|
|
115
|
+
writeFileSync(dictionaryPath, formattedContent, "utf-8");
|
|
116
|
+
console.info("Updated the file successfully.");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export {
|
|
121
|
+
editContent
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=content-editor.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/content-editor.ts"],"sourcesContent":["import { 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} from '@babel/types';\nimport {\n NodeType,\n type KeyPath,\n type ObjectExpressionNode,\n type TranslationOrEnumerationNode,\n} from '@intlayer/core';\nimport prettier from 'prettier';\nimport type { EditedContent } from '../client/index';\n\nconst requireFunction =\n typeof import.meta.url === 'undefined'\n ? require\n : createRequire(import.meta.url);\n\nconst { default: generate } = requireFunction('@babel/generator');\n\n/**\n * Helper function to find a nested property in an ObjectExpression based on a key path\n */\nconst findNestedProperty = (\n obj: ObjectExpression,\n keyPath: KeyPath[]\n): ObjectExpression | undefined => {\n let currentObj = obj;\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 foundProperty = currentObj.properties.find(\n (prop) =>\n 'key' in prop &&\n (prop.key as Identifier).name === (key as ObjectExpressionNode).key\n );\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 foundProperty = (\n (currentObj as unknown as CallExpression)\n .arguments[0] as ObjectExpression\n ).properties.find(\n (prop) => 'key' in prop && (prop.key as Identifier).name === key.key\n );\n }\n\n if (foundProperty && 'value' in foundProperty) {\n currentObj = foundProperty.value as ObjectExpression;\n } else {\n return undefined;\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 // throw new Error('Could not find the specified key path in the AST.');\n};\n\n/**\n * Format the content with Prettier\n */\nconst format = async (content: string) => {\n // Resolve the configuration from the project\n let options: prettier.Options = {};\n\n try {\n // Resolve the prettier configuration from the project\n options =\n (await prettier.resolveConfig(content, {\n editorconfig: true,\n })) ?? {};\n } catch (error) {\n console.error('Failed to resolve Prettier configuration:', error);\n }\n\n // Add the parser option to the resolved config\n const config: prettier.Options = { ...options, parser: 'typescript' };\n\n return prettier.format(content, config);\n};\n\n/**\n * Edit the content of a file based on the key path and new value\n */\nexport const editContent = 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":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getConfiguration } from "@intlayer/config";
|
|
2
|
+
import bodyParser from "body-parser";
|
|
3
|
+
import express from "express";
|
|
4
|
+
import { editContent } from './content-editor.mjs';
|
|
5
|
+
const startIntlayerEditor = () => {
|
|
6
|
+
const app = express();
|
|
7
|
+
const {
|
|
8
|
+
editor: { port }
|
|
9
|
+
} = getConfiguration();
|
|
10
|
+
app.use(bodyParser.json());
|
|
11
|
+
app.use(bodyParser.urlencoded({ extended: true }));
|
|
12
|
+
app.post(
|
|
13
|
+
"/",
|
|
14
|
+
async (req, res) => {
|
|
15
|
+
const editedContent = req.body;
|
|
16
|
+
try {
|
|
17
|
+
await editContent(editedContent);
|
|
18
|
+
res.send({ success: true, editedContent });
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error(error);
|
|
21
|
+
res.status(500).send({ success: false });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
app.listen(port, () => {
|
|
26
|
+
console.info(
|
|
27
|
+
`Intlayer editor server is running on http://localhost:${port}`
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
export {
|
|
32
|
+
startIntlayerEditor
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["import { getConfiguration } from '@intlayer/config';\nimport bodyParser from 'body-parser';\nimport express, { type Request, type Response } from 'express';\nimport type { EditedContent } from '../client';\nimport { editContent } from './content-editor';\n\nexport const startIntlayerEditor = () => {\n const app = express();\n const {\n editor: { port },\n } = getConfiguration();\n\n app.use(bodyParser.json());\n app.use(bodyParser.urlencoded({ extended: true }));\n\n app.post(\n '/',\n async (\n req: Request<undefined, undefined, EditedContent>,\n res: Response\n ) => {\n const editedContent = req.body;\n\n try {\n await editContent(editedContent);\n\n res.send({ success: true, editedContent });\n } catch (error) {\n console.error(error);\n res.status(500).send({ success: false });\n }\n }\n );\n\n app.listen(port, () => {\n console.info(\n `Intlayer editor server is running on http://localhost:${port}`\n );\n });\n};\n"],"mappings":"AAAA,SAAS,wBAAwB;AACjC,OAAO,gBAAgB;AACvB,OAAO,aAA8C;AAErD,SAAS,mBAAmB;AAErB,MAAM,sBAAsB,MAAM;AACvC,QAAM,MAAM,QAAQ;AACpB,QAAM;AAAA,IACJ,QAAQ,EAAE,KAAK;AAAA,EACjB,IAAI,iBAAiB;AAErB,MAAI,IAAI,WAAW,KAAK,CAAC;AACzB,MAAI,IAAI,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAC;AAEjD,MAAI;AAAA,IACF;AAAA,IACA,OACE,KACA,QACG;AACH,YAAM,gBAAgB,IAAI;AAE1B,UAAI;AACF,cAAM,YAAY,aAAa;AAE/B,YAAI,KAAK,EAAE,SAAS,MAAM,cAAc,CAAC;AAAA,MAC3C,SAAS,OAAO;AACd,gBAAQ,MAAM,KAAK;AACnB,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,MAAM,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,MAAM,MAAM;AACrB,YAAQ;AAAA,MACN,yDAAyD,IAAI;AAAA,IAC/D;AAAA,EACF,CAAC;AACH;","names":[]}
|