mirror of
https://gitee.com/mafgwo/stackedit
synced 2024-11-16 11:42:23 +08:00
Gitlab支持优化
This commit is contained in:
parent
4d8ff0ea0c
commit
b1691e0d4f
|
@ -69,6 +69,7 @@ StackEdit中文版
|
|||
- 支持图片直接存储到当前文档空间(2022-10-29)
|
||||
- 支持MD文档之间链接跳转(2022-11-20)
|
||||
- 支持预览区域选择主题样式(2022-12-04)
|
||||
- Gitlab的支持优化(2023-02-23)
|
||||
|
||||
## 国外开源版本弊端:
|
||||
- 作者已经不维护了
|
||||
|
@ -151,6 +152,9 @@ docker run -itd --name stackedit \
|
|||
|
||||
- Gitea可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITEA_CLIENT_ID、GITEA_CLIENT_SECRET、GITEA_URL,**[如何创建Gitea应用](./docs/部署之Gitea应用创建.md)**
|
||||
|
||||
- Gitlab可选择性配置环境变量(未配置则在关联时前端指定,有配置则仅允许配置的应用信息):GITLAB_CLIENT_ID、GITEA_URL **如何创建Gitlab应用(待补充文档)**
|
||||
|
||||
(特别说明:自建的Gitea、Gitlab要能接入stackedit必须支持跨域)
|
||||
|
||||
## 编译与运行
|
||||
> 编译运行的nodejs版本选择11.15.0版本
|
||||
|
|
|
@ -18,6 +18,8 @@ awsSecretAccessKey: ""
|
|||
giteaClientId: ""
|
||||
giteaClientSecret: ""
|
||||
giteaUrl: ""
|
||||
gitlabClientId: ""
|
||||
gitlabUrl: ""
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
|
|
|
@ -12,4 +12,6 @@ module.exports = merge(prodEnv, {
|
|||
// GITEA_CLIENT_ID: '"fe30f8f9-b1e8-4531-8f72-c1a5d3912805"',
|
||||
// GITEA_CLIENT_SECRET: '"lus7oMnb3H6M1hsChndphArE20Txr7erwJLf7SDBQWTw"',
|
||||
// GITEA_URL: '"https://gitea.test.com"',
|
||||
// GITLAB_CLIENT_ID: '"33e01128c27fe75df3e5b35218d710c7df280e6ee9c90b6ca27ac9d9fdfb92f7"',
|
||||
// GITLAB_URL: '"http://gitlab.qicoder.com"',
|
||||
})
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "stackedit",
|
||||
"version": "5.15.17",
|
||||
"version": "5.15.18",
|
||||
"description": "免费, 开源, 功能齐全的 Markdown 编辑器",
|
||||
"author": "Benoit Schweblin, 豆萁",
|
||||
"license": "Apache-2.0",
|
||||
|
|
|
@ -14,6 +14,8 @@ const wordpressClientId = process.env.WORDPRESS_CLIENT_ID;
|
|||
const giteaClientId = process.env.GITEA_CLIENT_ID;
|
||||
const giteaClientSecret = process.env.GITEA_CLIENT_SECRET;
|
||||
const giteaUrl = process.env.GITEA_URL;
|
||||
const gitlabClientId = process.env.GITLAB_CLIENT_ID;
|
||||
const gitlabUrl = process.env.GITLAB_URL;
|
||||
|
||||
exports.values = {
|
||||
pandocPath,
|
||||
|
@ -43,4 +45,6 @@ exports.publicValues = {
|
|||
allowSponsorship: !!paypalReceiverEmail,
|
||||
giteaClientId,
|
||||
giteaUrl,
|
||||
gitlabClientId,
|
||||
gitlabUrl,
|
||||
};
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
import modalTemplate from '../common/modalTemplate';
|
||||
import constants from '../../../data/constants';
|
||||
import store from '../../../store';
|
||||
import networkSvc from '../../../services/networkSvc';
|
||||
|
||||
export default modalTemplate({
|
||||
data: () => ({
|
||||
|
@ -65,6 +66,9 @@ export default modalTemplate({
|
|||
return !!confClientId && !!confServerUrl;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
networkSvc.getServerConf();
|
||||
},
|
||||
methods: {
|
||||
resolve() {
|
||||
if (this.useServerConf) {
|
||||
|
|
|
@ -5,22 +5,27 @@
|
|||
<icon-provider provider-id="gitlab"></icon-provider>
|
||||
</div>
|
||||
<p>将您的<b>GitLab</b>链接到<b>StackEdit中文版</b>。</p>
|
||||
<form-entry label="GitLab URL" error="serverUrl">
|
||||
<input v-if="config.forceServerUrl" slot="field" class="textfield" type="text" disabled="disabled" v-model="config.forceServerUrl">
|
||||
<input v-else slot="field" class="textfield" type="text" v-model.trim="serverUrl" @keydown.enter="resolve()">
|
||||
<div class="form-entry__info">
|
||||
<b>例如:</b> https://gitlab.example.com/
|
||||
</div>
|
||||
</form-entry>
|
||||
<form-entry label="Application ID" error="applicationId">
|
||||
<input slot="field" class="textfield" type="text" v-model.trim="applicationId" @keydown.enter="resolve()">
|
||||
<div class="form-entry__info">
|
||||
您必须使用重定向url <b>{{redirectUrl}}</b>配置OAuth2应用程序
|
||||
</div>
|
||||
<div class="form-entry__actions">
|
||||
<a href="https://docs.gitlab.com/ee/integration/oauth_provider.html" target="_blank">更多信息</a>
|
||||
</div>
|
||||
</form-entry>
|
||||
<template v-if="!useServerConf">
|
||||
<form-entry label="GitLab URL" error="serverUrl">
|
||||
<input v-if="config.forceServerUrl" slot="field" class="textfield" type="text" disabled="disabled" v-model="config.forceServerUrl">
|
||||
<input v-else slot="field" class="textfield" type="text" v-model.trim="serverUrl" @keydown.enter="resolve()">
|
||||
<div class="form-entry__info">
|
||||
<b>例如:</b> https://gitlab.example.com/
|
||||
<span v-if="httpAppUrl">
|
||||
,非https的URL,请跳转到 <a :href="httpAppUrl" target="_blank">HTTP链接</a> 添加Gitlab。
|
||||
</span>
|
||||
</div>
|
||||
</form-entry>
|
||||
<form-entry label="Application ID" error="applicationId">
|
||||
<input slot="field" class="textfield" type="text" v-model.trim="applicationId" @keydown.enter="resolve()">
|
||||
<div class="form-entry__info">
|
||||
您必须使用重定向url <b>{{redirectUrl}}</b>配置OAuth2应用程序
|
||||
</div>
|
||||
<div class="form-entry__actions">
|
||||
<a href="https://docs.gitlab.com/ee/integration/oauth_provider.html" target="_blank">更多信息</a>
|
||||
</div>
|
||||
</form-entry>
|
||||
</template>
|
||||
</div>
|
||||
<div class="modal__button-bar">
|
||||
<button class="button" @click="config.reject()">取消</button>
|
||||
|
@ -32,6 +37,8 @@
|
|||
<script>
|
||||
import modalTemplate from '../common/modalTemplate';
|
||||
import constants from '../../../data/constants';
|
||||
import store from '../../../store';
|
||||
import networkSvc from '../../../services/networkSvc';
|
||||
|
||||
export default modalTemplate({
|
||||
data: () => ({
|
||||
|
@ -41,8 +48,29 @@ export default modalTemplate({
|
|||
serverUrl: 'gitlabServerUrl',
|
||||
applicationId: 'gitlabApplicationId',
|
||||
},
|
||||
computed: {
|
||||
httpAppUrl() {
|
||||
if (constants.origin.indexOf('https://') === 0 && this.serverUrl.indexOf('http://') === 0) {
|
||||
return `${constants.origin.replace('https://', 'http://')}/app`;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// 是否使用服务端配置
|
||||
useServerConf() {
|
||||
const confClientId = store.getters['data/serverConf'].gitlabClientId;
|
||||
const confServerUrl = store.getters['data/serverConf'].gitlabUrl;
|
||||
return !!confClientId && !!confServerUrl;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
networkSvc.getServerConf();
|
||||
},
|
||||
methods: {
|
||||
resolve() {
|
||||
if (this.useServerConf) {
|
||||
this.config.resolve({});
|
||||
return;
|
||||
}
|
||||
const serverUrl = this.config.forceServerUrl || this.serverUrl;
|
||||
if (!serverUrl) {
|
||||
this.setError('serverUrl');
|
||||
|
@ -51,7 +79,7 @@ export default modalTemplate({
|
|||
this.setError('applicationId');
|
||||
}
|
||||
if (serverUrl && this.applicationId) {
|
||||
const parsedUrl = serverUrl.match(/^(https:\/\/[^/]+)/);
|
||||
const parsedUrl = serverUrl.match(/^(http[s]?:\/\/[^/]+)/);
|
||||
if (!parsedUrl) {
|
||||
this.setError('serverUrl');
|
||||
} else {
|
||||
|
|
|
@ -173,6 +173,18 @@ export default new Provider({
|
|||
},
|
||||
};
|
||||
},
|
||||
async downloadFile({ token, path }) {
|
||||
const { sha, data } = await gitlabHelper.downloadFile({
|
||||
...store.getters['workspace/currentWorkspace'],
|
||||
token,
|
||||
path,
|
||||
isImg: true,
|
||||
});
|
||||
return {
|
||||
content: data,
|
||||
sha,
|
||||
};
|
||||
},
|
||||
async downloadWorkspaceData({ token, syncData }) {
|
||||
if (!syncData) {
|
||||
return {};
|
||||
|
@ -200,18 +212,27 @@ export default new Provider({
|
|||
file,
|
||||
commitMessage,
|
||||
}) {
|
||||
const isImg = file.type === 'img';
|
||||
const path = store.getters.gitPathsByItemId[file.id];
|
||||
const absolutePath = `${store.getters['workspace/currentWorkspace'].path || ''}${path}`;
|
||||
const sha = gitWorkspaceSvc.shaByPath[path];
|
||||
const absolutePath = !isImg ? `${store.getters['workspace/currentWorkspace'].path || ''}${path}` : file.path;
|
||||
const sha = gitWorkspaceSvc.shaByPath[!isImg ? path : file.path];
|
||||
await gitlabHelper.uploadFile({
|
||||
...store.getters['workspace/currentWorkspace'],
|
||||
token,
|
||||
path: absolutePath,
|
||||
content: Provider.serializeContent(content),
|
||||
content: !isImg ? Provider.serializeContent(content) : file.content,
|
||||
sha,
|
||||
isImg,
|
||||
commitMessage,
|
||||
});
|
||||
|
||||
if (isImg) {
|
||||
const res2 = await this.downloadFile({ token, path: absolutePath });
|
||||
return {
|
||||
sha: res2.sha,
|
||||
};
|
||||
}
|
||||
|
||||
// Return new sync data
|
||||
return {
|
||||
contentSyncData: {
|
||||
|
|
|
@ -51,11 +51,22 @@ export default {
|
|||
* https://docs.gitlab.com/ee/api/oauth2.html
|
||||
*/
|
||||
async startOauth2(serverUrl, applicationId, sub = null, silent = false) {
|
||||
let apiUrl = serverUrl;
|
||||
let clientId = applicationId;
|
||||
// 获取gitea配置的参数
|
||||
await networkSvc.getServerConf();
|
||||
const confClientId = store.getters['data/serverConf'].gitlabClientId;
|
||||
const confServerUrl = store.getters['data/serverConf'].gitlabUrl;
|
||||
// 存在gitea配置则使用后端配置
|
||||
if (confClientId && confServerUrl) {
|
||||
apiUrl = confServerUrl;
|
||||
clientId = confClientId;
|
||||
}
|
||||
// Get an OAuth2 code
|
||||
const { accessToken } = await networkSvc.startOauth2(
|
||||
`${serverUrl}/oauth/authorize`,
|
||||
`${apiUrl}/oauth/authorize`,
|
||||
{
|
||||
client_id: applicationId,
|
||||
client_id: clientId,
|
||||
response_type: 'token',
|
||||
scope: 'api',
|
||||
},
|
||||
|
@ -157,14 +168,20 @@ export default {
|
|||
path,
|
||||
content,
|
||||
sha,
|
||||
isImg,
|
||||
commitMessage,
|
||||
}) {
|
||||
let uploadContent = content;
|
||||
if (isImg && typeof content !== 'string') {
|
||||
uploadContent = await utils.encodeFiletoBase64(content);
|
||||
}
|
||||
return request(token, {
|
||||
method: sha ? 'PUT' : 'POST',
|
||||
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
||||
body: {
|
||||
commit_message: commitMessage || getCommitMessage(sha ? 'updateFileMessage' : 'createFileMessage', path),
|
||||
content,
|
||||
encoding: 'base64',
|
||||
content: isImg ? uploadContent : utils.encodeBase64(content),
|
||||
last_commit_id: sha,
|
||||
branch,
|
||||
},
|
||||
|
@ -200,6 +217,7 @@ export default {
|
|||
projectId,
|
||||
branch,
|
||||
path,
|
||||
isImg,
|
||||
}) {
|
||||
const res = await request(token, {
|
||||
url: `projects/${encodeURIComponent(projectId)}/repository/files/${encodeURIComponent(path)}`,
|
||||
|
@ -207,7 +225,7 @@ export default {
|
|||
});
|
||||
return {
|
||||
sha: res.last_commit_id,
|
||||
data: utils.decodeBase64(res.content),
|
||||
data: !isImg ? utils.decodeBase64(res.content) : res.content,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -317,7 +317,7 @@ export default {
|
|||
};
|
||||
},
|
||||
parseGitlabProjectPath(url) {
|
||||
const parsedProject = url && url.match(/^https:\/\/[^/]+\/(.+?)(?:\.git|\/)?$/);
|
||||
const parsedProject = url && url.match(/^http[s]?:\/\/[^/]+\/(.+?)(?:\.git|\/)?$/);
|
||||
return parsedProject && parsedProject[1];
|
||||
},
|
||||
parseGiteaProjectPath(url) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user