支持Gitee 修复Github Oauth2授权bug
This commit is contained in:
parent
46383b5b6a
commit
e7e335d958
@ -1,4 +1,4 @@
|
|||||||
FROM benweet/stackedit-base
|
FROM node:11.15.0
|
||||||
|
|
||||||
RUN mkdir -p /opt/stackedit
|
RUN mkdir -p /opt/stackedit
|
||||||
WORKDIR /opt/stackedit
|
WORKDIR /opt/stackedit
|
||||||
|
14
README.md
14
README.md
@ -1,10 +1,22 @@
|
|||||||
# StackEdit
|
# StackEdit
|
||||||
|
|
||||||
|
从 [StackEdit 官方](https://github.com/benweet/stackedit) fork出来,然后加上了 **Gitee** 的支持,并且已经重新打了镜像,以下官方的部署方式,除了Docker镜像地址不同,其他均一致。
|
||||||
|
|
||||||
|
Fork出来修改的原因:Stackedit的作者可能因为什么原因,已经很久不维护了,Github授权登录很早之前就登录不了了,并且还没发支持国内常用的Gitee,比较蛋疼,所以想到Fork出来改,大概花了周末一整天终于改好了。
|
||||||
|
|
||||||
|
新的Docker镜像在中央仓库为:mafgwo/stackedit,当前最新版本为:5.15.1(延续原有版本号)
|
||||||
|
|
||||||
|
并增加了以下三个环境变量:
|
||||||
|
- `GITEE_CLIENT_ID` Gitee 的 Client ID
|
||||||
|
- `GITEE_CLIENT_SECRET` Gitee 的 Client Secret
|
||||||
|
- `GITEE_CALLBACK` Gitee的回调地址,Gitee授权获取token时还需要传入回调地址,格式是 http[s]://[hostname]:[port]/oauth2/callback
|
||||||
|
|
||||||
|
|
||||||
[![Build Status](https://img.shields.io/travis/benweet/stackedit.svg?style=flat)](https://travis-ci.org/benweet/stackedit) [![NPM version](https://img.shields.io/npm/v/stackedit.svg?style=flat)](https://www.npmjs.org/package/stackedit)
|
[![Build Status](https://img.shields.io/travis/benweet/stackedit.svg?style=flat)](https://travis-ci.org/benweet/stackedit) [![NPM version](https://img.shields.io/npm/v/stackedit.svg?style=flat)](https://www.npmjs.org/package/stackedit)
|
||||||
|
|
||||||
> Full-featured, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.
|
> Full-featured, open-source Markdown editor based on PageDown, the Markdown library used by Stack Overflow and the other Stack Exchange sites.
|
||||||
|
|
||||||
https://stackedit.io/
|
https://edit.qicoder.com/
|
||||||
|
|
||||||
### Ecosystem
|
### Ecosystem
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ googleClientId: ""
|
|||||||
googleApiKey: ""
|
googleApiKey: ""
|
||||||
githubClientId: ""
|
githubClientId: ""
|
||||||
githubClientSecret: ""
|
githubClientSecret: ""
|
||||||
|
giteeClientId: ""
|
||||||
|
giteeClientSecret: ""
|
||||||
wordpressClientId: ""
|
wordpressClientId: ""
|
||||||
wordpressSecret: ""
|
wordpressSecret: ""
|
||||||
paypalReceiverEmail: ""
|
paypalReceiverEmail: ""
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://stackedit.io/"
|
"https://edit.qicoder.com/"
|
||||||
],
|
],
|
||||||
"launch": {
|
"launch": {
|
||||||
"web_url": "https://stackedit.io/app"
|
"web_url": "https://edit.qicoder.com/app"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"offline_enabled": true,
|
"offline_enabled": true,
|
||||||
|
@ -23,7 +23,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
dev: {
|
dev: {
|
||||||
env: require('./dev.env'),
|
env: require('./dev.env'),
|
||||||
port: 8080,
|
port: 80,
|
||||||
autoOpenBrowser: false,
|
autoOpenBrowser: false,
|
||||||
assetsSubDirectory: 'static',
|
assetsSubDirectory: 'static',
|
||||||
assetsPublicPath: '/',
|
assetsPublicPath: '/',
|
||||||
|
13
index.html
13
index.html
@ -3,15 +3,26 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>StackEdit</title>
|
<title>StackEdit</title>
|
||||||
<link rel="canonical" href="https://stackedit.io/app">
|
<link rel="canonical" href="https://edit.qicoder.com/app">
|
||||||
<meta name="description" content="Free, open-source, full-featured Markdown editor.">
|
<meta name="description" content="Free, open-source, full-featured Markdown editor.">
|
||||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
|
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
|
<script>
|
||||||
|
var _hmt = _hmt || [];
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var hm = document.createElement("script");
|
||||||
|
hm.src = "https://hm.baidu.com/hm.js?6e5d2dbd2eeb7bba778f1056fba280d1";
|
||||||
|
var s = document.getElementsByTagName("script")[0];
|
||||||
|
s.parentNode.insertBefore(hm, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "stackedit",
|
"name": "stackedit",
|
||||||
"version": "5.14.10",
|
"version": "5.15.1",
|
||||||
"description": "Free, open-source, full-featured Markdown editor",
|
"description": "Free, open-source, full-featured Markdown editor",
|
||||||
"author": "Benoit Schweblin",
|
"author": "Benoit Schweblin",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/benweet/stackedit/issues"
|
"url": "https://github.com/mafgwo/stackedit/issues"
|
||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -8,6 +8,9 @@ const dropboxAppKey = process.env.DROPBOX_APP_KEY;
|
|||||||
const dropboxAppKeyFull = process.env.DROPBOX_APP_KEY_FULL;
|
const dropboxAppKeyFull = process.env.DROPBOX_APP_KEY_FULL;
|
||||||
const githubClientId = process.env.GITHUB_CLIENT_ID;
|
const githubClientId = process.env.GITHUB_CLIENT_ID;
|
||||||
const githubClientSecret = process.env.GITHUB_CLIENT_SECRET;
|
const githubClientSecret = process.env.GITHUB_CLIENT_SECRET;
|
||||||
|
const giteeClientId = process.env.GITEE_CLIENT_ID;
|
||||||
|
const giteeClientSecret = process.env.GITEE_CLIENT_SECRET;
|
||||||
|
const giteeCallback = process.env.GITEE_CALLBACK;
|
||||||
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
||||||
const googleApiKey = process.env.GOOGLE_API_KEY;
|
const googleApiKey = process.env.GOOGLE_API_KEY;
|
||||||
const wordpressClientId = process.env.WORDPRESS_CLIENT_ID;
|
const wordpressClientId = process.env.WORDPRESS_CLIENT_ID;
|
||||||
@ -22,6 +25,9 @@ exports.values = {
|
|||||||
dropboxAppKeyFull,
|
dropboxAppKeyFull,
|
||||||
githubClientId,
|
githubClientId,
|
||||||
githubClientSecret,
|
githubClientSecret,
|
||||||
|
giteeClientId,
|
||||||
|
giteeClientSecret,
|
||||||
|
giteeCallback,
|
||||||
googleClientId,
|
googleClientId,
|
||||||
googleApiKey,
|
googleApiKey,
|
||||||
wordpressClientId,
|
wordpressClientId,
|
||||||
@ -31,6 +37,7 @@ exports.publicValues = {
|
|||||||
dropboxAppKey,
|
dropboxAppKey,
|
||||||
dropboxAppKeyFull,
|
dropboxAppKeyFull,
|
||||||
githubClientId,
|
githubClientId,
|
||||||
|
giteeClientId,
|
||||||
googleClientId,
|
googleClientId,
|
||||||
googleApiKey,
|
googleApiKey,
|
||||||
wordpressClientId,
|
wordpressClientId,
|
||||||
|
45
server/gitee.js
Normal file
45
server/gitee.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
const qs = require('qs'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
const request = require('request');
|
||||||
|
const conf = require('./conf');
|
||||||
|
|
||||||
|
function giteeToken(clientId, code) {
|
||||||
|
console.log('clientId: ' + clientId);
|
||||||
|
console.log('code: ' + code);
|
||||||
|
console.log('client_secret: ' + conf.values.giteeClientSecret);
|
||||||
|
console.log('redirect_uri: ' + conf.values.giteeCallback);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://gitee.com/oauth/token',
|
||||||
|
form: {
|
||||||
|
client_id: clientId,
|
||||||
|
client_secret: conf.values.giteeClientSecret,
|
||||||
|
code,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
scope: 'authorization_code',
|
||||||
|
redirect_uri: conf.values.giteeCallback,
|
||||||
|
},
|
||||||
|
json: true
|
||||||
|
}, (err, res, body) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
const token = body.access_token;
|
||||||
|
if (token) {
|
||||||
|
resolve(token);
|
||||||
|
} else {
|
||||||
|
reject(res.statusCode + ',body:' + JSON.stringify(body));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.giteeToken = (req, res) => {
|
||||||
|
giteeToken(req.query.clientId, req.query.code)
|
||||||
|
.then(
|
||||||
|
token => res.send(token),
|
||||||
|
err => res
|
||||||
|
.status(400)
|
||||||
|
.send(err ? err.message || err.toString() : 'bad_code'),
|
||||||
|
);
|
||||||
|
};
|
@ -4,6 +4,7 @@ const bodyParser = require('body-parser');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const user = require('./user');
|
const user = require('./user');
|
||||||
const github = require('./github');
|
const github = require('./github');
|
||||||
|
const gitee = require('./gitee');
|
||||||
const pdf = require('./pdf');
|
const pdf = require('./pdf');
|
||||||
const pandoc = require('./pandoc');
|
const pandoc = require('./pandoc');
|
||||||
const conf = require('./conf');
|
const conf = require('./conf');
|
||||||
@ -25,6 +26,7 @@ module.exports = (app) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.get('/oauth2/githubToken', github.githubToken);
|
app.get('/oauth2/githubToken', github.githubToken);
|
||||||
|
app.get('/oauth2/giteeToken', gitee.giteeToken);
|
||||||
app.get('/conf', (req, res) => res.send(conf.publicValues));
|
app.get('/conf', (req, res) => res.send(conf.publicValues));
|
||||||
app.get('/userInfo', user.userInfo);
|
app.get('/userInfo', user.userInfo);
|
||||||
app.post('/pdfExport', pdf.generate);
|
app.post('/pdfExport', pdf.generate);
|
||||||
@ -37,6 +39,8 @@ module.exports = (app) => {
|
|||||||
app.get('/', (req, res) => res.sendFile(resolvePath('static/landing/index.html')));
|
app.get('/', (req, res) => res.sendFile(resolvePath('static/landing/index.html')));
|
||||||
// Serve sitemap.xml
|
// Serve sitemap.xml
|
||||||
app.get('/sitemap.xml', (req, res) => res.sendFile(resolvePath('static/sitemap.xml')));
|
app.get('/sitemap.xml', (req, res) => res.sendFile(resolvePath('static/sitemap.xml')));
|
||||||
|
// Serve google-api.js
|
||||||
|
app.get('/google-api.js', (req, res) => res.sendFile(resolvePath('static/google-api.js')));
|
||||||
// Serve callback.html
|
// Serve callback.html
|
||||||
app.get('/oauth2/callback', (req, res) => res.sendFile(resolvePath('static/oauth2/callback.html')));
|
app.get('/oauth2/callback', (req, res) => res.sendFile(resolvePath('static/oauth2/callback.html')));
|
||||||
// Google Drive action receiver
|
// Google Drive action receiver
|
||||||
|
5
src/assets/iconGitee.svg
Normal file
5
src/assets/iconGitee.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg t="1652950823759" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2991" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs><style type="text/css"></style></defs>
|
||||||
|
<path d="M512 1024C229.222 1024 0 794.778 0 512S229.222 0 512 0s512 229.222 512 512-229.222 512-512 512z m259.149-568.883h-290.74a25.293 25.293 0 0 0-25.292 25.293l-0.026 63.206c0 13.952 11.315 25.293 25.267 25.293h177.024c13.978 0 25.293 11.315 25.293 25.267v12.646a75.853 75.853 0 0 1-75.853 75.853h-240.23a25.293 25.293 0 0 1-25.267-25.293V417.203a75.853 75.853 0 0 1 75.827-75.853h353.946a25.293 25.293 0 0 0 25.267-25.292l0.077-63.207a25.293 25.293 0 0 0-25.268-25.293H417.152a189.62 189.62 0 0 0-189.62 189.645V771.15c0 13.977 11.316 25.293 25.294 25.293h372.94a170.65 170.65 0 0 0 170.65-170.65V480.384a25.293 25.293 0 0 0-25.293-25.267z" fill="#C71D23" p-id="2992"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="modal" v-if="config" @keydown.esc.stop="onEscape" @keydown.tab="onTab" @focusin="onFocusInOut" @focusout="onFocusInOut">
|
<div class="modal" v-if="config" @keydown.esc.stop="onEscape" @keydown.tab="onTab" @focusin="onFocusInOut" @focusout="onFocusInOut">
|
||||||
<div class="modal__sponsor-banner" v-if="!isSponsor">
|
<div class="modal__sponsor-banner" v-if="!isSponsor">
|
||||||
StackEdit is <a class="not-tabbable" target="_blank" href="https://github.com/benweet/stackedit/">open source</a>, please consider
|
StackEdit is <a class="not-tabbable" target="_blank" href="https://github.com/mafgwo/stackedit/">open source</a>, please consider
|
||||||
<a class="not-tabbable" href="javascript:void(0)" @click="sponsor">sponsoring</a> for just $5.
|
<a class="not-tabbable" href="javascript:void(0)" @click="sponsor">sponsoring</a> for just $5.
|
||||||
</div>
|
</div>
|
||||||
<component v-if="currentModalComponent" :is="currentModalComponent"></component>
|
<component v-if="currentModalComponent" :is="currentModalComponent"></component>
|
||||||
@ -56,6 +56,11 @@ import GithubWorkspaceModal from './modals/providers/GithubWorkspaceModal';
|
|||||||
import GithubPublishModal from './modals/providers/GithubPublishModal';
|
import GithubPublishModal from './modals/providers/GithubPublishModal';
|
||||||
import GistSyncModal from './modals/providers/GistSyncModal';
|
import GistSyncModal from './modals/providers/GistSyncModal';
|
||||||
import GistPublishModal from './modals/providers/GistPublishModal';
|
import GistPublishModal from './modals/providers/GistPublishModal';
|
||||||
|
import GiteeAccountModal from './modals/providers/GiteeAccountModal';
|
||||||
|
import GiteeOpenModal from './modals/providers/GiteeOpenModal';
|
||||||
|
import GiteeSaveModal from './modals/providers/GiteeSaveModal';
|
||||||
|
import GiteeWorkspaceModal from './modals/providers/GiteeWorkspaceModal';
|
||||||
|
import GiteePublishModal from './modals/providers/GiteePublishModal';
|
||||||
import GitlabAccountModal from './modals/providers/GitlabAccountModal';
|
import GitlabAccountModal from './modals/providers/GitlabAccountModal';
|
||||||
import GitlabOpenModal from './modals/providers/GitlabOpenModal';
|
import GitlabOpenModal from './modals/providers/GitlabOpenModal';
|
||||||
import GitlabPublishModal from './modals/providers/GitlabPublishModal';
|
import GitlabPublishModal from './modals/providers/GitlabPublishModal';
|
||||||
@ -107,6 +112,11 @@ export default {
|
|||||||
GithubPublishModal,
|
GithubPublishModal,
|
||||||
GistSyncModal,
|
GistSyncModal,
|
||||||
GistPublishModal,
|
GistPublishModal,
|
||||||
|
GiteeAccountModal,
|
||||||
|
GiteeOpenModal,
|
||||||
|
GiteeSaveModal,
|
||||||
|
GiteeWorkspaceModal,
|
||||||
|
GiteePublishModal,
|
||||||
GitlabAccountModal,
|
GitlabAccountModal,
|
||||||
GitlabOpenModal,
|
GitlabOpenModal,
|
||||||
GitlabPublishModal,
|
GitlabPublishModal,
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
<span v-else-if="currentWorkspace.providerId === 'githubWorkspace'">
|
<span v-else-if="currentWorkspace.providerId === 'githubWorkspace'">
|
||||||
<b>{{currentWorkspace.name}}</b> synced with a <a :href="workspaceLocationUrl" target="_blank">GitHub repo</a>.
|
<b>{{currentWorkspace.name}}</b> synced with a <a :href="workspaceLocationUrl" target="_blank">GitHub repo</a>.
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else-if="currentWorkspace.providerId === 'giteeWorkspace'">
|
||||||
|
<b>{{currentWorkspace.name}}</b> synced with a <a :href="workspaceLocationUrl" target="_blank">Gitee repo</a>.
|
||||||
|
</span>
|
||||||
<span v-else-if="currentWorkspace.providerId === 'gitlabWorkspace'">
|
<span v-else-if="currentWorkspace.providerId === 'gitlabWorkspace'">
|
||||||
<b>{{currentWorkspace.name}}</b> synced with a <a :href="workspaceLocationUrl" target="_blank">GitLab project</a>.
|
<b>{{currentWorkspace.name}}</b> synced with a <a :href="workspaceLocationUrl" target="_blank">GitLab project</a>.
|
||||||
</span>
|
</span>
|
||||||
|
@ -52,6 +52,13 @@
|
|||||||
<span>{{token.name}}</span>
|
<span>{{token.name}}</span>
|
||||||
</menu-entry>
|
</menu-entry>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-for="token in giteeTokens" :key="token.sub">
|
||||||
|
<menu-entry @click.native="publishGitee(token)">
|
||||||
|
<icon-provider slot="icon" provider-id="gitee"></icon-provider>
|
||||||
|
<div>Publish to Gitee</div>
|
||||||
|
<span>{{token.name}}</span>
|
||||||
|
</menu-entry>
|
||||||
|
</div>
|
||||||
<div v-for="token in gitlabTokens" :key="token.sub">
|
<div v-for="token in gitlabTokens" :key="token.sub">
|
||||||
<menu-entry @click.native="publishGitlab(token)">
|
<menu-entry @click.native="publishGitlab(token)">
|
||||||
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
||||||
@ -93,6 +100,10 @@
|
|||||||
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
||||||
<span>Add GitHub account</span>
|
<span>Add GitHub account</span>
|
||||||
</menu-entry>
|
</menu-entry>
|
||||||
|
<menu-entry @click.native="addGiteeAccount">
|
||||||
|
<icon-provider slot="icon" provider-id="gitee"></icon-provider>
|
||||||
|
<span>Add Gitee account</span>
|
||||||
|
</menu-entry>
|
||||||
<menu-entry @click.native="addGitlabAccount">
|
<menu-entry @click.native="addGitlabAccount">
|
||||||
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
||||||
<span>Add GitLab account</span>
|
<span>Add GitLab account</span>
|
||||||
@ -119,6 +130,7 @@ import MenuEntry from './common/MenuEntry';
|
|||||||
import googleHelper from '../../services/providers/helpers/googleHelper';
|
import googleHelper from '../../services/providers/helpers/googleHelper';
|
||||||
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
||||||
import githubHelper from '../../services/providers/helpers/githubHelper';
|
import githubHelper from '../../services/providers/helpers/githubHelper';
|
||||||
|
import giteeHelper from '../../services/providers/helpers/giteeHelper';
|
||||||
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
||||||
import wordpressHelper from '../../services/providers/helpers/wordpressHelper';
|
import wordpressHelper from '../../services/providers/helpers/wordpressHelper';
|
||||||
import zendeskHelper from '../../services/providers/helpers/zendeskHelper';
|
import zendeskHelper from '../../services/providers/helpers/zendeskHelper';
|
||||||
@ -168,6 +180,9 @@ export default {
|
|||||||
githubTokens() {
|
githubTokens() {
|
||||||
return tokensToArray(store.getters['data/githubTokensBySub']);
|
return tokensToArray(store.getters['data/githubTokensBySub']);
|
||||||
},
|
},
|
||||||
|
giteeTokens() {
|
||||||
|
return tokensToArray(store.getters['data/giteeTokensBySub']);
|
||||||
|
},
|
||||||
gitlabTokens() {
|
gitlabTokens() {
|
||||||
return tokensToArray(store.getters['data/gitlabTokensBySub']);
|
return tokensToArray(store.getters['data/gitlabTokensBySub']);
|
||||||
},
|
},
|
||||||
@ -218,6 +233,12 @@ export default {
|
|||||||
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
|
async addGiteeAccount() {
|
||||||
|
try {
|
||||||
|
await store.dispatch('modal/open', { type: 'giteeAccount' });
|
||||||
|
await giteeHelper.addAccount();
|
||||||
|
} catch (e) { /* cancel */ }
|
||||||
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
@ -245,6 +266,7 @@ export default {
|
|||||||
publishBloggerPage: publishModalOpener('bloggerPagePublish', 'publishToBloggerPage'),
|
publishBloggerPage: publishModalOpener('bloggerPagePublish', 'publishToBloggerPage'),
|
||||||
publishDropbox: publishModalOpener('dropboxPublish', 'publishToDropbox'),
|
publishDropbox: publishModalOpener('dropboxPublish', 'publishToDropbox'),
|
||||||
publishGithub: publishModalOpener('githubPublish', 'publishToGithub'),
|
publishGithub: publishModalOpener('githubPublish', 'publishToGithub'),
|
||||||
|
publishGitee: publishModalOpener('giteePublish', 'publishToGitee'),
|
||||||
publishGist: publishModalOpener('gistPublish', 'publishToGist'),
|
publishGist: publishModalOpener('gistPublish', 'publishToGist'),
|
||||||
publishGitlab: publishModalOpener('gitlabPublish', 'publishToGitlab'),
|
publishGitlab: publishModalOpener('gitlabPublish', 'publishToGitlab'),
|
||||||
publishGoogleDrive: publishModalOpener('googleDrivePublish', 'publishToGoogleDrive'),
|
publishGoogleDrive: publishModalOpener('googleDrivePublish', 'publishToGoogleDrive'),
|
||||||
|
@ -83,6 +83,10 @@
|
|||||||
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
||||||
<span>Add GitHub account</span>
|
<span>Add GitHub account</span>
|
||||||
</menu-entry>
|
</menu-entry>
|
||||||
|
<menu-entry @click.native="addGiteeAccount">
|
||||||
|
<icon-provider slot="icon" provider-id="gitee"></icon-provider>
|
||||||
|
<span>Add Gitee account</span>
|
||||||
|
</menu-entry>
|
||||||
<menu-entry @click.native="addGitlabAccount">
|
<menu-entry @click.native="addGitlabAccount">
|
||||||
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
||||||
<span>Add GitLab account</span>
|
<span>Add GitLab account</span>
|
||||||
@ -101,6 +105,7 @@ import MenuEntry from './common/MenuEntry';
|
|||||||
import googleHelper from '../../services/providers/helpers/googleHelper';
|
import googleHelper from '../../services/providers/helpers/googleHelper';
|
||||||
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
||||||
import githubHelper from '../../services/providers/helpers/githubHelper';
|
import githubHelper from '../../services/providers/helpers/githubHelper';
|
||||||
|
import giteeHelper from '../../services/providers/helpers/giteeHelper';
|
||||||
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
||||||
import googleDriveProvider from '../../services/providers/googleDriveProvider';
|
import googleDriveProvider from '../../services/providers/googleDriveProvider';
|
||||||
import dropboxProvider from '../../services/providers/dropboxProvider';
|
import dropboxProvider from '../../services/providers/dropboxProvider';
|
||||||
@ -148,6 +153,9 @@ export default {
|
|||||||
githubTokens() {
|
githubTokens() {
|
||||||
return tokensToArray(store.getters['data/githubTokensBySub']);
|
return tokensToArray(store.getters['data/githubTokensBySub']);
|
||||||
},
|
},
|
||||||
|
giteeTokens() {
|
||||||
|
return tokensToArray(store.getters['data/giteeTokensBySub']);
|
||||||
|
},
|
||||||
gitlabTokens() {
|
gitlabTokens() {
|
||||||
return tokensToArray(store.getters['data/gitlabTokensBySub']);
|
return tokensToArray(store.getters['data/gitlabTokensBySub']);
|
||||||
},
|
},
|
||||||
@ -157,7 +165,8 @@ export default {
|
|||||||
noToken() {
|
noToken() {
|
||||||
return !this.googleDriveTokens.length
|
return !this.googleDriveTokens.length
|
||||||
&& !this.dropboxTokens.length
|
&& !this.dropboxTokens.length
|
||||||
&& !this.githubTokens.length;
|
&& !this.githubTokens.length
|
||||||
|
&& !this.giteeTokens.length;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -183,6 +192,12 @@ export default {
|
|||||||
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
|
async addGiteeAccount() {
|
||||||
|
try {
|
||||||
|
await store.dispatch('modal/open', { type: 'giteeAccount' });
|
||||||
|
await giteeHelper.addAccount();
|
||||||
|
} catch (e) { /* cancel */ }
|
||||||
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
<icon-provider slot="icon" provider-id="githubWorkspace"></icon-provider>
|
<icon-provider slot="icon" provider-id="githubWorkspace"></icon-provider>
|
||||||
<span>Add a <b>GitHub</b> workspace</span>
|
<span>Add a <b>GitHub</b> workspace</span>
|
||||||
</menu-entry>
|
</menu-entry>
|
||||||
|
<menu-entry @click.native="addGiteeWorkspace">
|
||||||
|
<icon-provider slot="icon" provider-id="giteeWorkspace"></icon-provider>
|
||||||
|
<span>Add a <b>Gitee</b> workspace</span>
|
||||||
|
</menu-entry>
|
||||||
<menu-entry @click.native="addGitlabWorkspace">
|
<menu-entry @click.native="addGitlabWorkspace">
|
||||||
<icon-provider slot="icon" provider-id="gitlabWorkspace"></icon-provider>
|
<icon-provider slot="icon" provider-id="gitlabWorkspace"></icon-provider>
|
||||||
<span>Add a <b>GitLab</b> workspace</span>
|
<span>Add a <b>GitLab</b> workspace</span>
|
||||||
@ -67,6 +71,13 @@ export default {
|
|||||||
});
|
});
|
||||||
} catch (e) { /* Cancel */ }
|
} catch (e) { /* Cancel */ }
|
||||||
},
|
},
|
||||||
|
async addGiteeWorkspace() {
|
||||||
|
try {
|
||||||
|
store.dispatch('modal/open', {
|
||||||
|
type: 'giteeWorkspace',
|
||||||
|
});
|
||||||
|
} catch (e) { /* Cancel */ }
|
||||||
|
},
|
||||||
async addGitlabWorkspace() {
|
async addGitlabWorkspace() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
<modal-inner class="modal__inner-1--about-modal" aria-label="About">
|
<modal-inner class="modal__inner-1--about-modal" aria-label="About">
|
||||||
<div class="modal__content">
|
<div class="modal__content">
|
||||||
<div class="logo-background"></div>
|
<div class="logo-background"></div>
|
||||||
StackEdit on <a target="_blank" href="https://github.com/benweet/stackedit/">GitHub</a>
|
StackEdit on <a target="_blank" href="https://github.com/mafgwo/stackedit/">GitHub</a>
|
||||||
<br>
|
<br>
|
||||||
<a target="_blank" href="https://github.com/benweet/stackedit/issues">Issue tracker</a> — <a target="_blank" href="https://github.com/benweet/stackedit/releases">Changelog</a>
|
<a target="_blank" href="https://github.com/mafgwo/stackedit/issues">Issue tracker</a> — <a target="_blank" href="https://github.com/mafgwo/stackedit/releases">Changelog</a>
|
||||||
<br>
|
<br>
|
||||||
<a target="_blank" href="https://chrome.google.com/webstore/detail/iiooodelglhkcpgbajoejffhijaclcdg">Chrome app</a> — <a target="_blank" href="https://chrome.google.com/webstore/detail/ajehldoplanpchfokmeempkekhnhmoha">Chrome extension</a>
|
<a target="_blank" href="https://chrome.google.com/webstore/detail/iiooodelglhkcpgbajoejffhijaclcdg">Chrome app</a> — <a target="_blank" href="https://chrome.google.com/webstore/detail/ajehldoplanpchfokmeempkekhnhmoha">Chrome extension</a>
|
||||||
<br>
|
<br>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<br>
|
<br>
|
||||||
StackEdit on <a target="_blank" href="https://twitter.com/stackedit/">Twitter</a>
|
StackEdit on <a target="_blank" href="https://twitter.com/stackedit/">Twitter</a>
|
||||||
<hr>
|
<hr>
|
||||||
<small>© 2013-2019 Dock5 Software Ltd.<br>v{{version}}</small>
|
<small>© 2013-2022 Dock5 Software Ltd.<br>v{{version}}</small>
|
||||||
<h3>FAQ</h3>
|
<h3>FAQ</h3>
|
||||||
<div class="faq" v-html="faq"></div>
|
<div class="faq" v-html="faq"></div>
|
||||||
<div class="modal__info">
|
<div class="modal__info">
|
||||||
|
@ -49,6 +49,10 @@
|
|||||||
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
<icon-provider slot="icon" provider-id="github"></icon-provider>
|
||||||
<span>Add GitHub account</span>
|
<span>Add GitHub account</span>
|
||||||
</menu-entry>
|
</menu-entry>
|
||||||
|
<menu-entry @click.native="addGiteeAccount">
|
||||||
|
<icon-provider slot="icon" provider-id="gitee"></icon-provider>
|
||||||
|
<span>Add Gitee account</span>
|
||||||
|
</menu-entry>
|
||||||
<menu-entry @click.native="addGitlabAccount">
|
<menu-entry @click.native="addGitlabAccount">
|
||||||
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
<icon-provider slot="icon" provider-id="gitlab"></icon-provider>
|
||||||
<span>Add GitLab account</span>
|
<span>Add GitLab account</span>
|
||||||
@ -85,6 +89,7 @@ import utils from '../../services/utils';
|
|||||||
import googleHelper from '../../services/providers/helpers/googleHelper';
|
import googleHelper from '../../services/providers/helpers/googleHelper';
|
||||||
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
import dropboxHelper from '../../services/providers/helpers/dropboxHelper';
|
||||||
import githubHelper from '../../services/providers/helpers/githubHelper';
|
import githubHelper from '../../services/providers/helpers/githubHelper';
|
||||||
|
import giteeHelper from '../../services/providers/helpers/giteeHelper';
|
||||||
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
import gitlabHelper from '../../services/providers/helpers/gitlabHelper';
|
||||||
import wordpressHelper from '../../services/providers/helpers/wordpressHelper';
|
import wordpressHelper from '../../services/providers/helpers/wordpressHelper';
|
||||||
import zendeskHelper from '../../services/providers/helpers/zendeskHelper';
|
import zendeskHelper from '../../services/providers/helpers/zendeskHelper';
|
||||||
@ -128,6 +133,13 @@ export default {
|
|||||||
name: token.name,
|
name: token.name,
|
||||||
scopes: token.scopes,
|
scopes: token.scopes,
|
||||||
})),
|
})),
|
||||||
|
...Object.values(store.getters['data/giteeTokensBySub']).map(token => ({
|
||||||
|
token,
|
||||||
|
providerId: 'gitee',
|
||||||
|
userId: token.sub,
|
||||||
|
name: token.name,
|
||||||
|
scopes: ['projects', 'pull_requests'],
|
||||||
|
})),
|
||||||
...Object.values(store.getters['data/gitlabTokensBySub']).map(token => ({
|
...Object.values(store.getters['data/gitlabTokensBySub']).map(token => ({
|
||||||
token,
|
token,
|
||||||
providerId: 'gitlab',
|
providerId: 'gitlab',
|
||||||
@ -180,6 +192,12 @@ export default {
|
|||||||
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
await githubHelper.addAccount(store.getters['data/localSettings'].githubRepoFullAccess);
|
||||||
} catch (e) { /* cancel */ }
|
} catch (e) { /* cancel */ }
|
||||||
},
|
},
|
||||||
|
async addGiteeAccount() {
|
||||||
|
try {
|
||||||
|
await store.dispatch('modal/open', { type: 'giteeAccount' });
|
||||||
|
await giteeHelper.addAccount();
|
||||||
|
} catch (e) { /* cancel */ }
|
||||||
|
},
|
||||||
async addGitlabAccount() {
|
async addGitlabAccount() {
|
||||||
try {
|
try {
|
||||||
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
const { serverUrl, applicationId } = await store.dispatch('modal/open', { type: 'gitlabAccount' });
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
<span class="token key atrule">katex</span><span class="token punctuation">:</span>
|
<span class="token key atrule">katex</span><span class="token punctuation">:</span>
|
||||||
<span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
|
<span class="token key atrule">enabled</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>For the full list of options, see <a href="https://github.com/benweet/stackedit/blob/master/src/data/presets.js" target="_blank">here</a>.</p>
|
<p>For the full list of options, see <a href="https://github.com/mafgwo/stackedit/blob/master/src/data/presets.js" target="_blank">here</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,7 +45,7 @@ export default modalTemplate({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
resolve(evt) {
|
resolve(evt) {
|
||||||
evt.preventDefault(); // Fixes https://github.com/benweet/stackedit/issues/1503
|
evt.preventDefault(); // Fixes https://github.com/mafgwo/stackedit/issues/1503
|
||||||
if (!this.url) {
|
if (!this.url) {
|
||||||
this.setError('url');
|
this.setError('url');
|
||||||
} else {
|
} else {
|
||||||
|
@ -22,7 +22,7 @@ export default modalTemplate({
|
|||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
resolve(evt) {
|
resolve(evt) {
|
||||||
evt.preventDefault(); // Fixes https://github.com/benweet/stackedit/issues/1503
|
evt.preventDefault(); // Fixes https://github.com/mafgwo/stackedit/issues/1503
|
||||||
if (!this.url) {
|
if (!this.url) {
|
||||||
this.setError('url');
|
this.setError('url');
|
||||||
} else {
|
} else {
|
||||||
|
31
src/components/modals/providers/GiteeAccountModal.vue
Normal file
31
src/components/modals/providers/GiteeAccountModal.vue
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<modal-inner aria-label="Link Gitee account">
|
||||||
|
<div class="modal__content">
|
||||||
|
<div class="modal__image">
|
||||||
|
<icon-provider provider-id="gitee"></icon-provider>
|
||||||
|
</div>
|
||||||
|
<p>Link your <b>Gitee</b> account to <b>StackEdit</b>.</p>
|
||||||
|
<div class="form-entry">
|
||||||
|
<div class="form-entry__checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" v-model="repoFullAccess"> Grant access to your private repositories
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal__button-bar">
|
||||||
|
<button class="button" @click="config.reject()">Cancel</button>
|
||||||
|
<button class="button button--resolve" @click="config.resolve()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</modal-inner>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import modalTemplate from '../common/modalTemplate';
|
||||||
|
|
||||||
|
export default modalTemplate({
|
||||||
|
computedLocalSettings: {
|
||||||
|
repoFullAccess: 'giteeRepoFullAccess',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
70
src/components/modals/providers/GiteeOpenModal.vue
Normal file
70
src/components/modals/providers/GiteeOpenModal.vue
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<modal-inner aria-label="Synchronize with Gitee">
|
||||||
|
<div class="modal__content">
|
||||||
|
<div class="modal__image">
|
||||||
|
<icon-provider provider-id="gitee"></icon-provider>
|
||||||
|
</div>
|
||||||
|
<p>Open a file from your <b>Gitee</b> repository and keep it synced.</p>
|
||||||
|
<form-entry label="Repository URL" error="repoUrl">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="repoUrl" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> https://gitee.com/owner/my-repo
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="File path" error="path">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="path" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> path/to/README.md
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Branch" info="optional">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="branch" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
If not supplied, the <code>master</code> branch will be used.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
</div>
|
||||||
|
<div class="modal__button-bar">
|
||||||
|
<button class="button" @click="config.reject()">Cancel</button>
|
||||||
|
<button class="button button--resolve" @click="resolve()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</modal-inner>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import giteeProvider from '../../../services/providers/giteeProvider';
|
||||||
|
import modalTemplate from '../common/modalTemplate';
|
||||||
|
import utils from '../../../services/utils';
|
||||||
|
|
||||||
|
export default modalTemplate({
|
||||||
|
data: () => ({
|
||||||
|
branch: '',
|
||||||
|
path: '',
|
||||||
|
}),
|
||||||
|
computedLocalSettings: {
|
||||||
|
repoUrl: 'giteeRepoUrl',
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resolve() {
|
||||||
|
const parsedRepo = utils.parseGithubRepoUrl(this.repoUrl);
|
||||||
|
if (!parsedRepo) {
|
||||||
|
this.setError('repoUrl');
|
||||||
|
}
|
||||||
|
if (!this.path) {
|
||||||
|
this.setError('path');
|
||||||
|
}
|
||||||
|
if (parsedRepo && this.path) {
|
||||||
|
// Return new location
|
||||||
|
const location = giteeProvider.makeLocation(
|
||||||
|
this.config.token,
|
||||||
|
parsedRepo.owner,
|
||||||
|
parsedRepo.repo,
|
||||||
|
this.branch || 'master',
|
||||||
|
this.path,
|
||||||
|
);
|
||||||
|
this.config.resolve(location);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
86
src/components/modals/providers/GiteePublishModal.vue
Normal file
86
src/components/modals/providers/GiteePublishModal.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<modal-inner aria-label="Publish to Gitee">
|
||||||
|
<div class="modal__content">
|
||||||
|
<div class="modal__image">
|
||||||
|
<icon-provider provider-id="gitee"></icon-provider>
|
||||||
|
</div>
|
||||||
|
<p>Publish <b>{{currentFileName}}</b> to your <b>Gitee</b> repository.</p>
|
||||||
|
<form-entry label="Repository URL" error="repoUrl">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="repoUrl" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> https://gitee.com/owner/my-repo
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="File path" error="path">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="path" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> path/to/README.md<br>
|
||||||
|
If the file exists, it will be overwritten.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Branch" info="optional">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="branch" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
If not supplied, the <code>master</code> branch will be used.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Template">
|
||||||
|
<select slot="field" class="textfield" v-model="selectedTemplate" @keydown.enter="resolve()">
|
||||||
|
<option v-for="(template, id) in allTemplatesById" :key="id" :value="id">
|
||||||
|
{{ template.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<div class="form-entry__actions">
|
||||||
|
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
</div>
|
||||||
|
<div class="modal__button-bar">
|
||||||
|
<button class="button" @click="config.reject()">Cancel</button>
|
||||||
|
<button class="button button--resolve" @click="resolve()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</modal-inner>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import giteeProvider from '../../../services/providers/giteeProvider';
|
||||||
|
import modalTemplate from '../common/modalTemplate';
|
||||||
|
import utils from '../../../services/utils';
|
||||||
|
|
||||||
|
export default modalTemplate({
|
||||||
|
data: () => ({
|
||||||
|
branch: '',
|
||||||
|
path: '',
|
||||||
|
}),
|
||||||
|
computedLocalSettings: {
|
||||||
|
repoUrl: 'giteeRepoUrl',
|
||||||
|
selectedTemplate: 'giteePublishTemplate',
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.path = `${this.currentFileName}.md`;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resolve() {
|
||||||
|
const parsedRepo = utils.parseGithubRepoUrl(this.repoUrl);
|
||||||
|
if (!parsedRepo) {
|
||||||
|
this.setError('repoUrl');
|
||||||
|
}
|
||||||
|
if (!this.path) {
|
||||||
|
this.setError('path');
|
||||||
|
}
|
||||||
|
if (parsedRepo && this.path) {
|
||||||
|
// Return new location
|
||||||
|
const location = giteeProvider.makeLocation(
|
||||||
|
this.config.token,
|
||||||
|
parsedRepo.owner,
|
||||||
|
parsedRepo.repo,
|
||||||
|
this.branch || 'master',
|
||||||
|
this.path,
|
||||||
|
);
|
||||||
|
location.templateId = this.selectedTemplate;
|
||||||
|
this.config.resolve(location);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
73
src/components/modals/providers/GiteeSaveModal.vue
Normal file
73
src/components/modals/providers/GiteeSaveModal.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<modal-inner aria-label="Synchronize with Gitee">
|
||||||
|
<div class="modal__content">
|
||||||
|
<div class="modal__image">
|
||||||
|
<icon-provider provider-id="gitee"></icon-provider>
|
||||||
|
</div>
|
||||||
|
<p>Save <b>{{currentFileName}}</b> to your <b>Gitee</b> repository and keep it synced.</p>
|
||||||
|
<form-entry label="Repository URL" error="repoUrl">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="repoUrl" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> https://gitee.com/owner/my-repo
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="File path" error="path">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="path" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> path/to/README.md<br>
|
||||||
|
If the file exists, it will be overwritten.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Branch" info="optional">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="branch" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
If not supplied, the <code>master</code> branch will be used.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
</div>
|
||||||
|
<div class="modal__button-bar">
|
||||||
|
<button class="button" @click="config.reject()">Cancel</button>
|
||||||
|
<button class="button button--resolve" @click="resolve()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</modal-inner>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import giteeProvider from '../../../services/providers/giteeProvider';
|
||||||
|
import modalTemplate from '../common/modalTemplate';
|
||||||
|
import utils from '../../../services/utils';
|
||||||
|
|
||||||
|
export default modalTemplate({
|
||||||
|
data: () => ({
|
||||||
|
branch: '',
|
||||||
|
path: '',
|
||||||
|
}),
|
||||||
|
computedLocalSettings: {
|
||||||
|
repoUrl: 'giteeRepoUrl',
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.path = `${this.currentFileName}.md`;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resolve() {
|
||||||
|
const parsedRepo = utils.parseGithubRepoUrl(this.repoUrl);
|
||||||
|
if (!parsedRepo) {
|
||||||
|
this.setError('repoUrl');
|
||||||
|
}
|
||||||
|
if (!this.path) {
|
||||||
|
this.setError('path');
|
||||||
|
}
|
||||||
|
if (parsedRepo && this.path) {
|
||||||
|
const location = giteeProvider.makeLocation(
|
||||||
|
this.config.token,
|
||||||
|
parsedRepo.owner,
|
||||||
|
parsedRepo.repo,
|
||||||
|
this.branch || 'master',
|
||||||
|
this.path,
|
||||||
|
);
|
||||||
|
this.config.resolve(location);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
65
src/components/modals/providers/GiteeWorkspaceModal.vue
Normal file
65
src/components/modals/providers/GiteeWorkspaceModal.vue
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<modal-inner aria-label="Synchronize with Gitee">
|
||||||
|
<div class="modal__content">
|
||||||
|
<div class="modal__image">
|
||||||
|
<icon-provider provider-id="gitee"></icon-provider>
|
||||||
|
</div>
|
||||||
|
<p>Create a workspace synced with a <b>Gitee</b> repository folder.</p>
|
||||||
|
<form-entry label="Repository URL" error="repoUrl">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="repoUrl" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
<b>Example:</b> https://gitee.com/owner/my-repo
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Folder path" info="optional">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="path" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
If not supplied, the root folder will be used.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
<form-entry label="Branch" info="optional">
|
||||||
|
<input slot="field" class="textfield" type="text" v-model.trim="branch" @keydown.enter="resolve()">
|
||||||
|
<div class="form-entry__info">
|
||||||
|
If not supplied, the <code>master</code> branch will be used.
|
||||||
|
</div>
|
||||||
|
</form-entry>
|
||||||
|
</div>
|
||||||
|
<div class="modal__button-bar">
|
||||||
|
<button class="button" @click="config.reject()">Cancel</button>
|
||||||
|
<button class="button button--resolve" @click="resolve()">Ok</button>
|
||||||
|
</div>
|
||||||
|
</modal-inner>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import utils from '../../../services/utils';
|
||||||
|
import modalTemplate from '../common/modalTemplate';
|
||||||
|
|
||||||
|
export default modalTemplate({
|
||||||
|
data: () => ({
|
||||||
|
branch: '',
|
||||||
|
path: '',
|
||||||
|
}),
|
||||||
|
computedLocalSettings: {
|
||||||
|
repoUrl: 'giteeWorkspaceRepoUrl',
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
resolve() {
|
||||||
|
const parsedRepo = utils.parseGithubRepoUrl(this.repoUrl);
|
||||||
|
if (!parsedRepo) {
|
||||||
|
this.setError('repoUrl');
|
||||||
|
} else {
|
||||||
|
const path = this.path && this.path.replace(/^\//, '');
|
||||||
|
const url = utils.addQueryParams('app', {
|
||||||
|
...parsedRepo,
|
||||||
|
providerId: 'giteeWorkspace',
|
||||||
|
branch: this.branch || 'master',
|
||||||
|
path: path || undefined,
|
||||||
|
}, true);
|
||||||
|
this.config.resolve();
|
||||||
|
window.open(url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
@ -19,6 +19,8 @@ export default () => ({
|
|||||||
githubPublishTemplate: 'jekyllSite',
|
githubPublishTemplate: 'jekyllSite',
|
||||||
gistIsPublic: false,
|
gistIsPublic: false,
|
||||||
gistPublishTemplate: 'plainText',
|
gistPublishTemplate: 'plainText',
|
||||||
|
giteeRepoUrl: '',
|
||||||
|
giteeWorkspaceRepoUrl: '',
|
||||||
gitlabServerUrl: '',
|
gitlabServerUrl: '',
|
||||||
gitlabApplicationId: '',
|
gitlabApplicationId: '',
|
||||||
gitlabProjectUrl: '',
|
gitlabProjectUrl: '',
|
||||||
|
@ -79,16 +79,16 @@ turndown:
|
|||||||
|
|
||||||
# GitHub/GitLab commit messages
|
# GitHub/GitLab commit messages
|
||||||
git:
|
git:
|
||||||
createFileMessage: '{{path}} created from https://stackedit.io/'
|
createFileMessage: '{{path}} created from https://edit.qicoder.com/'
|
||||||
updateFileMessage: '{{path}} updated from https://stackedit.io/'
|
updateFileMessage: '{{path}} updated from https://edit.qicoder.com/'
|
||||||
deleteFileMessage: '{{path}} deleted from https://stackedit.io/'
|
deleteFileMessage: '{{path}} deleted from https://edit.qicoder.com/'
|
||||||
|
|
||||||
# Default content for new files
|
# Default content for new files
|
||||||
newFileContent: |
|
newFileContent: |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> Written with [StackEdit](https://stackedit.io/).
|
> Written with [StackEdit](https://edit.qicoder.com/).
|
||||||
|
|
||||||
# Default properties for new files
|
# Default properties for new files
|
||||||
newFileProperties: |
|
newFileProperties: |
|
||||||
|
@ -6,4 +6,4 @@ We recommend syncing your workspace to make sure files won't be lost in case you
|
|||||||
|
|
||||||
**Can StackEdit access my data without telling me?**
|
**Can StackEdit access my data without telling me?**
|
||||||
|
|
||||||
StackEdit is a browser-based application. The access tokens issued by Google, Dropbox, GitHub... are stored in your browser and are not sent to any kind of backend or 3^rd^ party so your data won't be accessed by anyone.
|
StackEdit is a browser-based application. The access tokens issued by Google, Dropbox, GitHub, Gitee... are stored in your browser and are not sent to any kind of backend or 3^rd^ party so your data won't be accessed by anyone.
|
||||||
|
@ -172,6 +172,11 @@ export default [
|
|||||||
'GitHub workspace creator',
|
'GitHub workspace creator',
|
||||||
'Use the workspace menu to create a GitHub workspace.',
|
'Use the workspace menu to create a GitHub workspace.',
|
||||||
),
|
),
|
||||||
|
new Feature(
|
||||||
|
'addGiteeWorkspace',
|
||||||
|
'GitHub workspace creator',
|
||||||
|
'Use the workspace menu to create a Gitee workspace.',
|
||||||
|
),
|
||||||
new Feature(
|
new Feature(
|
||||||
'addGitlabWorkspace',
|
'addGitlabWorkspace',
|
||||||
'GitLab workspace creator',
|
'GitLab workspace creator',
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{files.0.name}}</title>
|
<title>{{files.0.name}}</title>
|
||||||
<link rel="stylesheet" href="https://stackedit.io/style.css" />
|
<link rel="stylesheet" href="https://edit.qicoder.com/style.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
{{#if pdf}}
|
{{#if pdf}}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{files.0.name}}</title>
|
<title>{{files.0.name}}</title>
|
||||||
<link rel="stylesheet" href="https://stackedit.io/style.css" />
|
<link rel="stylesheet" href="https://edit.qicoder.com/style.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
{{#if pdf}}
|
{{#if pdf}}
|
||||||
|
@ -26,6 +26,8 @@ export default {
|
|||||||
return 'blogger';
|
return 'blogger';
|
||||||
case 'couchdbWorkspace':
|
case 'couchdbWorkspace':
|
||||||
return 'couchdb';
|
return 'couchdb';
|
||||||
|
case 'giteeWorkspace':
|
||||||
|
return 'gitee';
|
||||||
default:
|
default:
|
||||||
return this.providerId;
|
return this.providerId;
|
||||||
}
|
}
|
||||||
@ -86,4 +88,8 @@ export default {
|
|||||||
.icon-provider--couchdb {
|
.icon-provider--couchdb {
|
||||||
background-image: url(../assets/iconCouchdb.svg);
|
background-image: url(../assets/iconCouchdb.svg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-provider--gitee {
|
||||||
|
background-image: url(../assets/iconGitee.svg);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -69,7 +69,7 @@ export default {
|
|||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
script.onload = resolve;
|
script.onload = resolve;
|
||||||
script.onerror = reject;
|
script.onerror = reject;
|
||||||
script.src = `https://apis.google.com/js/api.js?${Date.now()}`;
|
script.src = `https://www.gstatic.cn/charts/loader.js?${Date.now()}`;
|
||||||
try {
|
try {
|
||||||
document.head.appendChild(script); // This can fail with bad network
|
document.head.appendChild(script); // This can fail with bad network
|
||||||
timeout = setTimeout(reject, networkTimeout);
|
timeout = setTimeout(reject, networkTimeout);
|
||||||
|
165
src/services/providers/giteeProvider.js
Normal file
165
src/services/providers/giteeProvider.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import store from '../../store';
|
||||||
|
import giteeHelper from './helpers/giteeHelper';
|
||||||
|
import Provider from './common/Provider';
|
||||||
|
import utils from '../utils';
|
||||||
|
import workspaceSvc from '../workspaceSvc';
|
||||||
|
import userSvc from '../userSvc';
|
||||||
|
|
||||||
|
const savedSha = {};
|
||||||
|
|
||||||
|
export default new Provider({
|
||||||
|
id: 'gitee',
|
||||||
|
name: 'Gitee',
|
||||||
|
getToken({ sub }) {
|
||||||
|
return store.getters['data/giteeTokensBySub'][sub];
|
||||||
|
},
|
||||||
|
getLocationUrl({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
}) {
|
||||||
|
return `https://gitee.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/tree/${encodeURIComponent(branch)}/${utils.encodeUrlPath(path)}`;
|
||||||
|
},
|
||||||
|
getLocationDescription({ path }) {
|
||||||
|
return path;
|
||||||
|
},
|
||||||
|
async downloadContent(token, syncLocation) {
|
||||||
|
const { sha, data } = await giteeHelper.downloadFile({
|
||||||
|
...syncLocation,
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
savedSha[syncLocation.id] = sha;
|
||||||
|
return Provider.parseContent(data, `${syncLocation.fileId}/content`);
|
||||||
|
},
|
||||||
|
async uploadContent(token, content, syncLocation) {
|
||||||
|
if (!savedSha[syncLocation.id]) {
|
||||||
|
try {
|
||||||
|
// Get the last sha
|
||||||
|
await this.downloadContent(token, syncLocation);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sha = savedSha[syncLocation.id];
|
||||||
|
delete savedSha[syncLocation.id];
|
||||||
|
await giteeHelper.uploadFile({
|
||||||
|
...syncLocation,
|
||||||
|
token,
|
||||||
|
content: Provider.serializeContent(content),
|
||||||
|
sha,
|
||||||
|
});
|
||||||
|
return syncLocation;
|
||||||
|
},
|
||||||
|
async publish(token, html, metadata, publishLocation) {
|
||||||
|
try {
|
||||||
|
// Get the last sha
|
||||||
|
await this.downloadContent(token, publishLocation);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore error
|
||||||
|
}
|
||||||
|
const sha = savedSha[publishLocation.id];
|
||||||
|
delete savedSha[publishLocation.id];
|
||||||
|
await giteeHelper.uploadFile({
|
||||||
|
...publishLocation,
|
||||||
|
token,
|
||||||
|
content: html,
|
||||||
|
sha,
|
||||||
|
});
|
||||||
|
return publishLocation;
|
||||||
|
},
|
||||||
|
async openFile(token, syncLocation) {
|
||||||
|
// Check if the file exists and open it
|
||||||
|
if (!Provider.openFileWithLocation(syncLocation)) {
|
||||||
|
// Download content from Gitee
|
||||||
|
let content;
|
||||||
|
try {
|
||||||
|
content = await this.downloadContent(token, syncLocation);
|
||||||
|
} catch (e) {
|
||||||
|
store.dispatch('notification/error', `Could not open file ${syncLocation.path}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the file
|
||||||
|
let name = syncLocation.path;
|
||||||
|
const slashPos = name.lastIndexOf('/');
|
||||||
|
if (slashPos > -1 && slashPos < name.length - 1) {
|
||||||
|
name = name.slice(slashPos + 1);
|
||||||
|
}
|
||||||
|
const dotPos = name.lastIndexOf('.');
|
||||||
|
if (dotPos > 0 && slashPos < name.length) {
|
||||||
|
name = name.slice(0, dotPos);
|
||||||
|
}
|
||||||
|
const item = await workspaceSvc.createFile({
|
||||||
|
name,
|
||||||
|
parentId: store.getters['file/current'].parentId,
|
||||||
|
text: content.text,
|
||||||
|
properties: content.properties,
|
||||||
|
discussions: content.discussions,
|
||||||
|
comments: content.comments,
|
||||||
|
}, true);
|
||||||
|
store.commit('file/setCurrentId', item.id);
|
||||||
|
workspaceSvc.addSyncLocation({
|
||||||
|
...syncLocation,
|
||||||
|
fileId: item.id,
|
||||||
|
});
|
||||||
|
store.dispatch('notification/info', `${store.getters['file/current'].name} was imported from Gitee.`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
makeLocation(token, owner, repo, branch, path) {
|
||||||
|
return {
|
||||||
|
providerId: this.id,
|
||||||
|
sub: token.sub,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async listFileRevisions({ token, syncLocation }) {
|
||||||
|
const entries = await giteeHelper.getCommits({
|
||||||
|
...syncLocation,
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
|
||||||
|
return entries.map(({
|
||||||
|
author,
|
||||||
|
committer,
|
||||||
|
commit,
|
||||||
|
sha,
|
||||||
|
}) => {
|
||||||
|
let user;
|
||||||
|
if (author && author.login) {
|
||||||
|
user = author;
|
||||||
|
} else if (committer && committer.login) {
|
||||||
|
user = committer;
|
||||||
|
}
|
||||||
|
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
||||||
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
|
const date = (commit.author && commit.author.date)
|
||||||
|
|| (commit.committer && commit.committer.date);
|
||||||
|
return {
|
||||||
|
id: sha,
|
||||||
|
sub,
|
||||||
|
created: date ? new Date(date).getTime() : 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async loadFileRevision() {
|
||||||
|
// Revision are already loaded
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
async getFileRevisionContent({
|
||||||
|
token,
|
||||||
|
contentId,
|
||||||
|
syncLocation,
|
||||||
|
revisionId,
|
||||||
|
}) {
|
||||||
|
const { data } = await giteeHelper.downloadFile({
|
||||||
|
...syncLocation,
|
||||||
|
token,
|
||||||
|
branch: revisionId,
|
||||||
|
});
|
||||||
|
return Provider.parseContent(data, contentId);
|
||||||
|
},
|
||||||
|
});
|
281
src/services/providers/giteeWorkspaceProvider.js
Normal file
281
src/services/providers/giteeWorkspaceProvider.js
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
import store from '../../store';
|
||||||
|
import giteeHelper from './helpers/giteeHelper';
|
||||||
|
import Provider from './common/Provider';
|
||||||
|
import utils from '../utils';
|
||||||
|
import userSvc from '../userSvc';
|
||||||
|
import gitWorkspaceSvc from '../gitWorkspaceSvc';
|
||||||
|
import badgeSvc from '../badgeSvc';
|
||||||
|
|
||||||
|
const getAbsolutePath = ({ id }) =>
|
||||||
|
`${store.getters['workspace/currentWorkspace'].path || ''}${id}`;
|
||||||
|
|
||||||
|
export default new Provider({
|
||||||
|
id: 'giteeWorkspace',
|
||||||
|
name: 'Gitee',
|
||||||
|
getToken() {
|
||||||
|
return store.getters['workspace/syncToken'];
|
||||||
|
},
|
||||||
|
getWorkspaceParams({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
providerId: this.id,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getWorkspaceLocationUrl({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
}) {
|
||||||
|
return `https://gitee.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/tree/${encodeURIComponent(branch)}/${utils.encodeUrlPath(path)}`;
|
||||||
|
},
|
||||||
|
getSyncDataUrl({ id }) {
|
||||||
|
const { owner, repo, branch } = store.getters['workspace/currentWorkspace'];
|
||||||
|
return `https://gitee.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/tree/${encodeURIComponent(branch)}/${utils.encodeUrlPath(getAbsolutePath({ id }))}`;
|
||||||
|
},
|
||||||
|
getSyncDataDescription({ id }) {
|
||||||
|
return getAbsolutePath({ id });
|
||||||
|
},
|
||||||
|
async initWorkspace() {
|
||||||
|
const { owner, repo, branch } = utils.queryParams;
|
||||||
|
const workspaceParams = this.getWorkspaceParams({ owner, repo, branch });
|
||||||
|
if (!branch) {
|
||||||
|
workspaceParams.branch = 'master';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract path param
|
||||||
|
const path = (utils.queryParams.path || '')
|
||||||
|
.trim()
|
||||||
|
.replace(/^\/*/, '') // Remove leading `/`
|
||||||
|
.replace(/\/*$/, '/'); // Add trailing `/`
|
||||||
|
if (path !== '/') {
|
||||||
|
workspaceParams.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workspaceId = utils.makeWorkspaceId(workspaceParams);
|
||||||
|
const workspace = store.getters['workspace/workspacesById'][workspaceId];
|
||||||
|
|
||||||
|
// See if we already have a token
|
||||||
|
let token;
|
||||||
|
if (workspace) {
|
||||||
|
// Token sub is in the workspace
|
||||||
|
token = store.getters['data/giteeTokensBySub'][workspace.sub];
|
||||||
|
}
|
||||||
|
if (!token) {
|
||||||
|
await store.dispatch('modal/open', { type: 'giteeAccount' });
|
||||||
|
token = await giteeHelper.addAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace) {
|
||||||
|
const pathEntries = (path || '').split('/');
|
||||||
|
const name = pathEntries[pathEntries.length - 2] || repo; // path ends with `/`
|
||||||
|
store.dispatch('workspace/patchWorkspacesById', {
|
||||||
|
[workspaceId]: {
|
||||||
|
...workspaceParams,
|
||||||
|
id: workspaceId,
|
||||||
|
sub: token.sub,
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeSvc.addBadge('addGithubWorkspace');
|
||||||
|
return store.getters['workspace/workspacesById'][workspaceId];
|
||||||
|
},
|
||||||
|
getChanges() {
|
||||||
|
return giteeHelper.getTree({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token: this.getToken(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
prepareChanges(tree) {
|
||||||
|
return gitWorkspaceSvc.makeChanges(tree);
|
||||||
|
},
|
||||||
|
async saveWorkspaceItem({ item }) {
|
||||||
|
const syncData = {
|
||||||
|
id: store.getters.gitPathsByItemId[item.id],
|
||||||
|
type: item.type,
|
||||||
|
hash: item.hash,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Files and folders are not in git, only contents
|
||||||
|
if (item.type === 'file' || item.type === 'folder') {
|
||||||
|
return { syncData };
|
||||||
|
}
|
||||||
|
|
||||||
|
// locations are stored as paths, so we upload an empty file
|
||||||
|
const syncToken = store.getters['workspace/syncToken'];
|
||||||
|
await giteeHelper.uploadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token: syncToken,
|
||||||
|
path: getAbsolutePath(syncData),
|
||||||
|
content: '',
|
||||||
|
sha: gitWorkspaceSvc.shaByPath[syncData.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return sync data to save
|
||||||
|
return { syncData };
|
||||||
|
},
|
||||||
|
async removeWorkspaceItem({ syncData }) {
|
||||||
|
if (gitWorkspaceSvc.shaByPath[syncData.id]) {
|
||||||
|
const syncToken = store.getters['workspace/syncToken'];
|
||||||
|
await giteeHelper.removeFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token: syncToken,
|
||||||
|
path: getAbsolutePath(syncData),
|
||||||
|
sha: gitWorkspaceSvc.shaByPath[syncData.id],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async downloadWorkspaceContent({
|
||||||
|
token,
|
||||||
|
contentId,
|
||||||
|
contentSyncData,
|
||||||
|
fileSyncData,
|
||||||
|
}) {
|
||||||
|
const { sha, data } = await giteeHelper.downloadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token,
|
||||||
|
path: getAbsolutePath(fileSyncData),
|
||||||
|
});
|
||||||
|
gitWorkspaceSvc.shaByPath[fileSyncData.id] = sha;
|
||||||
|
const content = Provider.parseContent(data, contentId);
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
contentSyncData: {
|
||||||
|
...contentSyncData,
|
||||||
|
hash: content.hash,
|
||||||
|
sha,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async downloadWorkspaceData({ token, syncData }) {
|
||||||
|
if (!syncData) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { sha, data } = await giteeHelper.downloadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token,
|
||||||
|
path: getAbsolutePath(syncData),
|
||||||
|
});
|
||||||
|
gitWorkspaceSvc.shaByPath[syncData.id] = sha;
|
||||||
|
const item = JSON.parse(data);
|
||||||
|
return {
|
||||||
|
item,
|
||||||
|
syncData: {
|
||||||
|
...syncData,
|
||||||
|
hash: item.hash,
|
||||||
|
sha,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async uploadWorkspaceContent({ token, content, file }) {
|
||||||
|
const path = store.getters.gitPathsByItemId[file.id];
|
||||||
|
const absolutePath = `${store.getters['workspace/currentWorkspace'].path || ''}${path}`;
|
||||||
|
const res = await giteeHelper.uploadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token,
|
||||||
|
path: absolutePath,
|
||||||
|
content: Provider.serializeContent(content),
|
||||||
|
sha: gitWorkspaceSvc.shaByPath[path],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return new sync data
|
||||||
|
return {
|
||||||
|
contentSyncData: {
|
||||||
|
id: store.getters.gitPathsByItemId[content.id],
|
||||||
|
type: content.type,
|
||||||
|
hash: content.hash,
|
||||||
|
sha: res.content.sha,
|
||||||
|
},
|
||||||
|
fileSyncData: {
|
||||||
|
id: path,
|
||||||
|
type: 'file',
|
||||||
|
hash: file.hash,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async uploadWorkspaceData({ token, item }) {
|
||||||
|
const path = store.getters.gitPathsByItemId[item.id];
|
||||||
|
const syncData = {
|
||||||
|
id: path,
|
||||||
|
type: item.type,
|
||||||
|
hash: item.hash,
|
||||||
|
};
|
||||||
|
const res = await giteeHelper.uploadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token,
|
||||||
|
path: getAbsolutePath(syncData),
|
||||||
|
content: JSON.stringify(item),
|
||||||
|
sha: gitWorkspaceSvc.shaByPath[path],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
syncData: {
|
||||||
|
...syncData,
|
||||||
|
sha: res.content.sha,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async listFileRevisions({ token, fileSyncDataId }) {
|
||||||
|
const { owner, repo, branch } = store.getters['workspace/currentWorkspace'];
|
||||||
|
const entries = await giteeHelper.getCommits({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
sha: branch,
|
||||||
|
path: getAbsolutePath({ id: fileSyncDataId }),
|
||||||
|
});
|
||||||
|
|
||||||
|
return entries.map(({
|
||||||
|
author,
|
||||||
|
committer,
|
||||||
|
commit,
|
||||||
|
sha,
|
||||||
|
}) => {
|
||||||
|
let user;
|
||||||
|
if (author && author.login) {
|
||||||
|
user = author;
|
||||||
|
} else if (committer && committer.login) {
|
||||||
|
user = committer;
|
||||||
|
}
|
||||||
|
const sub = `${giteeHelper.subPrefix}:${user.login}`;
|
||||||
|
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
|
||||||
|
const date = (commit.author && commit.author.date)
|
||||||
|
|| (commit.committer && commit.committer.date)
|
||||||
|
|| 1;
|
||||||
|
return {
|
||||||
|
id: sha,
|
||||||
|
sub,
|
||||||
|
created: new Date(date).getTime(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async loadFileRevision() {
|
||||||
|
// Revisions are already loaded
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
async getFileRevisionContent({
|
||||||
|
token,
|
||||||
|
contentId,
|
||||||
|
fileSyncDataId,
|
||||||
|
revisionId,
|
||||||
|
}) {
|
||||||
|
const { data } = await giteeHelper.downloadFile({
|
||||||
|
...store.getters['workspace/currentWorkspace'],
|
||||||
|
token,
|
||||||
|
branch: revisionId,
|
||||||
|
path: getAbsolutePath({ id: fileSyncDataId }),
|
||||||
|
});
|
||||||
|
return Provider.parseContent(data, contentId);
|
||||||
|
},
|
||||||
|
});
|
315
src/services/providers/helpers/giteeHelper.js
Normal file
315
src/services/providers/helpers/giteeHelper.js
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
import utils from '../../utils';
|
||||||
|
import networkSvc from '../../networkSvc';
|
||||||
|
import store from '../../../store';
|
||||||
|
import userSvc from '../../userSvc';
|
||||||
|
import badgeSvc from '../../badgeSvc';
|
||||||
|
|
||||||
|
const request = (token, options) => networkSvc.request({
|
||||||
|
...options,
|
||||||
|
headers: {
|
||||||
|
...options.headers || {},
|
||||||
|
Authorization: `token ${token.accessToken}`,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
...options.params || {},
|
||||||
|
t: Date.now(), // Prevent from caching
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const repoRequest = (token, owner, repo, options) => request(token, {
|
||||||
|
...options,
|
||||||
|
url: `https://gitee.com/api/v5/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${options.url}`,
|
||||||
|
})
|
||||||
|
.then(res => res.body);
|
||||||
|
|
||||||
|
const getCommitMessage = (name, path) => {
|
||||||
|
const message = store.getters['data/computedSettings'].git[name];
|
||||||
|
return message.replace(/{{path}}/g, path);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting a user from its userId is not feasible with API v3.
|
||||||
|
* Using an undocumented endpoint...
|
||||||
|
*/
|
||||||
|
const subPrefix = 'ge';
|
||||||
|
userSvc.setInfoResolver('gitee', subPrefix, async (sub) => {
|
||||||
|
try {
|
||||||
|
const user = (await networkSvc.request({
|
||||||
|
url: `https://gitee.com/api/v5/users/${sub}`,
|
||||||
|
params: {
|
||||||
|
t: Date.now(), // Prevent from caching
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: `${subPrefix}:${user.login}`,
|
||||||
|
name: user.login,
|
||||||
|
imageUrl: user.avatar_url || '',
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status !== 404) {
|
||||||
|
throw new Error('RETRY');
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
subPrefix,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/apps/building-oauth-apps/authorization-options-for-oauth-apps/
|
||||||
|
*/
|
||||||
|
async startOauth2(scopes, sub = null, silent = false) {
|
||||||
|
const clientId = store.getters['data/serverConf'].giteeClientId;
|
||||||
|
|
||||||
|
// Get an OAuth2 code
|
||||||
|
const { code } = await networkSvc.startOauth2(
|
||||||
|
'https://gitee.com/oauth/authorize',
|
||||||
|
{
|
||||||
|
client_id: clientId,
|
||||||
|
scope: 'projects pull_requests',
|
||||||
|
response_type: 'code',
|
||||||
|
},
|
||||||
|
silent,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exchange code with token
|
||||||
|
const accessToken = (await networkSvc.request({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'oauth2/giteeToken',
|
||||||
|
params: {
|
||||||
|
clientId,
|
||||||
|
code,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
|
||||||
|
// Call the user info endpoint
|
||||||
|
const user = (await networkSvc.request({
|
||||||
|
method: 'GET',
|
||||||
|
url: 'https://gitee.com/api/v5/user',
|
||||||
|
params: {
|
||||||
|
access_token: accessToken,
|
||||||
|
},
|
||||||
|
})).body;
|
||||||
|
userSvc.addUserInfo({
|
||||||
|
id: `${subPrefix}:${user.login}`,
|
||||||
|
name: user.login,
|
||||||
|
imageUrl: user.avatar_url || '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check the returned sub consistency
|
||||||
|
if (sub && `${user.login}` !== sub) {
|
||||||
|
throw new Error('Gitee account ID not expected.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build token object including scopes and sub
|
||||||
|
const token = {
|
||||||
|
scopes,
|
||||||
|
accessToken,
|
||||||
|
name: user.login,
|
||||||
|
sub: `${user.login}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add token to gitee tokens
|
||||||
|
store.dispatch('data/addGiteeToken', token);
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
async addAccount() {
|
||||||
|
const token = await this.startOauth2();
|
||||||
|
badgeSvc.addBadge('addGiteeAccount');
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/repos/commits/#get-a-single-commit
|
||||||
|
* https://developer.gitee.com/v3/git/trees/#get-a-tree
|
||||||
|
*/
|
||||||
|
async getTree({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
}) {
|
||||||
|
const { commit } = await repoRequest(token, owner, repo, {
|
||||||
|
url: `commits/${encodeURIComponent(branch)}`,
|
||||||
|
});
|
||||||
|
const { tree, truncated } = await repoRequest(token, owner, repo, {
|
||||||
|
url: `git/trees/${encodeURIComponent(commit.tree.sha)}?recursive=1`,
|
||||||
|
});
|
||||||
|
if (truncated) {
|
||||||
|
throw new Error('Git tree too big. Please remove some files in the repository.');
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/repos/commits/#list-commits-on-a-repository
|
||||||
|
*/
|
||||||
|
async getCommits({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
sha,
|
||||||
|
path,
|
||||||
|
}) {
|
||||||
|
return repoRequest(token, owner, repo, {
|
||||||
|
url: 'commits',
|
||||||
|
params: { sha, path },
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/repos/contents/#create-a-file
|
||||||
|
* https://developer.gitee.com/v3/repos/contents/#update-a-file
|
||||||
|
*/
|
||||||
|
async uploadFile({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
content,
|
||||||
|
sha,
|
||||||
|
}) {
|
||||||
|
return repoRequest(token, owner, repo, {
|
||||||
|
method: sha ? 'PUT' : 'POST',
|
||||||
|
url: `contents/${encodeURIComponent(path)}`,
|
||||||
|
body: {
|
||||||
|
message: getCommitMessage(sha ? 'updateFileMessage' : 'createFileMessage', path),
|
||||||
|
content: utils.encodeBase64(content),
|
||||||
|
sha,
|
||||||
|
branch,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/repos/contents/#delete-a-file
|
||||||
|
*/
|
||||||
|
async removeFile({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
sha,
|
||||||
|
}) {
|
||||||
|
return repoRequest(token, owner, repo, {
|
||||||
|
method: 'DELETE',
|
||||||
|
url: `contents/${encodeURIComponent(path)}`,
|
||||||
|
body: {
|
||||||
|
message: getCommitMessage('deleteFileMessage', path),
|
||||||
|
sha,
|
||||||
|
branch,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/repos/contents/#get-contents
|
||||||
|
*/
|
||||||
|
async downloadFile({
|
||||||
|
token,
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
branch,
|
||||||
|
path,
|
||||||
|
}) {
|
||||||
|
const { sha, content } = await repoRequest(token, owner, repo, {
|
||||||
|
url: `contents/${encodeURIComponent(path)}`,
|
||||||
|
params: { ref: branch },
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
sha,
|
||||||
|
data: utils.decodeBase64(content),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/gists/#create-a-gist
|
||||||
|
* https://developer.gitee.com/v3/gists/#edit-a-gist
|
||||||
|
*/
|
||||||
|
async uploadGist({
|
||||||
|
token,
|
||||||
|
description,
|
||||||
|
filename,
|
||||||
|
content,
|
||||||
|
isPublic,
|
||||||
|
gistId,
|
||||||
|
}) {
|
||||||
|
const { body } = await request(token, gistId ? {
|
||||||
|
method: 'PATCH',
|
||||||
|
url: `https://gitee.com/api/v5/gists/${gistId}`,
|
||||||
|
body: {
|
||||||
|
description,
|
||||||
|
files: {
|
||||||
|
[filename]: {
|
||||||
|
content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} : {
|
||||||
|
method: 'POST',
|
||||||
|
url: 'https://gitee.com/api/v5/gists',
|
||||||
|
body: {
|
||||||
|
description,
|
||||||
|
files: {
|
||||||
|
[filename]: {
|
||||||
|
content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
public: isPublic,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return body;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/gists/#get-a-single-gist
|
||||||
|
*/
|
||||||
|
async downloadGist({
|
||||||
|
token,
|
||||||
|
gistId,
|
||||||
|
filename,
|
||||||
|
}) {
|
||||||
|
const result = (await request(token, {
|
||||||
|
url: `https://gitee.com/api/v5/gists/${gistId}`,
|
||||||
|
})).body.files[filename];
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Gist file not found.');
|
||||||
|
}
|
||||||
|
return result.content;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/gists/#list-gist-commits
|
||||||
|
*/
|
||||||
|
async getGistCommits({
|
||||||
|
token,
|
||||||
|
gistId,
|
||||||
|
}) {
|
||||||
|
const { body } = await request(token, {
|
||||||
|
url: `https://gitee.com/api/v5/gists/${gistId}/commits`,
|
||||||
|
});
|
||||||
|
return body;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.gitee.com/v3/gists/#get-a-specific-revision-of-a-gist
|
||||||
|
*/
|
||||||
|
async downloadGistRevision({
|
||||||
|
token,
|
||||||
|
gistId,
|
||||||
|
filename,
|
||||||
|
sha,
|
||||||
|
}) {
|
||||||
|
const result = (await request(token, {
|
||||||
|
url: `https://gitee.com/api/v5/gists/${gistId}/${sha}`,
|
||||||
|
})).body.files[filename];
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Gist file not found.');
|
||||||
|
}
|
||||||
|
return result.content;
|
||||||
|
},
|
||||||
|
};
|
@ -89,8 +89,8 @@ export default {
|
|||||||
const user = (await networkSvc.request({
|
const user = (await networkSvc.request({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: 'https://api.github.com/user',
|
url: 'https://api.github.com/user',
|
||||||
params: {
|
headers: {
|
||||||
access_token: accessToken,
|
Authorization: `Bearer ${accessToken}`,
|
||||||
},
|
},
|
||||||
})).body;
|
})).body;
|
||||||
userSvc.addUserInfo({
|
userSvc.addUserInfo({
|
||||||
|
@ -625,7 +625,7 @@ export default {
|
|||||||
async openPicker(token, type = 'doc') {
|
async openPicker(token, type = 'doc') {
|
||||||
const scopes = type === 'img' ? photosScopes : getDriveScopes(token);
|
const scopes = type === 'img' ? photosScopes : getDriveScopes(token);
|
||||||
if (!window.google) {
|
if (!window.google) {
|
||||||
await networkSvc.loadScript('https://apis.google.com/js/api.js');
|
await networkSvc.loadScript('https://www.gstatic.cn/charts/loader.js');
|
||||||
await new Promise((resolve, reject) => window.gapi.load('picker', {
|
await new Promise((resolve, reject) => window.gapi.load('picker', {
|
||||||
callback: resolve,
|
callback: resolve,
|
||||||
onerror: reject,
|
onerror: reject,
|
||||||
|
@ -7,6 +7,7 @@ import providerRegistry from './providers/common/providerRegistry';
|
|||||||
import googleDriveAppDataProvider from './providers/googleDriveAppDataProvider';
|
import googleDriveAppDataProvider from './providers/googleDriveAppDataProvider';
|
||||||
import './providers/couchdbWorkspaceProvider';
|
import './providers/couchdbWorkspaceProvider';
|
||||||
import './providers/githubWorkspaceProvider';
|
import './providers/githubWorkspaceProvider';
|
||||||
|
import './providers/giteeWorkspaceProvider';
|
||||||
import './providers/gitlabWorkspaceProvider';
|
import './providers/gitlabWorkspaceProvider';
|
||||||
import './providers/googleDriveWorkspaceProvider';
|
import './providers/googleDriveWorkspaceProvider';
|
||||||
import tempFileSvc from './tempFileSvc';
|
import tempFileSvc from './tempFileSvc';
|
||||||
|
@ -211,6 +211,7 @@ export default {
|
|||||||
couchdbTokensBySub: (state, { tokensByType }) => tokensByType.couchdb || {},
|
couchdbTokensBySub: (state, { tokensByType }) => tokensByType.couchdb || {},
|
||||||
dropboxTokensBySub: (state, { tokensByType }) => tokensByType.dropbox || {},
|
dropboxTokensBySub: (state, { tokensByType }) => tokensByType.dropbox || {},
|
||||||
githubTokensBySub: (state, { tokensByType }) => tokensByType.github || {},
|
githubTokensBySub: (state, { tokensByType }) => tokensByType.github || {},
|
||||||
|
giteeTokensBySub: (state, { tokensByType }) => tokensByType.gitee || {},
|
||||||
gitlabTokensBySub: (state, { tokensByType }) => tokensByType.gitlab || {},
|
gitlabTokensBySub: (state, { tokensByType }) => tokensByType.gitlab || {},
|
||||||
wordpressTokensBySub: (state, { tokensByType }) => tokensByType.wordpress || {},
|
wordpressTokensBySub: (state, { tokensByType }) => tokensByType.wordpress || {},
|
||||||
zendeskTokensBySub: (state, { tokensByType }) => tokensByType.zendesk || {},
|
zendeskTokensBySub: (state, { tokensByType }) => tokensByType.zendesk || {},
|
||||||
@ -303,6 +304,7 @@ export default {
|
|||||||
addCouchdbToken: tokenAdder('couchdb'),
|
addCouchdbToken: tokenAdder('couchdb'),
|
||||||
addDropboxToken: tokenAdder('dropbox'),
|
addDropboxToken: tokenAdder('dropbox'),
|
||||||
addGithubToken: tokenAdder('github'),
|
addGithubToken: tokenAdder('github'),
|
||||||
|
addGiteeToken: tokenAdder('gitee'),
|
||||||
addGitlabToken: tokenAdder('gitlab'),
|
addGitlabToken: tokenAdder('gitlab'),
|
||||||
addWordpressToken: tokenAdder('wordpress'),
|
addWordpressToken: tokenAdder('wordpress'),
|
||||||
addZendeskToken: tokenAdder('zendesk'),
|
addZendeskToken: tokenAdder('zendesk'),
|
||||||
|
@ -44,9 +44,11 @@ export default {
|
|||||||
workspacesById[currentWorkspaceId] || mainWorkspace,
|
workspacesById[currentWorkspaceId] || mainWorkspace,
|
||||||
currentWorkspaceIsGit: (state, { currentWorkspace }) =>
|
currentWorkspaceIsGit: (state, { currentWorkspace }) =>
|
||||||
currentWorkspace.providerId === 'githubWorkspace'
|
currentWorkspace.providerId === 'githubWorkspace'
|
||||||
|
|| currentWorkspace.providerId === 'giteeWorkspace'
|
||||||
|| currentWorkspace.providerId === 'gitlabWorkspace',
|
|| currentWorkspace.providerId === 'gitlabWorkspace',
|
||||||
currentWorkspaceHasUniquePaths: (state, { currentWorkspace }) =>
|
currentWorkspaceHasUniquePaths: (state, { currentWorkspace }) =>
|
||||||
currentWorkspace.providerId === 'githubWorkspace'
|
currentWorkspace.providerId === 'githubWorkspace'
|
||||||
|
|| currentWorkspace.providerId === 'giteeWorkspace'
|
||||||
|| currentWorkspace.providerId === 'gitlabWorkspace',
|
|| currentWorkspace.providerId === 'gitlabWorkspace',
|
||||||
lastSyncActivityKey: (state, { currentWorkspace }) => `${currentWorkspace.id}/lastSyncActivity`,
|
lastSyncActivityKey: (state, { currentWorkspace }) => `${currentWorkspace.id}/lastSyncActivity`,
|
||||||
lastFocusKey: (state, { currentWorkspace }) => `${currentWorkspace.id}/lastWindowFocus`,
|
lastFocusKey: (state, { currentWorkspace }) => `${currentWorkspace.id}/lastWindowFocus`,
|
||||||
@ -63,6 +65,8 @@ export default {
|
|||||||
return rootGetters['data/googleTokensBySub'][currentWorkspace.sub];
|
return rootGetters['data/googleTokensBySub'][currentWorkspace.sub];
|
||||||
case 'githubWorkspace':
|
case 'githubWorkspace':
|
||||||
return rootGetters['data/githubTokensBySub'][currentWorkspace.sub];
|
return rootGetters['data/githubTokensBySub'][currentWorkspace.sub];
|
||||||
|
case 'giteeWorkspace':
|
||||||
|
return rootGetters['data/giteeTokensBySub'][currentWorkspace.sub];
|
||||||
case 'gitlabWorkspace':
|
case 'gitlabWorkspace':
|
||||||
return rootGetters['data/gitlabTokensBySub'][currentWorkspace.sub];
|
return rootGetters['data/gitlabTokensBySub'][currentWorkspace.sub];
|
||||||
case 'couchdbWorkspace':
|
case 'couchdbWorkspace':
|
||||||
@ -78,6 +82,8 @@ export default {
|
|||||||
return 'google';
|
return 'google';
|
||||||
case 'githubWorkspace':
|
case 'githubWorkspace':
|
||||||
return 'github';
|
return 'github';
|
||||||
|
case 'giteeWorkspace':
|
||||||
|
return 'gitee';
|
||||||
case 'gitlabWorkspace':
|
case 'gitlabWorkspace':
|
||||||
return 'gitlab';
|
return 'gitlab';
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>StackEdit – In-browser Markdown editor</title>
|
<title>StackEdit – In-browser Markdown editor</title>
|
||||||
<link rel="canonical" href="https://stackedit.io/">
|
<link rel="canonical" href="https://edit.qicoder.com/">
|
||||||
<link rel="icon" href="static/landing/favicon.ico" type="image/x-icon">
|
<link rel="icon" href="static/landing/favicon.ico" type="image/x-icon">
|
||||||
<link rel="shortcut icon" href="static/landing/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="static/landing/favicon.ico" type="image/x-icon">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
|
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
|
||||||
<meta name="msvalidate.01" content="5E47EE6F67B069C17E3CDD418351A612">
|
<meta name="msvalidate.01" content="5E47EE6F67B069C17E3CDD418351A612">
|
||||||
<meta name="google-site-verification" content="iWDn0T2r2_bDQWp_nW23MGePbO9X0M8wQSzbOU70pFQ" />
|
<meta name="google-site-verification" content="iWDn0T2r2_bDQWp_nW23MGePbO9X0M8wQSzbOU70pFQ" />
|
||||||
<link rel="stylesheet" href="https://stackedit.io/style.css">
|
<link rel="stylesheet" href="https://edit.qicoder.com/style.css">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
<url>
|
<url>
|
||||||
<loc>https://stackedit.io/</loc>
|
<loc>https://edit.qicoder.com/</loc>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://stackedit.io/app</loc>
|
<loc>https://edit.qicoder.com/app</loc>
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://stackedit.io/privacy_policy.html</loc>
|
<loc>https://edit.qicoder.com/privacy_policy.html</loc>
|
||||||
<changefreq>monthly</changefreq>
|
<changefreq>monthly</changefreq>
|
||||||
<priority>0.6</priority>
|
<priority>0.6</priority>
|
||||||
</url>
|
</url>
|
||||||
|
Loading…
Reference in New Issue
Block a user