diff --git a/Dockerfile b/Dockerfile index f82c17d3..b5e38976 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,9 @@ WORKDIR /opt/stackedit COPY package*json /opt/stackedit/ COPY gulpfile.js /opt/stackedit/ -RUN npm install --unsafe-perm \ + +ENV NODE_TLS_REJECT_UNAUTHORIZED=0 +RUN git config --global http.sslVerify false && npm set strict-ssl false && npm install --unsafe-perm \ && npm cache clean --force COPY . /opt/stackedit ENV NODE_ENV production diff --git a/src/components/Modal.vue b/src/components/Modal.vue index 164b0837..39c20c7e 100644 --- a/src/components/Modal.vue +++ b/src/components/Modal.vue @@ -71,6 +71,7 @@ import GiteaOpenModal from './modals/providers/GiteaOpenModal'; import GiteaPublishModal from './modals/providers/GiteaPublishModal'; import GiteaSaveModal from './modals/providers/GiteaSaveModal'; import GiteaWorkspaceModal from './modals/providers/GiteaWorkspaceModal'; +import GiteaImgStorageModal from './modals/providers/GiteaImgStorageModal'; import WordpressPublishModal from './modals/providers/WordpressPublishModal'; import BloggerPublishModal from './modals/providers/BloggerPublishModal'; import BloggerPagePublishModal from './modals/providers/BloggerPagePublishModal'; @@ -133,6 +134,7 @@ export default { GiteaPublishModal, GiteaSaveModal, GiteaWorkspaceModal, + GiteaImgStorageModal, WordpressPublishModal, BloggerPublishModal, BloggerPagePublishModal, diff --git a/src/components/menus/common/MenuItem.vue b/src/components/menus/common/MenuItem.vue new file mode 100644 index 00000000..6697bb35 --- /dev/null +++ b/src/components/menus/common/MenuItem.vue @@ -0,0 +1,93 @@ + + + diff --git a/src/components/modals/ImageModal.vue b/src/components/modals/ImageModal.vue index 6097c73e..b8ccbbd8 100644 --- a/src/components/modals/ImageModal.vue +++ b/src/components/modals/ImageModal.vue @@ -6,30 +6,52 @@ - 图片上传失败,如未添加SM.MS账号请先添加并选择,之后关闭窗口再重试! + 图片上传失败,如未添加图床请先添加并选择,之后关闭窗口再重试!

请为您的图像提供 url

添加并选择图床后可实现粘贴/拖拽自动上传图片

- + - + -
SM.MS图床
+
+ SM.MS图床 + +
{{token.name}} -
+ +
+ + + + + +
Gitea图床 + +
+ {{tokenStorage.uname}}, 仓库URL: {{tokenStorage.repoUrl}}, 路径: {{tokenStorage.path}}, 分支: {{tokenStorage.branch}} +
- 添加SM.MS账号 + 添加SM.MS图床账号 + + + + 添加Gitea图床仓库 @@ -37,12 +59,16 @@ + diff --git a/src/components/modals/providers/GiteaImgStorageModal.vue b/src/components/modals/providers/GiteaImgStorageModal.vue new file mode 100644 index 00000000..d05ddeab --- /dev/null +++ b/src/components/modals/providers/GiteaImgStorageModal.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/modals/providers/GiteaWorkspaceModal.vue b/src/components/modals/providers/GiteaWorkspaceModal.vue index 8d12a057..77fb9b7f 100644 --- a/src/components/modals/providers/GiteaWorkspaceModal.vue +++ b/src/components/modals/providers/GiteaWorkspaceModal.vue @@ -4,11 +4,11 @@ -

创建一个与 Gitea 项目文件夹同步的文档空间。

- +

创建一个与 Gitea 仓库文件夹同步的文档空间。

+ diff --git a/src/data/simpleModals.js b/src/data/simpleModals.js index 5445067a..b10ccc61 100644 --- a/src/data/simpleModals.js +++ b/src/data/simpleModals.js @@ -26,6 +26,11 @@ export default { '取消', '确认删除', ), + imgStorageDeletion: simpleModal( + '

您将要删除图床,你确定吗?

', + '取消', + '确认删除', + ), pathConflict: simpleModal( config => `

${config.item.name}已经存在。您要添加后缀吗?

`, '取消', diff --git a/src/data/versions.js b/src/data/versions.js new file mode 100644 index 00000000..b1183268 --- /dev/null +++ b/src/data/versions.js @@ -0,0 +1,5 @@ +export default { + versionsDescription: { + '5.15.7': '支持了粘贴/拖拽图片自动上传SM.MS图床/Gitea图床', + }, +}; diff --git a/src/data/welcomeFile.md b/src/data/welcomeFile.md index 947dae78..24fea572 100644 --- a/src/data/welcomeFile.md +++ b/src/data/welcomeFile.md @@ -2,11 +2,6 @@ 你好!我是你在 **StackEdit中文版** 中的第一个 Markdown 文件。如果你想了解 StackEdit中文版,可以阅读此文章。如果你想玩 Markdown,你也可以编辑次文章。另外,您可以通过打开导航栏左角的**文件资源管理器**来创建新文件。 -> **新功能** -> -> 已支持直接粘贴/拖拽上传文件,目前仅支持了SM.MS图床(2022.07.01) - - # 文件 StackEdit中文版 将您的文件存储在您的浏览器中,这意味着您的所有文件都会自动保存在本地并且可以**离线访问!** diff --git a/src/index.js b/src/index.js index 8f373d90..6b0a2c94 100644 --- a/src/index.js +++ b/src/index.js @@ -8,9 +8,10 @@ import './icons'; import App from './components/App'; import store from './store'; import localDbSvc from './services/localDbSvc'; +import versionsDescription from './data/versions'; if (!indexedDB) { - throw new Error('Your browser is not supported. Please upgrade to the latest version.'); + throw new Error('不支持您的浏览器,请升级到最新版本。'); } OfflinePluginRuntime.install({ @@ -29,8 +30,9 @@ OfflinePluginRuntime.install({ }); if (localStorage.updated) { - store.dispatch('notification/info', 'StackEdit has just updated itself!'); - setTimeout(() => localStorage.removeItem('updated'), 2000); + const versionDesc = versionsDescription[VERSION]; + store.dispatch('notification/info', `StackEdit中文版刚刚更新了!${versionDesc}`); + setTimeout(() => localStorage.removeItem('updated'), 3000); } if (!localStorage.installPrompted) { @@ -39,7 +41,7 @@ if (!localStorage.installPrompted) { promptEvent.preventDefault(); try { - await store.dispatch('notification/confirm', 'Add StackEdit to your home screen?'); + await store.dispatch('notification/confirm', '将StackEdit中文版添加到您的主屏幕上?'); promptEvent.prompt(); await promptEvent.userChoice; } catch (err) { diff --git a/src/services/providers/giteaWorkspaceProvider.js b/src/services/providers/giteaWorkspaceProvider.js index fc1cd52a..9f1d56b8 100644 --- a/src/services/providers/giteaWorkspaceProvider.js +++ b/src/services/providers/giteaWorkspaceProvider.js @@ -83,7 +83,7 @@ export default new Provider({ } if (!workspace) { - const projectId = await giteaHelper.getProjectId(workspaceParams); + const projectId = await giteaHelper.getProjectId(token, workspaceParams); const pathEntries = (path || '').split('/'); const projectPathEntries = (projectPath || '').split('/'); const name = pathEntries[pathEntries.length - 2] // path ends with `/` diff --git a/src/services/providers/helpers/giteaHelper.js b/src/services/providers/helpers/giteaHelper.js index 47458815..279d21d8 100644 --- a/src/services/providers/helpers/giteaHelper.js +++ b/src/services/providers/helpers/giteaHelper.js @@ -58,6 +58,7 @@ export default { sub = null, silent = false, refreshToken, ) { let tokenBody; + const imgStorages = refreshToken && refreshToken.imgStorages; if (!silent) { // Get an OAuth2 code const { code } = await networkSvc.startOauth2( @@ -120,6 +121,7 @@ export default { name: user.username, applicationId, applicationSecret, + imgStorages, refreshToken: tokenBody.refresh_token, expiresOn: Date.now() + (tokenBody.expires_in * 1000), serverUrl, @@ -176,16 +178,48 @@ export default { badgeSvc.addBadge('addGiteaAccount'); return token; }, - - /** - * https://try.gitea.io/api/swagger#/repository/repoGet - */ - async getProjectId({ projectPath, projectId }) { + async updateToken(token, imgStorageInfo) { + const imgStorages = token.imgStorages || []; + // 存储仓库唯一标识 + const sid = utils.hash(`${imgStorageInfo.repoUri}${imgStorageInfo.path}${imgStorageInfo.branch}`); + // 查询是否存在 存在则更新 + const filterStorages = imgStorages.filter(it => it.sid === sid); + if (filterStorages && filterStorages.length > 0) { + filterStorages.repoUri = imgStorageInfo.repoUri; + filterStorages.path = imgStorageInfo.path; + filterStorages.branch = imgStorageInfo.branch; + } else { + imgStorages.push({ + sid, + repoUri: imgStorageInfo.repoUri, + path: imgStorageInfo.path, + branch: imgStorageInfo.branch, + }); + token.imgStorages = imgStorages; + } + store.dispatch('data/addGiteaToken', token); + }, + async removeTokenImgStorage(token, sid) { + if (!token.imgStorages || token.imgStorages.length === 0) { + return; + } + token.imgStorages = token.imgStorages.filter(it => it.sid !== sid); + store.dispatch('data/addGiteaToken', token); + }, + async getProjectId(token, { projectPath, projectId }) { if (projectId) { return projectId; } + const repoInfo = await this.getRepoInfo(token, projectPath); + return repoInfo.full_name; + }, + /** + * https://try.gitea.io/api/swagger#/repository/repoGet + */ + async getRepoInfo(token, projectPath) { const [, repoFullName] = projectPath.match(/([^/]+\/[^/]+)$/); - return repoFullName; + const refreshedToken = await this.refreshToken(token); + return request(refreshedToken, { url: `repos/${repoFullName}` }); }, /** @@ -236,6 +270,7 @@ export default { path, content, sha, + isFile, }) { const refreshedToken = await this.refreshToken(token); return request(refreshedToken, { @@ -243,7 +278,7 @@ export default { url: `repos/${projectId}/contents/${encodeURIComponent(path)}`, body: { message: getCommitMessage(sha ? 'updateFileMessage' : 'createFileMessage', path), - content: utils.encodeBase64(content), + content: isFile ? await utils.encodeFiletoBase64(content) : utils.encodeBase64(content), sha, branch, }, diff --git a/src/services/utils.js b/src/services/utils.js index 7b7f4d9f..88d27d3a 100644 --- a/src/services/utils.js +++ b/src/services/utils.js @@ -182,6 +182,14 @@ export default { .replace(/\+/g, '-') // Replace `+` with `-` .replace(/=+$/, ''); // Remove trailing `=` }, + encodeFiletoBase64(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result.split(',').pop()); + reader.onerror = error => reject(error); + }); + }, decodeBase64(str) { // In case of URL safe base64 const sanitizedStr = str.replace(/_/g, '/').replace(/-/g, '+');