optimize whole environment
This commit is contained in:
23
.cspell.json
Normal file
23
.cspell.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2",
|
||||||
|
"language": "en,en-gb",
|
||||||
|
"ignoreWords": [],
|
||||||
|
"words": [
|
||||||
|
"blankspace",
|
||||||
|
"docxtemplater",
|
||||||
|
"Heiti",
|
||||||
|
"Kaku",
|
||||||
|
"kintone",
|
||||||
|
"kintoneplugin",
|
||||||
|
"kypes",
|
||||||
|
"Ligh",
|
||||||
|
"moize",
|
||||||
|
"officedocument",
|
||||||
|
"openxmlformats",
|
||||||
|
"pizzip",
|
||||||
|
"rspack",
|
||||||
|
"SUBTABLE",
|
||||||
|
"wordprocessingml"
|
||||||
|
],
|
||||||
|
"ignorePaths": [".env"]
|
||||||
|
}
|
7
.vscode/extensions.json
vendored
7
.vscode/extensions.json
vendored
@ -1,3 +1,8 @@
|
|||||||
{
|
{
|
||||||
"recommendations": ["esbenp.prettier-vscode"]
|
"recommendations": [
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"streetsidesoftware.code-spell-checker",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"jawandarajbir.react-vscode-extension-pack"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -27,6 +27,8 @@
|
|||||||
"[jsonc]": {
|
"[jsonc]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
|
// Exteions - cSpell
|
||||||
|
// - see: .cspell.json
|
||||||
// Extensions - HTML
|
// Extensions - HTML
|
||||||
"html.format.wrapLineLength": 0,
|
"html.format.wrapLineLength": 0,
|
||||||
// Extentions - Prettier
|
// Extentions - Prettier
|
||||||
|
@ -1,4 +1,17 @@
|
|||||||
import presetsPrettier from "@cybozu/eslint-config/flat/presets/react-typescript-prettier.js";
|
import presetsPrettier from '@cybozu/eslint-config/flat/presets/react-typescript-prettier.js';
|
||||||
|
import globals from 'globals';
|
||||||
|
|
||||||
/** @type {import("eslint").Linter.Config[]} */
|
/** @type {import("eslint").Linter.Config[]} */
|
||||||
export default [...presetsPrettier];
|
export default [
|
||||||
|
...presetsPrettier,
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'spaced-comment': ['error', 'always', { markers: ['/'] }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
901
package-lock.json
generated
901
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
|||||||
"upload": "env-cmd --silent kintone-plugin-uploader dist/plugin.zip --watch --waiting-dialog-ms 3000"
|
"upload": "env-cmd --silent kintone-plugin-uploader dist/plugin.zip --watch --waiting-dialog-ms 3000"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kintone/rest-api-client": "^5.7.3",
|
"@kintone/rest-api-client": "^5.7.4",
|
||||||
"angular-expressions": "^1.4.3",
|
"angular-expressions": "^1.4.3",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
@ -42,6 +42,7 @@
|
|||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"eslint": "^9.28.0",
|
"eslint": "^9.28.0",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
|
"globals": "^16.2.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
"ja": "Word出力プラグイン"
|
"ja": "Word出力プラグイン"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"en": "Data can be formatted and downloaded using WORD template files.",
|
"en": "Data can be formatted and downloaded using Word template files.",
|
||||||
"ja": "WORDテンプレートファイルを使用して、データを整形してダウンロードできます。"
|
"ja": "Wordテンプレートファイルを使用して、データを整形してダウンロードできます。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,15 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const RSA = require('node-rsa');
|
const RSA = require('node-rsa');
|
||||||
|
|
||||||
const key = new RSA({ b: 1024 });
|
|
||||||
const privateKey = key.exportKey('pkcs1-private');
|
|
||||||
const privateKeyFile = './private.ppk';
|
const privateKeyFile = './private.ppk';
|
||||||
|
|
||||||
if (!fs.existsSync(privateKeyFile)) {
|
if (!fs.existsSync(privateKeyFile)) {
|
||||||
|
const key = new RSA({ b: 1024 });
|
||||||
|
const privateKey = key.exportKey('pkcs1-private');
|
||||||
fs.writeFile(privateKeyFile, privateKey, (err) => {
|
fs.writeFile(privateKeyFile, privateKey, (err) => {
|
||||||
err && console.error(err);
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,4 @@ invariant(
|
|||||||
`Unsupported language: ${LANGUAGE}. Supported languages are: ${KintoneUserLanguages.join(', ')}`,
|
`Unsupported language: ${LANGUAGE}. Supported languages are: ${KintoneUserLanguages.join(', ')}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const DOCX_CONTENTTYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
export const DOCX_CONTENT_TYPE = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
||||||
export const DOCX_EXTENSION = 'docx';
|
|
||||||
|
@ -65,7 +65,7 @@ const Settings: React.FC = () => {
|
|||||||
<KintonePluginTitle>
|
<KintonePluginTitle>
|
||||||
Template<KintonePluginRequire>*</KintonePluginRequire>
|
Template<KintonePluginRequire>*</KintonePluginRequire>
|
||||||
</KintonePluginTitle>
|
</KintonePluginTitle>
|
||||||
<KintonePluginDesc>Select a file field that contains the WORD template file.</KintonePluginDesc>
|
<KintonePluginDesc>Select a file field that contains the Word template file.</KintonePluginDesc>
|
||||||
{fileFields.length === 0 ? (
|
{fileFields.length === 0 ? (
|
||||||
<KintonePluginAlert>
|
<KintonePluginAlert>
|
||||||
No file fields found in the app. Please add a file field to use this plugin.
|
No file fields found in the app. Please add a file field to use this plugin.
|
||||||
|
45
src/declaration.d.ts
vendored
45
src/declaration.d.ts
vendored
@ -1,45 +0,0 @@
|
|||||||
// CSS modules
|
|
||||||
type CSSModuleClasses = { readonly [key: string]: string };
|
|
||||||
|
|
||||||
declare module '*.module.css' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.scss' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.sass' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.less' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.styl' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.stylus' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.pcss' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
declare module '*.module.sss' {
|
|
||||||
const classes: CSSModuleClasses;
|
|
||||||
export default classes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CSS
|
|
||||||
declare module '*.css' {}
|
|
||||||
declare module '*.scss' {}
|
|
||||||
declare module '*.sass' {}
|
|
||||||
declare module '*.less' {}
|
|
||||||
declare module '*.styl' {}
|
|
||||||
declare module '*.stylus' {}
|
|
||||||
declare module '*.pcss' {}
|
|
||||||
declare module '*.sss' {}
|
|
@ -5,8 +5,6 @@ import ErrorFallback from '../common/ErrorFallback';
|
|||||||
import Loading from '../common/Loading';
|
import Loading from '../common/Loading';
|
||||||
import MenuPanel from './MenuPanel';
|
import MenuPanel from './MenuPanel';
|
||||||
|
|
||||||
import '@shin-chan/kypes';
|
|
||||||
|
|
||||||
interface DesktopAppProps {
|
interface DesktopAppProps {
|
||||||
event: kintone.events.AppRecordDetailShowEvent | kintone.events.MobileAppRecordDetailShowEvent;
|
event: kintone.events.AppRecordDetailShowEvent | kintone.events.MobileAppRecordDetailShowEvent;
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,10 @@ import { saveAs } from 'file-saver';
|
|||||||
import moize from 'moize';
|
import moize from 'moize';
|
||||||
import PizZip from 'pizzip';
|
import PizZip from 'pizzip';
|
||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import { DOCX_CONTENTTYPE, LANGUAGE, PLUGIN_ID } from '../common/global';
|
import { DOCX_CONTENT_TYPE, LANGUAGE, PLUGIN_ID } from '../common/global';
|
||||||
import KintonePluginAlert from '../common/ui/KintonePluginAlert';
|
import KintonePluginAlert from '../common/ui/KintonePluginAlert';
|
||||||
import KintonePluginButton from '../common/ui/KintonePluginButton';
|
import KintonePluginButton from '../common/ui/KintonePluginButton';
|
||||||
|
|
||||||
import '@shin-chan/kypes';
|
|
||||||
|
|
||||||
interface TemplateData {
|
interface TemplateData {
|
||||||
[key: string]: TemplateData | TemplateData[] | string | string[];
|
[key: string]: TemplateData | TemplateData[] | string | string[];
|
||||||
}
|
}
|
||||||
@ -191,32 +189,32 @@ const MenuPanel: React.FC<MenuPanelProps> = (props) => {
|
|||||||
if (template === '') {
|
if (template === '') {
|
||||||
return (
|
return (
|
||||||
<KintonePluginAlert>
|
<KintonePluginAlert>
|
||||||
WORD output plugin: Template field is not set. Please configure the plugin.
|
Word output plugin: Template field is not set. Please configure the plugin.
|
||||||
</KintonePluginAlert>
|
</KintonePluginAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const record = event.record[template];
|
const record = event.record[template];
|
||||||
if (record == null) {
|
if (record == null) {
|
||||||
return <KintonePluginAlert>WORD output plugin: Template field is not available in this app.</KintonePluginAlert>;
|
return <KintonePluginAlert>Word output plugin: Template field is not available in this app.</KintonePluginAlert>;
|
||||||
}
|
}
|
||||||
if (record.type !== 'FILE') {
|
if (record.type !== 'FILE') {
|
||||||
return <KintonePluginAlert>WORD output plugin: Template field must be a file field.</KintonePluginAlert>;
|
return <KintonePluginAlert>Word output plugin: Template field must be a file field.</KintonePluginAlert>;
|
||||||
}
|
}
|
||||||
if (record.value.length === 0) {
|
if (record.value.length === 0) {
|
||||||
return <KintonePluginAlert>WORD output plugin: Template field does not contain any files.</KintonePluginAlert>;
|
return <KintonePluginAlert>Word output plugin: Template field does not contain any files.</KintonePluginAlert>;
|
||||||
}
|
}
|
||||||
if (record.value.length > 1) {
|
if (record.value.length > 1) {
|
||||||
return (
|
return (
|
||||||
<KintonePluginAlert>
|
<KintonePluginAlert>
|
||||||
WORD output plugin: Template field contains multiple files. Please ensure it contains only one file.
|
Word output plugin: Template field contains multiple files. Please ensure it contains only one file.
|
||||||
</KintonePluginAlert>
|
</KintonePluginAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const { fileKey, contentType } = record.value[0];
|
const { fileKey, contentType } = record.value[0];
|
||||||
if (contentType !== DOCX_CONTENTTYPE) {
|
if (contentType !== DOCX_CONTENT_TYPE) {
|
||||||
return (
|
return (
|
||||||
<KintonePluginAlert>
|
<KintonePluginAlert>
|
||||||
WORD output plugin: The template file must be a DOCX file. The current file type is {contentType}.
|
Word output plugin: The template file must be a DOCX file. The current file type is {contentType}.
|
||||||
</KintonePluginAlert>
|
</KintonePluginAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -233,18 +231,18 @@ const MenuPanel: React.FC<MenuPanelProps> = (props) => {
|
|||||||
parser: expressionParser,
|
parser: expressionParser,
|
||||||
});
|
});
|
||||||
doc.render(record2data(properties, event.record));
|
doc.render(record2data(properties, event.record));
|
||||||
const out = doc.getZip().generate({ type: 'blob', mimeType: DOCX_CONTENTTYPE });
|
const out = doc.getZip().generate({ type: 'blob', mimeType: DOCX_CONTENT_TYPE });
|
||||||
saveAs(out, 'output.docx');
|
saveAs(out, 'output.docx');
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error downloading file:', error);
|
console.error('Error downloading file:', error);
|
||||||
alert('Failed to download the WORD template file.');
|
alert('Failed to download the Word template file.');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KintonePluginButton variant="normal" onClick={handleOnClickOutputButton}>
|
<KintonePluginButton variant="normal" onClick={handleOnClickOutputButton}>
|
||||||
WORD出力
|
Word出力
|
||||||
</KintonePluginButton>
|
</KintonePluginButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,6 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import invariant from 'tiny-invariant';
|
import invariant from 'tiny-invariant';
|
||||||
import DesktopApp from './DesktopApp';
|
import DesktopApp from './DesktopApp';
|
||||||
|
|
||||||
import '@shin-chan/kypes';
|
|
||||||
|
|
||||||
import '../common/ui/51-modern-default.css';
|
import '../common/ui/51-modern-default.css';
|
||||||
|
|
||||||
kintone.events.on(
|
kintone.events.on(
|
||||||
|
17
src/kintone-env.d.ts
vendored
Normal file
17
src/kintone-env.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/// <reference types="@shin-chan/kypes" />
|
||||||
|
|
||||||
|
// CSS modules
|
||||||
|
type CSSModuleClasses = { readonly [key: string]: string };
|
||||||
|
|
||||||
|
declare module '*.module.css' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.scss' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS
|
||||||
|
declare module '*.css' {}
|
||||||
|
declare module '*.scss' {}
|
Reference in New Issue
Block a user