This feature is restricted to sponsors as it relies on server resources.
',
diff --git a/src/data/welcomeFile.md b/src/data/welcomeFile.md
index 9de422a2..1bb5c10e 100644
--- a/src/data/welcomeFile.md
+++ b/src/data/welcomeFile.md
@@ -1,143 +1,167 @@
-# Welcome to StackEdit!
+# 欢迎来到 StackEdit!
-Hi! I'm your first Markdown file in **StackEdit**. If you want to learn about StackEdit, you can read me. If you want to play with Markdown, you can edit me. Once you have finished with me, you can create new files by opening the **file explorer** on the left corner of the navigation bar.
+你好!我是你在 **StackEdit** 中的第一个 Markdown 文件。如果你想了解 StackEdit,可以阅读我的文章。如果你想玩 Markdown,你可以编辑我。完成后,您可以通过打开导航栏左角的**文件资源管理器**来创建新文件。
-# Files
+# 文件
-StackEdit stores your files in your browser, which means all your files are automatically saved locally and are accessible **offline!**
+StackEdit 将您的文件存储在您的浏览器中,这意味着您的所有文件都会自动保存在本地并且可以**离线访问!**
-## Create files and folders
+## 创建文件和文件夹
-The file explorer is accessible using the button in left corner of the navigation bar. You can create a new file by clicking the **New file** button in the file explorer. You can also create folders by clicking the **New folder** button.
+使用导航栏左角的按钮可以访问文件资源管理器。您可以通过单击文件资源管理器中的 **创建文件** 按钮来创建新文件。您还可以通过单击 **创建文件夹** 按钮来创建文件夹。
-## Switch to another file
+## 切换到另一个文件
-All your files and folders are presented as a tree in the file explorer. You can switch from one to another by clicking a file in the tree.
+您的所有文件和文件夹在文件资源管理器中都显示为树。您可以通过单击树中的文件从一个文件切换到另一个文件。
-## Rename a file
+## 重命名文件
-You can rename the current file by clicking the file name in the navigation bar or by clicking the **Rename** button in the file explorer.
+您可以通过单击导航栏中的文件名或单击文件资源管理器中的**重命名**按钮来重命名当前文件。
-## Delete a file
+## 删除一个文件
-You can delete the current file by clicking the **Remove** button in the file explorer. The file will be moved into the **Trash** folder and automatically deleted after 7 days of inactivity.
+您可以通过单击文件资源管理器中的 **删除** 按钮来删除当前文件。该文件将被移至 **Trash** 文件夹并在 7 天不活动后自动删除。
-## Export a file
+## 导出文件
-You can export the current file by clicking **Export to disk** in the menu. You can choose to export the file as plain Markdown, as HTML using a Handlebars template or as a PDF.
+您可以通过单击菜单中的 **导出到磁盘** 来导出当前文件。您可以选择将文件导出为纯 Markdown、使用 Handlebars 模板的 HTML 或 PDF。
-# Synchronization
+# 同步
-Synchronization is one of the biggest features of StackEdit. It enables you to synchronize any file in your workspace with other files stored in your **Google Drive**, your **Dropbox** and your **GitHub** accounts. This allows you to keep writing on other devices, collaborate with people you share the file with, integrate easily into your workflow... The synchronization mechanism takes place every minute in the background, downloading, merging, and uploading file modifications.
+同步是 StackEdit 的最大特点之一。它使您可以将工作区中的任何文件与存储在 **Google Drive**、**Dropbox** 和 **GitHub** 帐户中的其他文件同步。这使您可以继续在其他设备上写作,与您共享文件的人协作,轻松集成到您的工作流程中......同步机制在后台每分钟发生一次,下载、合并和上传文件修改。
-There are two types of synchronization and they can complement each other:
+有两种类型的同步,它们可以相互补充:
-- The workspace synchronization will sync all your files, folders and settings automatically. This will allow you to fetch your workspace on any other device.
- > To start syncing your workspace, just sign in with Google in the menu.
+- 工作区同步将自动同步您的所有文件、文件夹和设置。这将允许您在任何其他设备上获取您的工作区。
+> 要开始同步您的工作区,只需在菜单中使用 Google 登录。
-- The file synchronization will keep one file of the workspace synced with one or multiple files in **Google Drive**, **Dropbox** or **GitHub**.
- > Before starting to sync files, you must link an account in the **Synchronize** sub-menu.
+- 文件同步将保持工作区的一个文件与**Google Drive**、**Dropbox**或**GitHub**中的一个或多个文件同步。
+> 在开始同步文件之前,您必须在**同步**子菜单中链接一个帐户。
-## Open a file
+## 打开一个文件
-You can open a file from **Google Drive**, **Dropbox** or **GitHub** by opening the **Synchronize** sub-menu and clicking **Open from**. Once opened in the workspace, any modification in the file will be automatically synced.
+您可以通过打开 **同步** 子菜单并单击 **Open from** 从 **Google Drive**、**Dropbox** 或 **GitHub** 打开文件。在工作区中打开后,文件中的任何修改都将自动同步。
-## Save a file
+## 保存文件
-You can save any file of the workspace to **Google Drive**, **Dropbox** or **GitHub** by opening the **Synchronize** sub-menu and clicking **Save on**. Even if a file in the workspace is already synced, you can save it to another location. StackEdit can sync one file with multiple locations and accounts.
+您可以通过打开 **同步** 子菜单并单击 **Save on** 将工作区的任何文件保存到 **Google Drive**、**Dropbox** 或 **GitHub**。即使工作区中的文件已经同步,您也可以将其保存到另一个位置。 StackEdit 可以将一个文件与多个位置和帐户同步。
-## Synchronize a file
+##同步文件
-Once your file is linked to a synchronized location, StackEdit will periodically synchronize it by downloading/uploading any modification. A merge will be performed if necessary and conflicts will be resolved.
+一旦您的文件链接到同步位置,StackEdit 将通过下载/上传任何修改来定期同步它。如有必要,将执行合并并解决冲突。
-If you just have modified your file and you want to force syncing, click the **Synchronize now** button in the navigation bar.
+如果您刚刚修改了文件并且想要强制同步,请单击导航栏中的 **Synchronize now** 按钮。
-> **Note:** The **Synchronize now** button is disabled if you have no file to synchronize.
+> **注意:** 如果您没有要同步的文件,**立即同步**按钮将被禁用。
-## Manage file synchronization
+## 管理文件同步
-Since one file can be synced with multiple locations, you can list and manage synchronized locations by clicking **File synchronization** in the **Synchronize** sub-menu. This allows you to list and remove synchronized locations that are linked to your file.
+由于一个文件可以与多个位置同步,您可以通过单击**同步**子菜单中的**文件同步**列出和管理同步位置。这允许您列出和删除链接到您的文件的同步位置。
-# Publication
+# 出版物
-Publishing in StackEdit makes it simple for you to publish online your files. Once you're happy with a file, you can publish it to different hosting platforms like **Blogger**, **Dropbox**, **Gist**, **GitHub**, **Google Drive**, **WordPress** and **Zendesk**. With [Handlebars templates](http://handlebarsjs.com/), you have full control over what you export.
+在 StackEdit 中发布使您可以轻松地在线发布文件。对文件感到满意后,您可以将其发布到不同的托管平台,例如 **Blogger**、**Dropbox**、**Gist**、**GitHub**、**Google Drive**、* *WordPress** 和 **Zendesk**。使用 [Handlebars 模板](http://handlebarsjs.com/),您可以完全控制导出的内容。
-> Before starting to publish, you must link an account in the **Publish** sub-menu.
+> 在开始发布之前,您必须在**发布**子菜单中链接一个帐户。
-## Publish a File
+## 发布文件
-You can publish your file by opening the **Publish** sub-menu and by clicking **Publish to**. For some locations, you can choose between the following formats:
+您可以通过打开 **发布** 子菜单并单击 **发布到** 来发布您的文件。对于某些位置,您可以选择以下格式:
-- Markdown: publish the Markdown text on a website that can interpret it (**GitHub** for instance),
-- HTML: publish the file converted to HTML via a Handlebars template (on a blog for example).
+- Markdown:在可以解释的网站上发布 Markdown 文本(例如**GitHub**),
+- HTML:通过 Handlebars 模板发布转换为 HTML 的文件(例如在博客上)。
-## Update a publication
+## 更新出版物
-After publishing, StackEdit keeps your file linked to that publication which makes it easy for you to re-publish it. Once you have modified your file and you want to update your publication, click on the **Publish now** button in the navigation bar.
+发布后,StackEdit 会将您的文件链接到该出版物,这使您可以轻松地重新发布它。一旦您修改了文件并想要更新您的出版物,请单击导航栏中的**立即发布**按钮。
-> **Note:** The **Publish now** button is disabled if your file has not been published yet.
+> **注意:** 如果您没有要同步的文件,**立即同步**按钮将被禁用。
-## Manage file publication
+## 管理文件同步
-Since one file can be published to multiple locations, you can list and manage publish locations by clicking **File publication** in the **Publish** sub-menu. This allows you to list and remove publication locations that are linked to your file.
+由于一个文件可以与多个位置同步,您可以通过单击**同步**子菜单中的**文件同步**列出和管理同步位置。这允许您列出和删除链接到您的文件的同步位置。
-# Markdown extensions
+# 出版物
-StackEdit extends the standard Markdown syntax by adding extra **Markdown extensions**, providing you with some nice features.
+在 StackEdit 中发布使您可以轻松地在线发布文件。对文件感到满意后,您可以将其发布到不同的托管平台,例如 **Blogger**、**Dropbox**、**Gist**、**GitHub**、**Google Drive**、* *WordPress** 和 **Zendesk**。使用 [Handlebars 模板](http://handlebarsjs.com/),您可以完全控制导出的内容。
-> **ProTip:** You can disable any **Markdown extension** in the **File properties** dialog.
+> 在开始发布之前,您必须在**发布**子菜单中链接一个帐户。
+
+## 发布文件
+
+您可以通过打开 **发布** 子菜单并单击 **发布到** 来发布您的文件。对于某些位置,您可以选择以下格式:
+
+- Markdown:在可以解释的网站上发布 Markdown 文本(例如**GitHub**),
+- HTML:通过 Handlebars 模板发布转换为 HTML 的文件(例如在博客上)。
+
+## 更新出版物
+
+发布后,StackEdit 会将您的文件链接到该出版物,这使您可以轻松地重新发布它。一旦您修改了文件并想要更新您的出版物,请单击导航栏中的**立即发布**按钮。
+
+> **注意:** 如果您的文件尚未发布,则 **立即发布** 按钮将被禁用。
+
+## 管理文件发布
+
+由于一个文件可以发布到多个位置,您可以通过单击**发布**子菜单中的**文件发布**来列出和管理发布位置。这允许您列出和删除链接到您的文件的发布位置。
+
+
+# Markdown扩展
+
+StackEdit 通过添加额外的 **Markdown扩展** 扩展了标准 Markdown 语法,为您提供了一些不错的功能。
+
+> **专业提示:** 您可以在 **文件属性** 对话框中禁用任何 **Markdown 扩展名**。
## SmartyPants
-SmartyPants converts ASCII punctuation characters into "smart" typographic punctuation HTML entities. For example:
+SmartyPants 将 ASCII 标点字符转换为“智能”印刷标点 HTML 实体。例如:
-| |ASCII |HTML |
-|----------------|-------------------------------|-----------------------------|
-|Single backticks|`'Isn't this fun?'` |'Isn't this fun?' |
-|Quotes |`"Isn't this fun?"` |"Isn't this fun?" |
-|Dashes |`-- is en-dash, --- is em-dash`|-- is en-dash, --- is em-dash|
+| |ASCII |HTML |
+|----------------|--------------------------------| ------------------------------|
+|单反引号|`'这不好玩吗?'` |'这不好玩吗? |
+|引用|`“这不好玩吗?”` |“这不好玩吗?” |
+|破折号 |`-- 是破折号,--- 是破折号`|-- 是破折号,--- 是破折号|
## KaTeX
-You can render LaTeX mathematical expressions using [KaTeX](https://khan.github.io/KaTeX/):
+您可以使用 [KaTeX](https://khan.github.io/KaTeX/) 渲染 LaTeX 数学表达式:
-The *Gamma function* satisfying $\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N$ is via the Euler integral
+满足 $\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N$ 的 *Gamma 函数* 是通过欧拉积分
$$
\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.
$$
-> You can find more information about **LaTeX** mathematical expressions [here](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).
+> 您可以在 [这里](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference) 找到有关 **LaTeX** 数学表达式的更多信息。
-## UML diagrams
+## UML 图
-You can render UML diagrams using [Mermaid](https://mermaidjs.github.io/). For example, this will produce a sequence diagram:
+您可以使用 [Mermaid](https://mermaidjs.github.io/) 渲染 UML 图。例如,这将产生一个序列图:
```mermaid
sequenceDiagram
-Alice ->> Bob: Hello Bob, how are you?
-Bob-->>John: How about you John?
-Bob--x Alice: I am good thanks!
-Bob-x John: I am good thanks!
-Note right of John: Bob thinks a long long time, so long that the text does not fit on a row.
+爱丽丝 ->> 鲍勃: 你好鲍勃,你好吗?
+鲍勃-->>约翰: 约翰,你呢?
+鲍勃--x 爱丽丝: 我很好,谢谢!
+鲍勃-x 约翰: 我很好,谢谢!
+Note right of 约翰: 鲍勃想了很长 很长的时间,太长了 文本确实 不能放在一行中。
-Bob-->Alice: Checking with John...
-Alice->John: Yes... John, how are you?
+鲍勃-->爱丽丝: 正在和 John 核对...
+爱丽丝->约翰: 是的……约翰,你好吗?
```
-And this will produce a flow chart:
+这将产生一个流程图:
```mermaid
graph LR
-A[Square Rect] -- Link text --> B((Circle))
-A --> C(Round Rect)
-B --> D{Rhombus}
+A[Square Rect] -- 链接文本 --> B((Circle))
+A --> C(圆角矩形)
+B --> D{菱形}
C --> D
-```
+```
\ No newline at end of file
diff --git a/src/services/badgeSvc.js b/src/services/badgeSvc.js
index d627d349..964aea85 100644
--- a/src/services/badgeSvc.js
+++ b/src/services/badgeSvc.js
@@ -8,8 +8,8 @@ const showInfo = () => {
.filter(badge => badge.isEarned && !lastEarnedFeatureIds.has(badge.featureId));
if (earnedBadges.length) {
store.dispatch('notification/badge', earnedBadges.length > 1
- ? `You've earned ${earnedBadges.length} badges: ${earnedBadges.map(badge => `"${badge.name}"`).join(', ')}.`
- : `You've earned 1 badge: "${earnedBadges[0].name}".`);
+ ? `您已获得 ${earnedBadges.length} 个徽章: ${earnedBadges.map(badge => `"${badge.name}"`).join(', ')}.`
+ : `您已获得 1 个徽章: "${earnedBadges[0].name}".`);
}
lastEarnedFeatureIds = null;
};
diff --git a/src/services/providers/giteaProvider.js b/src/services/providers/giteaProvider.js
index bb77496f..df88d84c 100644
--- a/src/services/providers/giteaProvider.js
+++ b/src/services/providers/giteaProvider.js
@@ -135,17 +135,24 @@ export default new Provider({
token,
});
- return entries.map((entry) => {
- const email = entry.author_email || entry.committer_email;
- const sub = `${giteaHelper.subPrefix}:${token.serverUrl}/${email}`;
- userSvc.addUserInfo({
- id: sub,
- name: entry.author_name || entry.committer_name,
- imageUrl: '',
- });
- const date = entry.authored_date || entry.committed_date || 1;
+ return entries.map(({
+ author,
+ committer,
+ commit,
+ sha,
+ }) => {
+ let user;
+ if (author && author.login) {
+ user = author;
+ } else if (committer && committer.login) {
+ user = committer;
+ }
+ const sub = `${giteaHelper.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: entry.id,
+ id: sha,
sub,
created: date ? new Date(date).getTime() : 1,
};
diff --git a/src/services/providers/giteaWorkspaceProvider.js b/src/services/providers/giteaWorkspaceProvider.js
index 0ae8d0d5..fc1cd52a 100644
--- a/src/services/providers/giteaWorkspaceProvider.js
+++ b/src/services/providers/giteaWorkspaceProvider.js
@@ -251,19 +251,27 @@ export default new Provider({
path: getAbsolutePath({ id: fileSyncDataId }),
});
- return entries.map((entry) => {
- const email = entry.author_email || entry.committer_email;
- const sub = `${giteaHelper.subPrefix}:${token.serverUrl}/${email}`;
- userSvc.addUserInfo({
- id: sub,
- name: entry.author_name || entry.committer_name,
- imageUrl: '', // No way to get user's avatar url...
- });
- const date = entry.authored_date || entry.committed_date || 1;
+ return entries.map(({
+ author,
+ committer,
+ commit,
+ sha,
+ }) => {
+ let user;
+ if (author && author.login) {
+ user = author;
+ } else if (committer && committer.login) {
+ user = committer;
+ }
+ const sub = `${giteaHelper.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: entry.id,
+ id: sha,
sub,
- created: date ? new Date(date).getTime() : 1,
+ created: new Date(date).getTime(),
};
});
},
diff --git a/src/services/providers/giteeProvider.js b/src/services/providers/giteeProvider.js
index 9c68dacd..0e719d47 100644
--- a/src/services/providers/giteeProvider.js
+++ b/src/services/providers/giteeProvider.js
@@ -135,6 +135,9 @@ export default new Provider({
user = committer;
}
const sub = `${giteeHelper.subPrefix}:${user.login}`;
+ if (user.avatar_url && user.avatar_url.endsWith('.png')) {
+ user.avatar_url = `${user.avatar_url}!avatar60`;
+ }
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
const date = (commit.author && commit.author.date)
|| (commit.committer && commit.committer.date);
diff --git a/src/services/providers/giteeWorkspaceProvider.js b/src/services/providers/giteeWorkspaceProvider.js
index 3d5ec740..4617d3a5 100644
--- a/src/services/providers/giteeWorkspaceProvider.js
+++ b/src/services/providers/giteeWorkspaceProvider.js
@@ -249,6 +249,9 @@ export default new Provider({
user = committer;
}
const sub = `${giteeHelper.subPrefix}:${user.login}`;
+ if (user.avatar_url && user.avatar_url.endsWith('.png')) {
+ user.avatar_url = `${user.avatar_url}!avatar60`;
+ }
userSvc.addUserInfo({ id: sub, name: user.login, imageUrl: user.avatar_url });
const date = (commit.author && commit.author.date)
|| (commit.committer && commit.committer.date)
diff --git a/src/services/providers/helpers/giteaHelper.js b/src/services/providers/helpers/giteaHelper.js
index 62d5268d..53fc8618 100644
--- a/src/services/providers/helpers/giteaHelper.js
+++ b/src/services/providers/helpers/giteaHelper.js
@@ -5,6 +5,8 @@ import userSvc from '../../userSvc';
import badgeSvc from '../../badgeSvc';
import constants from '../../../data/constants';
+const tokenExpirationMargin = 5 * 60 * 1000;
+
const request = ({ accessToken, serverUrl }, options) => networkSvc.request({
...options,
url: `${serverUrl}/api/v1/${options.url}`,
@@ -51,30 +53,50 @@ export default {
/**
* https://docs.gitea.io/en-us/oauth2-provider/
*/
- async startOauth2(serverUrl, applicationId, applicationSecret, sub = null, silent = false) {
- // Get an OAuth2 code
- const { code } = await networkSvc.startOauth2(
- `${serverUrl}/login/oauth/authorize`,
- {
- client_id: applicationId,
- response_type: 'code',
- redirect_uri: constants.oauth2RedirectUri,
- },
- silent,
- );
+ async startOauth2(
+ serverUrl, applicationId, applicationSecret,
+ sub = null, silent = false, refreshToken,
+ ) {
+ let tokenBody;
+ if (!silent) {
+ // Get an OAuth2 code
+ const { code } = await networkSvc.startOauth2(
+ `${serverUrl}/login/oauth/authorize`,
+ {
+ client_id: applicationId,
+ response_type: 'code',
+ redirect_uri: constants.oauth2RedirectUri,
+ },
+ silent,
+ );
+ // Exchange code with token
+ tokenBody = (await networkSvc.request({
+ method: 'POST',
+ url: `${serverUrl}/login/oauth/access_token`,
+ body: {
+ client_id: applicationId,
+ client_secret: applicationSecret,
+ code,
+ grant_type: 'authorization_code',
+ redirect_uri: constants.oauth2RedirectUri,
+ },
+ })).body;
+ } else {
+ // Exchange refreshToken with token
+ tokenBody = (await networkSvc.request({
+ method: 'POST',
+ url: `${serverUrl}/login/oauth/access_token`,
+ body: {
+ client_id: applicationId,
+ client_secret: applicationSecret,
+ refresh_token: refreshToken,
+ grant_type: 'refresh_token',
+ redirect_uri: constants.oauth2RedirectUri,
+ },
+ })).body;
+ }
- // Exchange code with token
- const accessToken = (await networkSvc.request({
- method: 'POST',
- url: `${serverUrl}/login/oauth/access_token`,
- body: {
- client_id: applicationId,
- client_secret: applicationSecret,
- code,
- grant_type: 'authorization_code',
- redirect_uri: constants.oauth2RedirectUri,
- },
- })).body.access_token;
+ const accessToken = tokenBody.access_token;
// Call the user info endpoint
const user = await request({ accessToken, serverUrl }, {
@@ -96,6 +118,8 @@ export default {
const token = {
accessToken,
name: user.username,
+ refreshToken: tokenBody.refresh_token,
+ expiresOn: Date.now() + (tokenBody.expires_in * 1000),
serverUrl,
sub: uniqueSub,
};
@@ -104,6 +128,47 @@ export default {
store.dispatch('data/addGiteaToken', token);
return token;
},
+ // 刷新token
+ async refreshToken(token) {
+ const {
+ serverUrl,
+ applicationId,
+ applicationSecret,
+ sub,
+ } = token;
+ const lastToken = store.getters['data/giteaTokensBySub'][sub];
+ // 兼容旧的没有过期时间
+ if (!lastToken.expiresOn) {
+ await store.dispatch('modal/open', {
+ type: 'providerRedirection',
+ name: 'Gitea',
+ });
+ return this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
+ }
+ // lastToken is not expired
+ if (lastToken.expiresOn > Date.now() + tokenExpirationMargin) {
+ return lastToken;
+ }
+
+ // existing token is about to expire.
+ // Try to get a new token in background
+ try {
+ return await this.startOauth2(
+ serverUrl, applicationId, applicationSecret,
+ sub, true, lastToken.refreshToken,
+ );
+ } catch (err) {
+ // If it fails try to popup a window
+ if (store.state.offline) {
+ throw err;
+ }
+ await store.dispatch('modal/open', {
+ type: 'providerRedirection',
+ name: 'Gitea',
+ });
+ return this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
+ }
+ },
async addAccount(serverUrl, applicationId, applicationSecret, sub = null) {
const token = await this.startOauth2(serverUrl, applicationId, applicationSecret, sub);
badgeSvc.addBadge('addGiteaAccount');
@@ -129,7 +194,8 @@ export default {
projectId,
branch,
}) {
- return request(token, {
+ const refreshedToken = await this.refreshToken(token);
+ return request(refreshedToken, {
url: `repos/${projectId}/git/trees/${branch}`,
params: {
recursive: true,
@@ -147,7 +213,8 @@ export default {
branch,
path,
}) {
- return request(token, {
+ const refreshedToken = await this.refreshToken(token);
+ return request(refreshedToken, {
url: `repos/${projectId}/commits`,
params: {
sha: branch,
@@ -168,7 +235,8 @@ export default {
content,
sha,
}) {
- return request(token, {
+ const refreshedToken = await this.refreshToken(token);
+ return request(refreshedToken, {
method: sha ? 'PUT' : 'POST',
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
body: {
@@ -190,7 +258,8 @@ export default {
path,
sha,
}) {
- return request(token, {
+ const refreshedToken = await this.refreshToken(token);
+ return request(refreshedToken, {
method: 'DELETE',
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
body: {
@@ -210,7 +279,8 @@ export default {
branch,
path,
}) {
- const { sha, content } = await request(token, {
+ const refreshedToken = await this.refreshToken(token);
+ const { sha, content } = await request(refreshedToken, {
url: `repos/${projectId}/contents/${encodeURIComponent(path)}`,
params: { ref: branch },
});
diff --git a/src/services/providers/helpers/giteeHelper.js b/src/services/providers/helpers/giteeHelper.js
index ffae68ab..59b02227 100644
--- a/src/services/providers/helpers/giteeHelper.js
+++ b/src/services/providers/helpers/giteeHelper.js
@@ -139,7 +139,7 @@ export default {
return this.startOauth2();
}
// lastToken is not expired
- if (lastToken.expiresOn > Date.now() - tokenExpirationMargin) {
+ if (lastToken.expiresOn > Date.now() + tokenExpirationMargin) {
return lastToken;
}
diff --git a/src/services/timeSvc.js b/src/services/timeSvc.js
index 8b157ed2..f8895639 100644
--- a/src/services/timeSvc.js
+++ b/src/services/timeSvc.js
@@ -138,21 +138,21 @@ class RelativeTime {
const hr = Math.round(min / 60);
const day = Math.round(hr / 24);
if (ms < 0) {
- return 'just now';
+ return '刚刚';
} else if (sec < 45) {
- return 'just now';
+ return '刚刚';
} else if (sec < 90) {
- return 'a minute ago';
+ return '1分钟前';
} else if (min < 45) {
- return `${min} minutes ago`;
+ return `${min}分钟前`;
} else if (min < 90) {
- return 'an hour ago';
+ return '1小时前';
} else if (hr < 24) {
- return `${hr} hours ago`;
+ return `${hr}小时前`;
} else if (hr < 36) {
- return 'a day ago';
+ return '1天前';
} else if (day < 30) {
- return `${day} days ago`;
+ return `${day}天前`;
}
return null;
}
diff --git a/src/store/explorer.js b/src/store/explorer.js
index e4f1eb2f..98469815 100644
--- a/src/store/explorer.js
+++ b/src/store/explorer.js
@@ -89,7 +89,7 @@ export default {
// Create Trash node
const trashFolderNode = new Node(emptyFolder(), [], true);
trashFolderNode.item.id = 'trash';
- trashFolderNode.item.name = 'Trash';
+ trashFolderNode.item.name = '回收站';
trashFolderNode.noDrag = true;
trashFolderNode.isTrash = true;
trashFolderNode.parentNode = rootNode;
@@ -97,7 +97,7 @@ export default {
// Create Temp node
const tempFolderNode = new Node(emptyFolder(), [], true);
tempFolderNode.item.id = 'temp';
- tempFolderNode.item.name = 'Temp';
+ tempFolderNode.item.name = '临时目录';
tempFolderNode.noDrag = true;
tempFolderNode.noDrop = true;
tempFolderNode.isTemp = true;
diff --git a/static/landing/index.html b/static/landing/index.html
index ecc21dd1..25b939bd 100644
--- a/static/landing/index.html
+++ b/static/landing/index.html
@@ -2,7 +2,7 @@
- StackEdit – In-browser Markdown editor
+ StackEdit中文版 – 浏览器内 Markdown 编辑器
@@ -271,20 +271,20 @@
Whether you write, you review, you comment… StackEdit's layout provides you with the flexibility you need, without sacrifice.
+
智能布局
+
无论你是写作、阅读还是评论……StackEdit的布局都为你提供了所需的灵活性。
@@ -332,17 +332,17 @@
-
Live preview with Scroll Sync
-
StackEdit’s Scroll Sync feature accurately binds the scrollbars of the editor panel and the preview panel to ensure that you always keep an eye on the output while writing.
StackEdit can sync your files with Google Drive, Dropbox and GitHub. It can also publish them as blog posts to Blogger, WordPress and Zendesk. You can choose whether to upload in Markdown format, HTML, or to format the output using the Handlebars template engine.
With StackEdit, you can share collaborative workspaces, thanks to the synchronization mechanism. If two collaborators are working on the same file at the same time, StackEdit takes care of merging the changes.
StackEdit supports different Markdown flavors such as Markdown Extra, GFM and CommonMark. Each Markdown feature can be enabled or disabled at your convenience.