1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-19 18:29:23 +00:00

Merge pull request #5818 from haiwen/update-seafile-editor

Update seafile editor
This commit is contained in:
杨顺强
2023-12-11 09:37:44 +08:00
committed by GitHub
49 changed files with 12925 additions and 5893 deletions

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line strict
'use strict';
const fs = require('fs');
@@ -20,7 +21,7 @@ const getClientEnvironment = require('./env');
const paths = require('./paths');
const modules = require('./modules');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const webpackBundleTracker = require('webpack-bundle-tracker');
const ForkTsCheckerWebpackPlugin =
@@ -608,7 +609,7 @@ module.exports = function (webpackEnv) {
},
plugins: [
new webpack.ProvidePlugin({
process: "process/browser.js",
process: 'process/browser.js',
}),
new NodePolyfillPlugin({
excludeAliases: ['console'],

11958
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@
"@seafile/resumablejs": "1.1.16",
"@seafile/sdoc-editor": "0.3.23",
"@seafile/seafile-calendar": "0.0.12",
"@seafile/seafile-editor": "0.4.8",
"@seafile/seafile-editor": "1.0.6",
"@uiw/codemirror-extensions-langs": "^4.19.4",
"@uiw/react-codemirror": "^4.19.4",
"classnames": "^2.2.6",
@@ -17,9 +17,9 @@
"crypto-js": "4.2.0",
"deep-copy": "1.4.2",
"glamor": "^2.20.40",
"i18next": "22.4.6",
"i18next-browser-languagedetector": "7.0.1",
"i18next-xhr-backend": "3.2.2",
"i18next": "^17.0.13",
"i18next-browser-languagedetector": "^3.0.3",
"i18next-xhr-backend": "^3.1.2",
"is-hotkey": "0.2.0",
"MD5": "^1.3.0",
"moment": "^2.22.2",
@@ -32,7 +32,7 @@
"react-chartjs-2": "^2.8.0",
"react-cookies": "^0.1.0",
"react-dom": "17.0.0",
"react-i18next": "12.1.1",
"react-i18next": "^10.12.2",
"react-responsive": "9.0.2",
"react-select": "5.7.0",
"react-transition-group": "4.4.5",

View File

@@ -2,7 +2,7 @@ import i18n from 'i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import { mediaUrl } from './utils/constants';
import { mediaUrl } from '../utils/constants';
const lang = window.app.pageOptions.lang;
@@ -14,7 +14,7 @@ i18n
lng: lang,
fallbackLng: 'en',
ns: ['seafile-editor'],
defaultNS: 'translations',
defaultNS: 'seafile-editor',
whitelist: ['en', 'zh-CN', 'fr', 'de', 'cs', 'es', 'es-AR', 'es-MX', 'ru'],

View File

@@ -13,6 +13,14 @@ const propTypes = {
class TermsEditorDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
isValueChanged: false,
};
this.editorRef = React.createRef();
}
static defaultProps = {
title: gettext('Terms'),
};
@@ -22,20 +30,20 @@ class TermsEditorDialog extends React.Component {
};
toggle = () => {
if (this.isContentChanged()) {
const { isValueChanged } = this.state;
if (isValueChanged) {
let currentContent = this.getCurrentContent();
this.props.onCommit(currentContent);
}
this.props.onCloseEditorDialog();
};
isContentChanged = () => {
return this.simpleEditor.hasContentChange();
onContentChanged = () => {
return this.setState({isValueChanged: true});
};
getCurrentContent = () => {
let markdownContent = this.simpleEditor.getMarkdown();
return markdownContent;
return this.editorRef.current.getValue();
};
setSimpleEditorRef = (editor) => {
@@ -58,8 +66,9 @@ class TermsEditorDialog extends React.Component {
<ModalHeader className="conditions-editor-dialog-title" toggle={this.toggle}>{title}</ModalHeader>
<ModalBody className={'conditions-editor-dialog-main'}>
<SimpleEditor
onRef={this.setSimpleEditorRef.bind(this)}
ref={this.editorRef}
value={content || ''}
onContentChanged={this.onContentChanged}
/>
</ModalBody>
</Modal>

View File

@@ -9,15 +9,14 @@ const { fileContent } = window.app.pageOptions;
class FileContent extends React.Component {
render() {
return (
<div className="file-view-content flex-1 o-auto">
<div className="md-content">
<div className="file-view-content md-content">
<MarkdownViewer
markdownContent={fileContent}
showTOC={false}
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
isFetching={false}
value={fileContent}
isShowOutline={false}
mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'}
/>
</div>
</div>
);
}
}

View File

@@ -1,300 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { repoID, slug, serviceURL, isPublicWiki } from '../utils/constants';
import { Utils } from '../utils/utils';
import { deserialize } from '@seafile/seafile-editor';
import'../css/index-viewer.css';
const viewerPropTypes = {
indexContent: PropTypes.string.isRequired,
onLinkClick: PropTypes.func.isRequired,
};
class TreeNode {
constructor({ name, href, parentNode }) {
this.name = name;
this.href = href;
this.parentNode = parentNode || null;
this.children = [];
}
setParent(parentNode) {
this.parentNode = parentNode;
}
addChildren(nodeList) {
nodeList.forEach((node) => {
node.setParent(this);
});
this.children = nodeList;
}
}
class IndexContentViewer extends React.Component {
constructor(props) {
super(props);
this.links = [];
this.treeRoot = new TreeNode({ name: '', href: '' });
this.state = {
currentPath: '',
};
}
UNSAFE_componentWillMount() {
this.getRootNode();
}
componentDidMount() {
this.bindClickEvent();
}
UNSAFE_componentWillReceiveProps() {
this.removeClickEvent();
}
componentDidUpdate() {
this.bindClickEvent();
}
componentWillUnmount() {
this.removeClickEvent();
}
bindClickEvent = () => {
const contentClass = 'wiki-nav-content';
this.links = document.querySelectorAll(`.${contentClass} a`);
this.links.forEach(link => {
link.addEventListener('click', this.onLinkClick);
});
};
removeClickEvent = () => {
this.links.forEach(link => {
link.removeEventListener('click', this.onLinkClick);
});
};
onLinkClick = (event) => {
event.preventDefault();
const currentPath = event.target.getAttribute('data-path');
if (currentPath === this.state.currentPath) {
return;
} else if (currentPath) {
this.setState({ currentPath: currentPath });
}
const link = this.getLink(event.target);
if (link) this.props.onLinkClick(link);
};
getLink = (node) => {
const tagName = node.tagName;
if (!tagName || tagName === 'HTML') return;
if (tagName === 'A') {
return node.href;
} else {
return this.getLink(node.parentNode);
}
};
changeInlineNode = (item) => {
if (item.type == 'link' || item.type === 'image') {
let url;
// change image url
if (item.type == 'image' && isPublicWiki) {
url = item.data.src;
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
// different repo
if (!re.test(url)) {
return;
}
// get image path
let index = url.indexOf('/file');
let index2 = url.indexOf('?');
const imagePath = url.substring(index + 5, index2);
// replace url
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
}
else if (item.type == 'link') {
url = item.data.href;
/* eslint-disable */
let expression = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/
/* eslint-enable */
let re = new RegExp(expression);
// Solving relative paths
if (!re.test(url)) {
item.data.href = serviceURL + '/published/' + slug + '/' + url;
}
// change file url
else if (Utils.isInternalMarkdownLink(url, repoID)) {
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
// replace url
item.data.href = serviceURL + '/published/' + slug + path;
}
// change dir url
else if (Utils.isInternalDirLink(url, repoID)) {
let path = Utils.getPathFromInternalDirLink(url, repoID);
// replace url
item.data.href = serviceURL + '/published/' + slug + path;
}
}
}
return item;
};
getRootNode = () => {
let value = deserialize(this.props.indexContent);
const newNodes = Utils.changeMarkdownNodes(value, this.changeInlineNode);
newNodes.forEach((node) => {
if (node.type === 'unordered_list' || node.type === 'ordered_list') {
let treeRoot = this.transSlateToTree(node.children, this.treeRoot);
this.setNodePath(treeRoot, '/');
this.treeRoot = treeRoot;
}
});
};
setNodePath = (node, parentNodePath) => {
let name = node.name;
let path = parentNodePath === '/' ? parentNodePath + name : parentNodePath + '/' + name;
node.path = path;
if (node.children.length > 0) {
node.children.forEach(child => {
this.setNodePath(child, path);
});
}
};
// slateNodes is list items of an unordered list or ordered list, translate them to treeNode and add to parentTreeNode
transSlateToTree = (slateNodes, parentTreeNode) => {
let treeNodes = slateNodes.map((slateNode) => {
// item has children(unordered list)
if (slateNode.children.length === 2 && (slateNode.children[1].type === 'unordered_list' || slateNode.children[1].type === 'ordered_list')) {
// slateNode.nodes[0] is paragraph, create TreeNode, set name and href
const paragraphNode = slateNode.children[0];
const treeNode = this.transParagraph(paragraphNode);
// slateNode.nodes[1] is list, set it as TreeNode's children
const listNode = slateNode.children[1];
// Add sub list items to the tree node
return this.transSlateToTree(listNode.children, treeNode);
} else {
// item doesn't have children list
if (slateNode.children[0] && (slateNode.children[0].type === 'paragraph')) {
return this.transParagraph(slateNode.children[0]);
} else {
// list item contain table/code_block/blockqupta
return new TreeNode({ name: '', href: '' });
}
}
});
parentTreeNode.addChildren(treeNodes);
return parentTreeNode;
};
// translate slate_paragraph_node to treeNode
transParagraph = (paragraphNode) => {
let treeNode;
if (paragraphNode.children[1] && paragraphNode.children[1].type === 'link') {
// paragraph node is a link node
const linkNode = paragraphNode.children[1];
const textNode = linkNode.children[0];
let name = textNode ? textNode.text : '';
treeNode = new TreeNode({ name: name, href: linkNode.data.href });
} else if (paragraphNode.children[0]) {
// paragraph first child node is a text node, then get node name
const textNode = paragraphNode.children[0];
let name = textNode.text ? textNode.text : '';
treeNode = new TreeNode({ name: name, href: '' });
} else {
treeNode = new TreeNode({ name: '', href: '' });
}
return treeNode;
};
render() {
return (
<div className="mx-4 o-hidden">
<FolderItem node={this.treeRoot} bindClickEvent={this.bindClickEvent} currentPath={this.state.currentPath}/>
</div>
);
}
}
IndexContentViewer.propTypes = viewerPropTypes;
const FolderItemPropTypes = {
node: PropTypes.object.isRequired,
bindClickEvent: PropTypes.func.isRequired,
currentPath: PropTypes.string,
};
class FolderItem extends React.Component {
constructor(props) {
super(props);
this.state = {
expanded: false
};
}
toggleExpanded = () => {
this.setState({ expanded: !this.state.expanded }, () => {
if (this.state.expanded) this.props.bindClickEvent();
});
};
renderLink = ({ href, name, path }) => {
const className = `wiki-nav-content ${path === this.props.currentPath ? 'wiki-nav-content-highlight' : ''}`;
if (href && name) {
return <div className={className}><a href={href} data-path={path} onClick={this.toggleExpanded} title={name}>{name}</a></div>;
} else if (name) {
return <div className="wiki-nav-content"><span onClick={this.toggleExpanded} title={name}>{name}</span></div>;
} else {
return null;
}
};
componentDidMount() {
if (this.props.node && !this.props.node.parentNode) {
this.setState({ expanded: true }, () => {
this.props.bindClickEvent();
});
}
}
render() {
const { node } = this.props;
if (node.children.length > 0) {
return (
<React.Fragment>
{node.parentNode &&
<React.Fragment>
<span className="switch-btn" onClick={this.toggleExpanded}>
{this.state.expanded ? <i className="fa fa-caret-down"></i> : <i className="fa fa-caret-right"></i>}
</span>
{this.renderLink(node)}
</React.Fragment>
}
{this.state.expanded && node.children.map((child, index) => {
return (
<div className="pl-4 position-relative" key={index}>
<FolderItem node={child} bindClickEvent={this.props.bindClickEvent} currentPath={this.props.currentPath}/>
</div>
);
})}
</React.Fragment>
);
} else {
return this.renderLink(node);
}
}
}
FolderItem.propTypes = FolderItemPropTypes;
export default IndexContentViewer;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { MarkdownViewer } from '@seafile/seafile-editor';
import { gettext, repoID, slug, serviceURL, isPublicWiki, sharedToken, mediaUrl } from '../utils/constants';
import { EXTERNAL_EVENTS, EventBus, MarkdownViewer } from '@seafile/seafile-editor';
import { gettext, isPublicWiki, mediaUrl, repoID, serviceURL, sharedToken, slug } from '../utils/constants';
import Loading from './loading';
import { Utils } from '../utils/utils';
@@ -25,109 +25,30 @@ class WikiMarkdownViewer extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTitleIndex: 0,
};
this.markdownContainer = React.createRef();
this.links = [];
this.titlesInfo = [];
this.scrollRef = React.createRef();
}
componentDidMount() {
// Bind event when first loaded
this.links = document.querySelectorAll(`.${contentClass} a`);
this.links.forEach(link => {
link.addEventListener('click', this.onLinkClick);
});
this.getTitlesInfo();
const eventBus = EventBus.getInstance();
this.unsubscribeLinkClick = eventBus.subscribe(EXTERNAL_EVENTS.ON_LINK_CLICK, this.onLinkClick);
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.markdownContent === nextProps.markdownContent) {
return;
}
// Unbound event when updating
this.links.forEach(link => {
link.removeEventListener('click', this.onLinkClick);
});
}
componentDidUpdate() {
// Update completed, rebind event
this.links = document.querySelectorAll(`.${contentClass} a`);
this.links.forEach(link => {
link.addEventListener('click', this.onLinkClick);
});
if (this.titlesInfo.length === 0) {
this.getTitlesInfo();
}
}
componentWillUnmount() {
// Unbound events when the component is destroyed
this.links.forEach(link => {
link.removeEventListener('click', this.onLinkClick);
});
this.unsubscribeLinkClick();
}
getTitlesInfo = () => {
let titlesInfo = [];
const titleDom = document.querySelectorAll('h1[id^="user-content"]')[0];
if (titleDom) {
const id = titleDom.getAttribute('id');
let content = id && id.replace('user-content-', '');
content = content ? `${content} - ${slug}` : slug;
Utils.updateTabTitle(content);
}
let headingList = document.querySelectorAll('h2[id^="user-content"], h3[id^="user-content"]');
for (let i = 0; i < headingList.length; i++) {
titlesInfo.push(headingList[i].offsetTop);
}
this.titlesInfo = titlesInfo;
};
onLinkClick = (event) => {
event.preventDefault();
event.stopPropagation();
let link = '';
if (event.target.tagName !== 'A') {
let target = event.target.parentNode;
while (target.tagName !== 'A') {
let target = event.target;
while (!target.dataset || !target.dataset.url) {
target = target.parentNode;
}
link = target.href;
} else {
link = event.target.href;
}
if (!target) return;
link = target.dataset.url;
this.props.onLinkClick(link);
};
onScrollHandler = () => {
const contentScrollTop = this.markdownContainer.current.scrollTop + 180;
let titlesLength = this.titlesInfo.length;
let activeTitleIndex;
if (contentScrollTop <= this.titlesInfo[0]) {
activeTitleIndex = 0;
this.setState({activeTitleIndex: activeTitleIndex});
return;
}
if (contentScrollTop > this.titlesInfo[titlesLength - 1]) {
activeTitleIndex = this.titlesInfo.length - 1;
this.setState({activeTitleIndex: activeTitleIndex});
return;
}
for (let i = 0; i < titlesLength; i++) {
if (contentScrollTop > this.titlesInfo[i]) {
continue;
} else {
activeTitleIndex = i - 1;
break;
}
}
this.setState({activeTitleIndex: activeTitleIndex});
};
changeInlineNode = (item) => {
let url, imagePath;
@@ -149,21 +70,21 @@ class WikiMarkdownViewer extends React.Component {
}
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
} else if (item.type == 'link') { // change link url
url = item.data.href;
url = item.url;
if (Utils.isInternalFileLink(url, repoID)) { // change file url
if (Utils.isInternalMarkdownLink(url, repoID)) {
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
// replace url
item.data.href = serviceURL + '/published/' + slug + path;
item.url = serviceURL + '/published/' + slug + path;
} else {
item.data.href = url.replace(/(.*)lib\/([-0-9a-f]{36})\/file(.*)/g, (match, p1, p2, p3) => {
item.url = url.replace(/(.*)lib\/([-0-9a-f]{36})\/file(.*)/g, (match, p1, p2, p3) => {
return `${p1}d/${sharedToken}/files/?p=${p3}&dl=1`;
});
}
} else if (Utils.isInternalDirLink(url, repoID)) { // change dir url
let path = Utils.getPathFromInternalDirLink(url, repoID);
// replace url
item.data.href = serviceURL + '/published/' + slug + path;
item.url = serviceURL + '/published/' + slug + path;
}
}
@@ -176,30 +97,16 @@ class WikiMarkdownViewer extends React.Component {
};
renderMarkdown = () => {
let isTOCShow = true;
if (this.props.isTOCShow === false) {
isTOCShow = false;
}
if (this.props.isWiki) {
return (
<MarkdownViewer
showTOC={isTOCShow}
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
markdownContent={this.props.markdownContent}
activeTitleIndex={this.state.activeTitleIndex}
modifyValueBeforeRender={this.modifyValueBeforeRender}
/>
);
}
const { isTOCShow = true, isWiki, markdownContent } = this.props;
const props = {
isShowOutline: isTOCShow,
mathJaxSource: `${mediaUrl}js/mathjax/tex-svg.js`,
value: markdownContent,
scrollRef: this.scrollRef,
...(isWiki && {beforeRenderCallback: this.modifyValueBeforeRender})
};
return (
<MarkdownViewer
showTOC={isTOCShow}
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
markdownContent={this.props.markdownContent}
activeTitleIndex={this.state.activeTitleIndex}
/>
);
return <MarkdownViewer {...props} />;
};
render() {
@@ -209,7 +116,7 @@ class WikiMarkdownViewer extends React.Component {
// In dir-column-file repoID is one of props, width is 100%; In wiki-viewer repoID is not props, width isn't 100%
let contentClassName = `${this.props.repoID ? contentClass + ' w-100' : contentClass}`;
return (
<div ref={this.markdownContainer} className="wiki-page-container" onScroll={this.onScrollHandler.bind(this)}>
<div ref={this.scrollRef} className="wiki-page-container">
<div className={contentClassName}>
{this.props.children}
{this.renderMarkdown()}

View File

@@ -1,102 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
const itemPropTypes = {
activeIndex: PropTypes.number.isRequired,
item: PropTypes.object.isRequired,
handleNavItemClick: PropTypes.func.isRequired,
};
class WikiOutlineItem extends React.Component {
handleNavItemClick = () => {
var activeId = this.props.item.id;
this.props.handleNavItemClick(activeId);
};
render() {
let item = this.props.item;
let activeIndex = parseInt(this.props.activeIndex);
let levelClass = item.depth === 3 ? ' textindent-2' : '';
let activeClass = item.key === activeIndex ? ' wiki-outline-item-active' : '';
let clazz = 'wiki-outline-item'+ levelClass + activeClass;
return (
<li className={clazz} data-index={item.key} onClick={this.handleNavItemClick}>
<a href={item.id} title={item.text}>{item.text}</a>
</li>
);
}
}
WikiOutlineItem.propTypes = itemPropTypes;
const outlinePropTypes = {
navItems: PropTypes.array.isRequired,
activeId: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]).isRequired,
handleNavItemClick: PropTypes.func.isRequired,
};
class WikiOutline extends React.Component {
constructor(props) {
super(props);
this.state = {
activeIndex : 0,
scrollTop: 0,
};
}
UNSAFE_componentWillReceiveProps(nextProps) {
let _this = this;
let activeId = nextProps.activeId;
let navItems = nextProps.navItems;
let length = navItems.length;
for (let i = 0; i < length; i++) {
let flag = false;
let item = navItems[i];
if (item.id === activeId && item.key !== _this.state.activeIndex) {
let scrollTop = 0;
if (item.key > 20) {
scrollTop = - (item.key - 20)*27 + 'px';
if (parseInt(scrollTop) > 0) { // handle scroll quickly;
scrollTop = 0;
}
}
_this.setState({
activeIndex : item.key,
scrollTop: scrollTop
});
flag = true;
}
if (flag) {
break;
}
}
}
render() {
let style = {top: this.state.scrollTop};
return (
<ul className="wiki-viewer-outline" ref="outlineContainer" style={style}>
{this.props.navItems.map(item => {
return (
<WikiOutlineItem
key={item.key}
item={item}
activeIndex={this.state.activeIndex}
handleNavItemClick={this.props.handleNavItemClick}
/>
);
})}
</ul>
);
}
}
WikiOutline.propTypes = outlinePropTypes;
export default WikiOutline;

View File

@@ -1,3 +1,9 @@
#wrapper {
height: 100%;
width: 100%;
display: flex;
}
.header .button-group {
display: flex;
align-items: center;

View File

@@ -29,20 +29,20 @@
}
.content-viewer {
flex: 1;
display: flex;
min-height: 0;
}
.content-viewer .sf-slate-viewer-scroll-container {
background-color: #fafaf9;
border-radius: 10px;
overflow: auto;
padding: 20px 40px;
display: block;
}
.markdown-viewer-render-content {
background-color: #fff;
word-break: break-word;
margin: 20px 40px;
border: 1px solid #e6e6dd;
}
.markdown-viewer-render-content .diff-view {
padding: 40px 60px;
.content-viewer .sf-slate-viewer-article-container .article {
width: 100%;
max-width: 100%;
}
.panel-header {
@@ -124,10 +124,14 @@
.history-content .main-panel {
max-width: 100%;
}
.markdown-viewer-render-content {
margin: 20px;
.content-viewer .sf-slate-viewer-scroll-container {
padding: 20px;
}
.markdown-viewer-render-content .diff-view {
.content-viewer .sf-slate-viewer-article-container {
margin: 0;
padding: 0;
}
.content-viewer .sf-slate-viewer-article-container .article {
padding: 20px;
}
}

View File

@@ -205,8 +205,17 @@
background-color: #f6f6f6;
}
.wiki-page-content .sf-slate-viewer-scroll-container {
padding: 0;
background-color: #fff;
border: none;
overflow: inherit;
}
.dir-content-main .wiki-page-content .article {
margin: 0;
padding: 0 10px;
border: none;
}
.wiki-page-content a {

View File

@@ -1,3 +1,8 @@
html, body, #root {
width: 100%;
height: 100%;
}
#root {
display: flex;
flex-direction: column;
@@ -168,3 +173,10 @@
margin-left: 0.5rem;
color: #888;
}
.sf-md-viewer-content {
flex: 1;
display: flex;
min-height: 0;
min-width: 0;
}

View File

@@ -1,9 +1,14 @@
.md-content {
box-shadow: 0 0 6px #ccc;
border: 1px solid #ccc;
padding: 70px 75px;
width: calc(100% - 40px);
max-width: 950px;
background: #fff;
margin: 0 auto;
.file-view-content.md-content {
width: 100%;
height: 100%;
background: #f4f4f4;
border-right: none;
padding: 0;
display: flex;
}
.md-content .sf-slate-viewer-scroll-container .article {
border: 1px solid #ccc;
box-shadow: 0 0 6px #ccc;
padding: 70px 75px;
}

View File

@@ -48,24 +48,14 @@
overflow: auto;
}
.shared-file-view-body .article {
min-height: calc(100% - 15px);
background: #fff;
padding: 40px 60px;
margin: 0 340px 15px 40px;
border: 1px solid #e6e6dd;
.shared-file-view-body.md-view {
padding: 0;
display: flex;
min-height: 0;
}
.shared-file-view-body .article-no-outline {
max-width: 950px;
margin: 0 auto 15px;
}
.shared-file-view-body .seafile-markdown-outline {
width: 300px;
top: 145px;
bottom: 30px;
height: auto;
.shared-file-view-body .sf-slate-viewer-outline {
top: 145px !important;
}
@media (max-width: 991.98px) {
@@ -73,27 +63,4 @@
width: 100%;
padding: 10px 20px;
}
.shared-file-view-body .md-view {
width: 95%;
}
.shared-file-view-body .md-view {
padding: 55px 50px;
}
}
@media (max-width: 768px) {
.shared-file-view-body .md-view {
padding: 0 10px;
width: 100%;
}
.shared-file-view-body .md-view .article {
display: flex;
padding: 20px;
margin: 0;
}
.shared-file-view-body .seafile-markdown-outline {
display: none;
}
}

View File

@@ -1,251 +0,0 @@
.wiki-side-panel .panel-top {
background: #fff;
}
.wiki-side-nav {
flex:auto;
display:flex;
flex-direction:column;
overflow:hidden; /* for ff */
border-right:1px solid #eee;
}
.wiki-pages-heading {
position: relative;
font-size: 1rem;
font-weight: normal;
padding: 0.5rem 0 0.5rem 2rem;
border-bottom: 1px solid #e8e8e8;
line-height: 1.5;
height: 40px;
background-color: #f9f9f9;
margin-bottom: 0;
}
.heading-icon {
position: absolute;
right: 1rem;
top: 25%;
color: #888;
font-size: 0.8125rem;
}
.wiki-pages-container {
flex: 1;
overflow: hidden;
padding-bottom: 10px;
}
.wiki-pages-container:hover {
overflow: auto;
}
.wiki-pages-container .tree-view {
margin-left: -10px;
padding-left:0;
}
.wiki-pages-container .article {
padding: 0 20px;
}
.wiki-pages-container .tree-view {
margin-top: 14px;
}
.wiki-md-viewer-rendered-content {
padding: 30px 0 0;
}
img[src=""] {
opacity: 0;
}
.wiki-side-panel {
flex: 0 0 20%;
display:flex;
flex-direction:column;
overflow:hidden;
}
@media (max-width: 767px) {
.wiki-side-panel {
z-index: 1051;
}
}
.wiki-main-panel {
flex: 1 0 80%;
display:flex;
flex-direction:column;
min-height: 0;
}
.wiki-main-panel .main-panel-north {
background-color: #fff;
}
.cur-view-content .wiki-page-container {
margin: 0 -1rem -1.25rem;
padding: 30px 1rem 1.25rem;
display: flex;
flex: 1;
padding-left: 30px;
overflow-y: auto;
}
.wiki-main-panel .cur-view-content .article {
padding: 0 10px;
}
.wiki-main-panel .cur-view-content .article h1 {
margin-top: 0;
}
.cur-view-content .wiki-page-container .outline-h2,
.cur-view-content .wiki-page-container .outline-h3 {
height: 24px;
font-size: 12px;
color: #4d5156;
}
.cur-view-content .wiki-page-container .outline-h2.active,
.cur-view-content .wiki-page-container .outline-h3.active {
color: #eb8205;
}
.cur-view-content .wiki-page-container .seafile-markdown-outline {
overflow-y: hidden;
margin-right: 10px;
}
.cur-view-content .wiki-page-container .seafile-markdown-outline:hover {
overflow-y: auto;
}
.cur-view-content .wiki-page-content {
width: calc(100% - 200px);
padding-right: 30px;
}
.cur-view-content .wiki-page-content .seafile-markdown-outline {
position: fixed;
padding-right: 1rem;
top: 79px;
right: 0;
width: 200px;
overflow: hidden;
}
.wiki-hide {
display: none !important;
}
@media (max-width: 991.98px) {
.cur-view-content .wiki-page-container {
padding: 0 14px;
padding-top: 30px;
}
.cur-view-content .wiki-page-content {
width: 100%;
padding-right: 0;
}
.cur-view-content .seafile-markdown-outline {
display: none;
}
}
.wiki-main .wiki-viewer-outline {
position: relative;
top: 0;
padding: 0;
list-style: none;
border-left: solid 1px #eee;
}
.textindent-2 {
text-indent: 18px;
}
.wiki-main .wiki-outline-item {
padding: 3px 15px;
font-size: 14px;
}
.wiki-outline-item a {
display: block;
color: #444;
text-decoration: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.wiki-outline-item a:hover {
color: #eb8205;
text-decoration: underline;
}
.wiki-outline-item-active {
border-left: 1px solid #eb8205;
}
.wiki-outline-item-active a {
color: #eb8205 !important;
}
.wiki-page-ops {
position:fixed;
top:10px;
}
@media (min-width: 768px) {
.wiki-page-ops:before {
content:'';
border-left:1px solid #ddd;
position:absolute;
top:3px;
left:-16px;
bottom:3px;
}
}
.wiki-page-list-item {
word-break:break-all;
line-height:1.6;
margin:3px 0;
}
.wiki-page-link,
.wiki-page-link:hover {
font-size:1.15em;
font-weight:normal;
color:#444;
margin-left:5px;
}
#wiki-page-last-modified {
padding: 40px 10px;
font-size:12px;
color: #666;
}
.wiki-md-viewer-rendered-content.article h1 {
margin-top: 0;
}
.wiki-page-content a {
cursor: pointer;
}
.wiki-side-nav .wiki-page-content a {
color: #212529;
cursor: pointer;
}
.index-edit {
position: absolute;
right: 0.25rem;
top: 0.25rem;
}
.wiki-main-panel .wiki-page-content .ml-2 {
text-decoration: underline;
}
.wiki-main-panel .wiki-page-content .ml-2:hover {
text-decoration: underline;
color:#eb8205;
}

View File

@@ -1,737 +1,15 @@
import React from 'react';
import ReactDom from 'react-dom';
import PropTypes from 'prop-types';
import axios from 'axios';
import classnames from 'classnames';
import { Button, Tooltip, Nav, NavItem, NavLink, TabContent, TabPane } from 'reactstrap';
/* eslint-disable */
import Prism from 'prismjs';
/* eslint-enable */
import { ReactEditor, DiffViewer } from '@seafile/seafile-editor';
import { siteRoot, gettext, draftOriginFilePath, draftFilePath, author, authorAvatar, originFileExists, draftFileExists, draftID, draftFileName, draftRepoID, draftStatus, draftPublishVersion, originFileVersion, filePermission, serviceURL, mediaUrl } from './utils/constants';
import { seafileAPI } from './utils/seafile-api';
import Loading from './components/loading';
import AddReviewerDialog from './components/dialog/add-reviewer-dialog';
import HistoryList from './pages/review/history-list';
import ModalPortal from './components/modal-portal';
import './css/layout.css';
import './css/toolbar.css';
import './css/dirent-detail.css';
import './css/draft.css';
const URL = require('url-parse');
var moment = require('moment');
const { toDOMNode } = ReactEditor;
class Draft extends React.Component {
constructor(props) {
super(props);
this.state = {
draftContent: '',
draftOriginContent: '',
draftInfo: {},
isLoading: true,
isShowDiff: true,
showDiffTip: false,
activeTab: 'reviewInfo',
changedNodes: [],
originRepoName: '',
activeItem: null,
historyList: [],
showReviewerDialog: false,
reviewers: [],
draftStatus: draftStatus,
};
this.quote = '';
this.newIndex = null;
this.oldIndex = null;
this.changeIndex = -1;
this.range = null;
}
initialContent = () => {
switch(draftStatus) {
case 'open':
if (!draftFileExists) {
this.setState({
isLoading: false,
isShowDiff: false
});
return;
}
if (!originFileExists) {
seafileAPI.getFileDownloadLink(draftRepoID, draftFilePath)
.then(res => {
seafileAPI.getFileContent(res.data)
.then(res => {
this.setState({
draftContent: res.data,
draftOriginContent: res.data,
isLoading: false,
isShowDiff: false
});
});
});
return;
}
// eslint-disable-next-line
const hash = window.location.hash;
if (hash.indexOf('#history-') === 0) {
const currentCommitID = hash.slice(9, 49);
const preCommitID = hash.slice(50, 90);
let preItemFilePath, currentItemFilePath;
this.setState({
isLoading: false,
activeTab: 'history',
});
seafileAPI.listFileHistoryRecords(draftRepoID, draftFilePath, 1, 25).then((res) => {
const historyList = res.data.data;
this.setState({
historyList: historyList,
totalReversionCount: res.data.total_count
});
for (let i = 0, length = historyList.length; i < length; i++) {
if (preCommitID === historyList[i].commit_id) {
this.setState({
activeItem: i
});
preItemFilePath = historyList[i].path;
}
if (currentCommitID === historyList[i].commit_id) {
currentItemFilePath = historyList[i].path;
}
if (preItemFilePath && currentItemFilePath) break;
}
axios.all([
seafileAPI.getFileRevision(draftRepoID, currentCommitID, currentItemFilePath),
seafileAPI.getFileRevision(draftRepoID, preCommitID, preItemFilePath)
]).then(axios.spread((res1, res2) => {
axios.all([seafileAPI.getFileContent(res1.data), seafileAPI.getFileContent(res2.data)]).then(axios.spread((content1, content2) => {
this.setDiffViewerContent(content2.data, content1.data);
}));
}));
return;
});
} else {
axios.all([
seafileAPI.getFileDownloadLink(draftRepoID, draftFilePath),
seafileAPI.getFileDownloadLink(draftRepoID, draftOriginFilePath)
]).then(axios.spread((res1, res2) => {
axios.all([
seafileAPI.getFileContent(res1.data),
seafileAPI.getFileContent(res2.data)
]).then(axios.spread((draftContent, draftOriginContent) => {
this.setState({
draftContent: draftContent.data,
draftOriginContent: draftOriginContent.data,
isLoading: false
});
let that = this;
setTimeout(() => {
that.getChangedNodes();
}, 100);
}));
}));
}
break;
case 'published':
if (!originFileExists) {
this.setState({
isLoading: false,
isShowDiff: false
});
return;
}
// eslint-disable-next-line
let dl0 = siteRoot + 'repo/' + draftRepoID + '/' + draftPublishVersion + '/download?' + 'p=' + draftOriginFilePath;
// eslint-disable-next-line
let dl = siteRoot + 'repo/' + draftRepoID + '/' + originFileVersion + '/download?' + 'p=' + draftOriginFilePath;
axios.all([
seafileAPI.getFileContent(dl0),
seafileAPI.getFileContent(dl)
]).then(axios.spread((draftContent, draftOriginContent) => {
this.setState({
draftContent: draftContent.data,
draftOriginContent: draftOriginContent.data,
isLoading: false,
});
}));
break;
}
};
onHistoryItemClick = (currentItem, preItem, activeItem) => {
const preCommitID = preItem.commit_id;
const currentCommitID = currentItem.commit_id;
const url = 'history-' + preCommitID + '-' + currentCommitID;
this.setURL(url);
this.setState({
activeItem: activeItem,
isLoading: true,
});
axios.all([
seafileAPI.getFileRevision(draftRepoID, currentCommitID, currentItem.path),
seafileAPI.getFileRevision(draftRepoID, preCommitID, preItem.path)
]).then(axios.spread((res1, res2) => {
axios.all([seafileAPI.getFileContent(res1.data), seafileAPI.getFileContent(res2.data)]).then(axios.spread((content1,content2) => {
this.setDiffViewerContent(content1.data, content2.data);
}));
}));
};
onHistoryListChange = (historyList) => {
this.setState({historyList: historyList });
};
getOriginRepoInfo = () => {
seafileAPI.getRepoInfo(draftRepoID).then((res) => {
this.setState({ originRepoName: res.data.repo_name });
});
};
getDraftInfo = () => {
if (draftStatus === 'open') {
seafileAPI.getFileInfo(draftRepoID, draftFilePath).then((res) => {
this.setState({ draftInfo: res.data });
});
}
};
getChangedNodes = () => {
const nodes = this.refs.diffViewer.value;
let keys = [];
let lastDiffState = '';
nodes.forEach((node, index) => {
const diff_state = node.data['diff_state'];
if (diff_state === 'diff-added' && lastDiffState !== 'diff-added') {
keys.push(index);
} else if (diff_state === 'diff-removed' && lastDiffState !== 'diff-removed') {
keys.push(index);
} else if (diff_state === 'diff-replaced' && lastDiffState !== 'diff-replaced') {
keys.push(index);
}
lastDiffState = node.data.diff_state;
});
this.setState({
changedNodes: keys
});
};
scrollToChangedNode = (scroll) => {
if (this.state.changedNodes.length == 0) return;
if (scroll === 'up') { this.changeIndex++; } else { this.changeIndex--; }
if (this.changeIndex > this.state.changedNodes.length - 1) {
this.changeIndex = 0;
}
if (this.changeIndex < 0) {
this.changeIndex = this.state.changedNodes.length - 1;
}
const win = window;
let key = this.state.changedNodes[this.changeIndex];
let node = window.viewer.children[key];
let element = toDOMNode(window.viewer, node);
// fix code-block or tables
while (element.className.indexOf('diff-') === -1 && element.tagName !== 'BODY') {
element = element.parentNode;
}
const scroller = this.findScrollContainer(element, win);
const isWindow = scroller == win.document.body || scroller == win.document.documentElement;
if (isWindow) {
win.scrollTo(0, element.offsetTop);
} else {
scroller.scrollTop = element.offsetTop;
}
};
findScrollContainer = (element, window) => {
let parent = element.parentNode;
const OVERFLOWS = ['auto', 'overlay', 'scroll'];
let scroller;
while (!scroller) {
if (!parent.parentNode) break;
const style = window.getComputedStyle(parent);
const { overflowY } = style;
if (OVERFLOWS.includes(overflowY)) {
scroller = parent;
break;
}
parent = parent.parentNode;
}
if (!scroller) {
return window.document.body;
}
return scroller;
};
showDiffViewer = () => {
export default function Draft() {
return (
<div>
{this.state.isShowDiff ?
<DiffViewer
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
newMarkdownContent={this.state.draftContent}
oldMarkdownContent={this.state.draftOriginContent}
ref="diffViewer"
/> :
<DiffViewer
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
newMarkdownContent={this.state.draftContent}
oldMarkdownContent={this.state.draftContent}
ref="diffViewer"
/>
}
</div>
);
};
listReviewers = () => {
seafileAPI.listDraftReviewers(draftID).then((res) => {
this.setState({
reviewers: res.data.reviewers
});
});
};
onSwitchShowDiff = () => {
if (!this.state.isShowDiff) {
let that = this;
setTimeout(() => {
that.getChangedNodes();
}, 100);
}
this.setState({
isShowDiff: !this.state.isShowDiff,
});
};
toggleDiffTip = () => {
this.setState({
showDiffTip: !this.state.showDiffTip
});
};
toggleAddReviewerDialog = () => {
if (this.state.showReviewerDialog) {
this.listReviewers();
}
this.setState({
showReviewerDialog: !this.state.showReviewerDialog
});
};
showDiffButton = () => {
return (
<div className={'seafile-toggle-diff'}>
<label className="custom-switch" id="toggle-diff">
<input type="checkbox" checked={this.state.isShowDiff && 'checked'}
name="option" className="custom-switch-input"
onChange={this.onSwitchShowDiff}/>
<span className="custom-switch-indicator"></span>
</label>
<Tooltip placement="bottom" isOpen={this.state.showDiffTip}
target="toggle-diff" toggle={this.toggleDiffTip}>
{gettext('View diff')}</Tooltip>
</div>
);
};
onPublishDraft = () => {
seafileAPI.publishDraft(draftID).then(res => {
this.setState({
draftStatus: res.data.draft_status,
});
});
};
initialDiffViewerContent = () => {
seafileAPI.listFileHistoryRecords(draftRepoID, draftFilePath, 1, 25).then((res) => {
this.setState({
historyList: res.data.data,
totalReversionCount: res.data.total_count
});
if (res.data.data.length > 1) {
axios.all([
seafileAPI.getFileRevision(draftRepoID, res.data.data[0].commit_id, draftFilePath),
seafileAPI.getFileRevision(draftRepoID, res.data.data[1].commit_id, draftFilePath)
]).then(axios.spread((res1, res2) => {
axios.all([seafileAPI.getFileContent(res1.data), seafileAPI.getFileContent(res2.data)]).then(axios.spread((content1,content2) => {
this.setState({
draftContent: content1.data,
draftOriginContent: content2.data
});
}));
}));
} else {
seafileAPI.getFileRevision(draftRepoID, res.data.data[0].commit_id, draftFilePath).then((res) => {
seafileAPI.getFileContent(res.data).then((content) => {
this.setState({
draftContent: content.data,
draftOriginContent: ''
});
});
});
}
});
};
setDiffViewerContent = (newContent, prevContent) => {
this.setState({
draftContent: newContent,
draftOriginContent: prevContent,
isLoading: false,
});
};
setURL = (newurl) => {
let url = new URL(window.location.href);
url.set('hash', newurl);
window.location.href = url.toString();
};
tabItemClick = (tab) => {
if (this.state.activeTab !== tab) {
if (tab !== 'history' && window.location.hash) {
this.setURL('#');
}
if (tab == 'reviewInfo') {
this.initialContent();
} else if (tab == 'history') {
this.initialDiffViewerContent();
}
this.setState({
activeTab: tab
});
}
};
showNavItem = (showTab) => {
switch(showTab) {
case 'info':
return (
<NavItem className="nav-item">
<NavLink
className={classnames({ active: this.state.activeTab === 'reviewInfo' })}
onClick={() => { this.tabItemClick('reviewInfo');}}
>
<i className="fas fa-info-circle"></i>
</NavLink>
</NavItem>
);
case 'history':
return (
<NavItem className="nav-item">
<NavLink
className={classnames({ active: this.state.activeTab === 'history' })}
onClick={() => { this.tabItemClick('history');}}
>
<i className="fas fa-history"></i>
</NavLink>
</NavItem>
);
}
};
componentDidMount() {
this.getOriginRepoInfo();
this.getDraftInfo();
this.listReviewers();
this.initialContent();
}
renderDiffButton = () => {
switch(draftStatus) {
case 'open':
if (!draftFileExists || !originFileExists) {
return;
}
return this.showDiffButton();
case 'published':
if (!originFileExists) {
return;
}
return this.showDiffButton();
}
};
renderNavItems = () => {
switch (draftStatus) {
case 'open':
if (!draftFileExists) {
return (
<Nav tabs className="review-side-panel-nav">
{this.showNavItem('info')}
</Nav>
);
}
return (
<Nav tabs className="review-side-panel-nav">
{this.showNavItem('info')}
{this.showNavItem('history')}
</Nav>
);
case 'published':
if (!originFileExists) {
return (
<Nav tabs className="review-side-panel-nav">
{this.showNavItem('info')}
</Nav>
);
}
return (
<Nav tabs className="review-side-panel-nav">
{this.showNavItem('info')}
</Nav>
);
}
};
renderContent = () => {
switch(draftStatus) {
case 'open':
if (!draftFileExists) {
return <p className="error">{gettext('Draft has been deleted.')}</p>;
}
return this.showDiffViewer();
case 'published':
if (!originFileExists) {
return <p className="error">{gettext('Original file has been deleted.')}</p>;
}
return this.showDiffViewer();
}
};
render() {
const { draftInfo, reviewers, originRepoName, draftStatus } = this.state;
const draftLink = siteRoot + 'lib/' + draftRepoID + '/file' + draftFilePath + '?mode=edit';
const showPublishedButton = this.state.draftStatus == 'published';
const showPublishButton = this.state.draftStatus == 'open' && filePermission == 'rw';
const showEditButton = this.state.draftStatus == 'open' && filePermission == 'rw';
const time = moment(draftInfo.mtime * 1000).format('YYYY-MM-DD HH:mm');
const url = `${siteRoot}profile/${encodeURIComponent(draftInfo.last_modifier_email)}/`;
return(
<div className="wrapper">
<div id="header" className="header review">
<div className="cur-file-info">
<div className="info-item file-feature">
<span className="sf2-icon-review"></span>
</div>
<div>
<div className="info-item file-info">
<span className="file-name">{draftFileName}</span>
<span className="mx-2 file-review">{gettext('Review')}</span>
</div>
{(!showPublishedButton && draftInfo.mtime) &&
<div className="last-modification">
<a href={url}>{draftInfo.last_modifier_name}</a><span className="mx-1">{time}</span>
</div>
}
</div>
</div>
<div className="button-group">
{this.renderDiffButton()}
{showEditButton &&
<a href={draftLink} className="mx-1">
<Button className="file-operation-btn" color="secondary">{gettext('Edit Draft')}</Button>
</a>
}
{showPublishButton &&
<button className='btn btn-success file-operation-btn' title={gettext('Publish draft')} onClick={this.onPublishDraft}>
{gettext('Publish')}
</button>
}
{showPublishedButton &&
<button className='btn btn-success file-operation-btn' title={gettext('Published')} disabled>
{gettext('Published')}
</button>
}
</div>
</div>
<div id="main" className="main" ref="main">
<div className="cur-view-container">
<div className='cur-view-content' ref="viewContent">
{this.state.isLoading ?
<div className="markdown-viewer-render-content article">
<Loading />
</div>
:
<div className="markdown-viewer-render-content article">
{this.renderContent()}
</div>
}
</div>
<div className="cur-view-right-part">
<div className="review-side-panel">
{this.renderNavItems()}
<TabContent activeTab={this.state.activeTab}>
<TabPane tabId="reviewInfo">
<div className="review-side-panel-body">
<SidePanelReviewers
reviewers={reviewers}
toggleAddReviewerDialog={this.toggleAddReviewerDialog}/>
<SidePanelAuthor/>
{(this.state.isShowDiff === true && this.state.changedNodes.length > 0) &&
<SidePanelChanges
changedNumber={this.state.changedNodes.length}
scrollToChangedNode={this.scrollToChangedNode}/>
}
<SidePanelOrigin originRepoName={originRepoName} draftInfo={draftInfo} draftStatus={draftStatus}/>
</div>
</TabPane>
<TabPane tabId="history" className="history">
<HistoryList
activeItem={this.state.activeItem}
historyList={this.state.historyList}
totalReversionCount={this.state.totalReversionCount}
onHistoryItemClick={this.onHistoryItemClick}
onHistoryListChange={this.onHistoryListChange}
/>
</TabPane>
</TabContent>
</div>
</div>
</div>
</div>
{this.state.showReviewerDialog &&
<ModalPortal>
<AddReviewerDialog
showReviewerDialog={this.state.showReviewerDialog}
toggleAddReviewerDialog={this.toggleAddReviewerDialog}
draftID={draftID}
reviewers={reviewers}
/>
</ModalPortal>
}
<div style={{display: 'flex', flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center'}}>
<h1>Draft module</h1>
<div>The current module is no longer supported</div>
</div>
);
}
}
class SidePanelReviewers extends React.Component {
constructor(props) {
super(props);
}
render() {
const { reviewers } = this.props;
return (
<div className="review-side-panel-item">
<div className="review-side-panel-header">{gettext('Reviewers')}
<i className="fa fa-cog" onClick={this.props.toggleAddReviewerDialog}></i>
</div>
{reviewers.length > 0 ?
reviewers.map((item, index = 0, arr) => {
return (
<div className="reviewer-info" key={index}>
<img className="avatar review-side-panel-avatar" src={item.avatar_url} alt=""/>
<span className="reviewer-name ellipsis">{item.user_name}</span>
</div>
);
})
:
<span>{gettext('No reviewer yet.')}</span>
}
</div>
);
}
}
const sidePanelReviewersPropTypes = {
reviewers: PropTypes.array.isRequired,
toggleAddReviewerDialog: PropTypes.func.isRequired
};
SidePanelReviewers.propTypes = sidePanelReviewersPropTypes;
class SidePanelAuthor extends React.Component {
render() {
return (
<div className="review-side-panel-item">
<div className="review-side-panel-header">{gettext('Author')}</div>
<div className="author-info">
<img className="avatar review-side-panel-avatar" src={authorAvatar} alt=""/>
<span className="author-name ellipsis">{author}</span>
</div>
</div>
);
}
}
class SidePanelOrigin extends React.Component {
constructor(props) {
super(props);
}
render() {
const { draftStatus, originRepoName } = this.props;
const filePath = serviceURL + '/lib/' + draftRepoID + '/file' + draftOriginFilePath;
return (
<div className="dirent-table-container">
<table className="table-thead-hidden">
<thead>
<tr><th width="25%"></th><th width="75%"></th></tr>
</thead>
<tbody>
<tr>
<th className="align-text-top">{gettext('Location')}</th>
<td>
{draftStatus === 'open' ?
<span>{originRepoName}{draftFilePath}</span> :
<a href={filePath} className="text-dark">{filePath}</a>
}
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
const SidePanelOriginPropTypes = {
originRepoName: PropTypes.string.isRequired,
draftStatus: PropTypes.string.isRequired,
};
SidePanelOrigin.propTypes = SidePanelOriginPropTypes;
class SidePanelChanges extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="review-side-panel-item">
<div className="review-side-panel-header">{gettext('Changes')}</div>
<div className="changes-info">
<span>{gettext('Number of changes:')}{' '}{this.props.changedNumber}</span>
{this.props.changedNumber > 0 &&
<div>
<i className="fa fa-arrow-circle-up" onClick={() => { this.props.scrollToChangedNode('down');}}></i>
<i className="fa fa-arrow-circle-down" onClick={() => { this.props.scrollToChangedNode('up');}}></i>
</div>
}
</div>
</div>
);
}
}
const sidePanelChangesPropTypes = {
changedNumber: PropTypes.number.isRequired,
scrollToChangedNode: PropTypes.func.isRequired
};
SidePanelChanges.propTypes = sidePanelChangesPropTypes;
ReactDom.render(<Draft />, document.getElementById('wrapper'));

View File

@@ -31,19 +31,6 @@ class FileHistory extends React.Component {
onHistoryItemClick = (item, preItem)=> {
this.setState({renderingContent: true});
if (preItem) {
axios.all([
seafileAPI.getFileRevision(historyRepoID, item.commit_id, item.path),
seafileAPI.getFileRevision(historyRepoID, preItem.commit_id, preItem.path)
]).then(axios.spread((res, res1) => {
axios.all([
seafileAPI.getFileContent(res.data),
seafileAPI.getFileContent(res1.data)
]).then(axios.spread((content1, content2) => {
this.setDiffContent(content1.data, content2.data);
}));
}));
} else {
seafileAPI.getFileRevision(historyRepoID, item.commit_id, item.path).then((res) => {
axios.all([
seafileAPI.getFileContent(res.data),
@@ -51,7 +38,6 @@ class FileHistory extends React.Component {
this.setDiffContent(content1.data, '');
}));
});
}
};
onBackClick = (event) => {

View File

@@ -1,15 +1,18 @@
// Import React!
import React from 'react';
import React, { Suspense } from 'react';
import ReactDom from 'react-dom';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n-seafile-editor';
import i18n from './_i18n/i18n-seafile-editor';
import MarkdownEditor from './pages/markdown-editor';
import Loading from './components/loading';
import './index.css';
ReactDom.render(
<I18nextProvider i18n={ i18n } >
<Suspense fallback={<Loading />}>
<MarkdownEditor />
</Suspense>
</I18nextProvider>,
document.getElementById('root')
);

View File

@@ -1,11 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import Prism from 'prismjs';
import { DiffViewer } from '@seafile/seafile-editor';
import { MarkdownViewer } from '@seafile/seafile-editor';
import Loading from '../../components/loading';
import { mediaUrl } from '../../utils/constants';
const contentClass = 'markdown-viewer-render-content';
const propTypes = {
renderingContent: PropTypes.bool.isRequired,
content: PropTypes.string,
@@ -24,19 +23,18 @@ class MainPanel extends React.Component {
};
render() {
const { renderingContent, newMarkdownContent } = this.props;
return (
<div className="content-viewer flex-fill">
<div className={contentClass}>
{this.props.renderingContent ?
(<Loading />) :
(<div className="diff-view article">
<DiffViewer
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
newMarkdownContent={this.props.newMarkdownContent}
oldMarkdownContent={this.props.oldMarkdownContent}
{renderingContent && <Loading />}
{!renderingContent && (
<MarkdownViewer
isFetching={renderingContent}
value={newMarkdownContent}
isShowOutline={false}
mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'}
/>
</div>)}
</div>
)}
</div>
);
}

View File

@@ -23,3 +23,7 @@
.collab-users-dropdown.dropdown {
margin-right: 6px;
}
.btn-active[data-active=true] {
color: #eb8205;
}

View File

@@ -45,7 +45,7 @@ class EditorApi {
);
}
getParentDectionaryUrl() {
getParentDictionaryUrl() {
let parentPath = this.filePath.substring(0, this.filePath.lastIndexOf('/'));
let libName = encodeURIComponent(repoName);
let path = Utils.encodePath(parentPath);

View File

@@ -23,7 +23,6 @@ const propTypes = {
onEdit: PropTypes.func.isRequired,
toggleNewDraft: PropTypes.func.isRequired,
toggleStar: PropTypes.func.isRequired,
openParentDirectory: PropTypes.func.isRequired,
openDialogs: PropTypes.func.isRequired,
showFileHistory: PropTypes.bool.isRequired,
toggleHistory: PropTypes.func.isRequired,
@@ -31,6 +30,7 @@ const propTypes = {
readOnly: PropTypes.bool.isRequired,
contentChanged: PropTypes.bool.isRequired,
saving: PropTypes.bool.isRequired,
onSaveEditorContent: PropTypes.func.isRequired,
showDraftSaved: PropTypes.bool.isRequired,
isLocked: PropTypes.bool.isRequired,
lockedByMe: PropTypes.bool.isRequired,
@@ -52,10 +52,13 @@ class HeaderToolbar extends React.Component {
location.href = `seafile://openfile?repo_id=${encodeURIComponent(repoID)}&path=${encodeURIComponent(path)}`;
};
openParentDirectory = () => {
const { editorApi } = this.props;
window.location.href = editorApi.getParentDictionaryUrl();
};
render() {
let { contentChanged, saving, isLocked, lockedByMe } = this.props;
let canPublishDraft = this.props.fileInfo.permission == 'rw';
let canCreateDraft = canPublishDraft && (!this.props.hasDraft && !this.props.isDraft && this.props.isDocs);
if (this.props.editorMode === 'rich') {
return (
@@ -71,27 +74,7 @@ class HeaderToolbar extends React.Component {
mediaUrl={mediaUrl}
isStarred={this.props.fileInfo.isStarred}
/>
{(this.props.hasDraft && !this.props.isDraft) &&
<div className='seafile-btn-view-review'>
<div className='tag tag-green'>{gettext('This file is in draft stage.')}
<a className="ml-2" onMouseDown={this.props.editorApi.goDraftPage}>{gettext('View Draft')}</a></div>
</div>
}
<div className="topbar-btn-container">
{canCreateDraft &&
<button onMouseDown={this.props.toggleNewDraft} className="btn btn-success btn-new-draft">
{gettext('New Draft')}</button>
}
{this.props.isDraft &&
<div>
<button type="button" className="btn btn-success seafile-btn-add-review"
onMouseDown={this.props.editorApi.goDraftPage}>{gettext('Start review')}</button>
{canPublishDraft &&
<button type="button" className="btn btn-success seafile-btn-add-review"
onMouseDown={this.props.editorApi.publishDraftFile}>{gettext('Publish')}</button>
}
</div>
}
{(seafileCollabServer && this.props.collabUsers.length > 0) &&
<CollabUsersButton
className="collab-users-dropdown"
@@ -100,24 +83,43 @@ class HeaderToolbar extends React.Component {
/>
}
<ButtonGroup>
<ButtonItem text={gettext('Open parent directory')} id={'parentDirectory'}
icon={'fa fa-folder-open'} onMouseDown={this.props.openParentDirectory}/>
{(canLockUnlockFile && !isLocked) &&
<ButtonItem id="lock-unlock-file" icon='fa fa-lock' text={gettext('Lock')} onMouseDown={this.props.toggleLockFile}/>
}
{(canLockUnlockFile && lockedByMe) &&
<ButtonItem id="lock-unlock-file" icon='fa fa-unlock' text={gettext('Unlock')} onMouseDown={this.props.toggleLockFile}/>
}
{canGenerateShareLink &&
<ButtonItem id={'shareBtn'} text={gettext('Share')} icon={'fa fa-share-alt'}
onMouseDown={this.props.toggleShareLinkDialog}/>
}
<ButtonItem
text={gettext('Open parent directory')}
id={'parentDirectory'}
icon={'fa fa-folder-open'}
onMouseDown={this.openParentDirectory}
/>
{(canLockUnlockFile && !isLocked) && (
<ButtonItem
id="lock-unlock-file"
icon='fa fa-lock'
text={gettext('Lock')}
onMouseDown={this.props.toggleLockFile}
/>
)}
{(canLockUnlockFile && lockedByMe) && (
<ButtonItem
id="lock-unlock-file"
icon='fa fa-unlock'
text={gettext('Unlock')}
onMouseDown={this.props.toggleLockFile}
/>
)}
{canGenerateShareLink && (
<ButtonItem
id={'shareBtn'}
text={gettext('Share')}
icon={'fa fa-share-alt'}
onMouseDown={this.props.toggleShareLinkDialog}
/>
)}
{saving ?
<button type={'button'} aria-label={gettext('Saving...')} className={'btn btn-icon btn-secondary btn-active'}>
<i className={'fa fa-spin fa-spinner'}/></button>
<i className={'fa fa-spin fa-spinner'}/>
</button>
:
<ButtonItem text={gettext('Save')} id={'saveButton'} icon={'fa fa-save'} disabled={!contentChanged}
onMouseDown={window.seafileEditor && window.seafileEditor.onRichEditorSave} isActive={contentChanged}/>
onMouseDown={this.props.onSaveEditorContent} isActive={contentChanged}/>
}
{canDownloadFile && (
<ButtonItem
@@ -127,14 +129,14 @@ class HeaderToolbar extends React.Component {
onClick={this.downloadFile}
/>
)}
{this.props.fileInfo.permission == 'rw' &&
{this.props.fileInfo.permission == 'rw' && (
<ButtonItem
id="open-via-client"
icon="sf3-font sf3-font-desktop"
text={gettext('Open via Client')}
onClick={this.openFileViaClient}
/>
}
)}
</ButtonGroup>
<MoreMenu
readOnly={this.props.readOnly}
@@ -170,7 +172,7 @@ class HeaderToolbar extends React.Component {
editorMode={this.props.editorMode}
onEdit={this.props.onEdit}
toggleShareLinkDialog={this.props.toggleShareLinkDialog}
openParentDirectory={this.props.openParentDirectory}
openParentDirectory={this.openParentDirectory}
showFileHistory={this.props.showFileHistory}
toggleHistory={this.props.toggleHistory}
isSmallScreen={true}
@@ -179,7 +181,9 @@ class HeaderToolbar extends React.Component {
</div>
</div>
);
} else if (this.props.editorMode === 'plain') {
}
if (this.props.editorMode === 'plain') {
return (
<div className="sf-md-viewer-topbar">
<div className="sf-md-viewer-topbar-first d-flex justify-content-between">
@@ -196,7 +200,8 @@ class HeaderToolbar extends React.Component {
<ButtonGroup>
{saving ?
<button type={'button'} className={'btn btn-icon btn-secondary btn-active'}>
<i className={'fa fa-spin fa-spinner'}/></button>
<i className={'fa fa-spin fa-spinner'}/>
</button>
:
<ButtonItem id={'saveButton'} text={gettext('Save')} icon={'fa fa-save'} onMouseDown={window.seafileEditor && window.seafileEditor.onPlainEditorSave} disabled={!contentChanged} isActive={contentChanged} />
}
@@ -238,10 +243,11 @@ class HeaderToolbar extends React.Component {
/>
</div>
</div>
</div>
);
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { EXTERNAL_EVENTS, EventBus } from '@seafile/seafile-editor';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, Tooltip } from 'reactstrap';
import { gettext, canGenerateShareLink } from '../../../utils/constants';
@@ -35,6 +36,11 @@ class MoreMenu extends React.PureComponent {
this.setState({ dropdownOpen: !this.state.dropdownOpen });
};
onHelpModuleToggle = (event) => {
const eventBus = EventBus.getInstance();
eventBus.dispatch(EXTERNAL_EVENTS.ON_HELP_INFO_TOGGLE, true);
};
downloadFile = () => {
location.href = '?dl=1';
};
@@ -51,18 +57,18 @@ class MoreMenu extends React.PureComponent {
</DropdownToggle>
<DropdownMenu className="drop-list" right={true}>
{(!this.props.readOnly && editorMode === 'rich') &&
<DropdownItem onMouseDown={this.props.onEdit.bind(this, 'plain')}>{gettext('Switch to plain text editor')}</DropdownItem>}
<DropdownItem onClick={this.props.onEdit.bind(this, 'plain')}>{gettext('Switch to plain text editor')}</DropdownItem>}
{(!this.props.readOnly && editorMode === 'plain') &&
<DropdownItem onMouseDown={this.props.onEdit.bind(this, 'rich')}>{gettext('Switch to rich text editor')}</DropdownItem>}
<DropdownItem onClick={this.props.onEdit.bind(this, 'rich')}>{gettext('Switch to rich text editor')}</DropdownItem>}
{!isSmall && this.props.showFileHistory &&
<DropdownItem onMouseDown={this.props.toggleHistory}>{gettext('History')}</DropdownItem>}
<DropdownItem onClick={this.props.toggleHistory}>{gettext('History')}</DropdownItem>}
{(this.props.openDialogs && editorMode === 'rich') &&
<DropdownItem onMouseDown={this.props.openDialogs.bind(this, 'help')}>{gettext('Help')}</DropdownItem>
<DropdownItem onClick={this.onHelpModuleToggle}>{gettext('Help')}</DropdownItem>
}
{isSmall && <DropdownItem onMouseDown={this.props.openParentDirectory}>{gettext('Open parent directory')}</DropdownItem>}
{isSmall && canGenerateShareLink && <DropdownItem onMouseDown={this.props.toggleShareLinkDialog}>{gettext('Share')}</DropdownItem>}
{isSmall && <DropdownItem onClick={this.props.openParentDirectory}>{gettext('Open parent directory')}</DropdownItem>}
{isSmall && canGenerateShareLink && <DropdownItem onClick={this.props.toggleShareLinkDialog}>{gettext('Share')}</DropdownItem>}
{(isSmall && this.props.showFileHistory) &&
<DropdownItem onMouseDown={this.props.toggleHistory}>{gettext('History')}</DropdownItem>
<DropdownItem onClick={this.props.toggleHistory}>{gettext('History')}</DropdownItem>
}
{isSmall && canDownloadFile &&
<DropdownItem onClick={this.downloadFile}>{gettext('Download')}</DropdownItem>

View File

@@ -1,21 +1,21 @@
import React, { Fragment } from 'react';
import io from 'socket.io-client';
import { serialize, deserialize } from '@seafile/seafile-editor';
import { EXTERNAL_EVENTS, EventBus, RichMarkdownEditor } from '@seafile/seafile-editor';
import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api';
import { gettext, isDocs, mediaUrl } from '../../utils/constants';
import toaster from '../../components/toast';
import ShareDialog from '../../components/dialog/share-dialog';
import InsertFileDialog from '../../components/dialog/insert-file-dialog';
import LocalDraftDialog from '../../components/dialog/local-draft-dialog';
import HeaderToolbar from './header-toolbar';
import SeafileEditor from './seafile-editor';
import editorApi from './editor-api';
import DetailListView from './detail-list-view';
import '../../css/markdown-viewer/markdown-editor.css';
const CryptoJS = require('crypto-js');
const URL = require('url-parse');
const { repoID, filePath, fileName, draftID, isDraft, hasDraft, isLocked, lockedByMe } = window.app.pageOptions;
const { siteRoot, serviceUrl, seafileCollabServer } = window.app.config;
const userInfo = window.app.userInfo;
@@ -75,6 +75,9 @@ class MarkdownEditor extends React.Component {
this.socket_id = socket.id;
});
}
this.editorRef = React.createRef();
this.isParticipant = false;
this.editorSelection = null;
}
toggleLockFile = () => {
@@ -121,6 +124,8 @@ class MarkdownEditor extends React.Component {
receivePresenceData(data) {
let collabUsers = [];
let editingUsers = [];
switch(data.response) {
case 'user_join':
toaster.notify(`user ${data.user.name} joined`, {
@@ -142,7 +147,13 @@ class MarkdownEditor extends React.Component {
}
}
}
this.setState({collabUsers: Object.values(data.users)});
collabUsers = Object.values(data.users);
editingUsers = collabUsers.filter(ele => ele.is_editing === true && ele.myself === undefined);
if (editingUsers.length > 0) {
const message = gettext('Another user is editing this file!');
toaster.danger(message, {duration: 3});
}
this.setState({ collabUsers });
return;
case 'user_editing':
toaster.danger(`user ${data.user.name} is editing this file!`, {
@@ -176,14 +187,6 @@ class MarkdownEditor extends React.Component {
}
};
setContent = (str) => {
let value = deserialize(str);
this.setState({
markdownContent: str,
value: value,
});
};
checkDraft = () => {
let draftKey = editorApi.getDraftKey();
let draft = localStorage.getItem(draftKey);
@@ -227,9 +230,6 @@ class MarkdownEditor extends React.Component {
openDialogs = (option) => {
switch (option) {
case 'help':
window.richMarkdownEditor.showHelpDialog();
break;
case 'share_link':
this.setState({
showMarkdownEditorDialog: true,
@@ -247,18 +247,6 @@ class MarkdownEditor extends React.Component {
}
};
componentWillUnmount() {
this.socket.emit('repo_update', {
request: 'unwatch_update',
repo_id: editorApi.repoID,
user: {
name: editorApi.name,
username: editorApi.username,
contact_email: editorApi.contact_email,
},
});
}
async componentDidMount() {
const fileIcon = Utils.getFileIconUrl(fileName, 192);
@@ -276,7 +264,6 @@ class MarkdownEditor extends React.Component {
// get file content
const fileContentRes = await seafileAPI.getFileContent(downloadUrl);
const markdownContent = fileContentRes.data;
const value = deserialize(markdownContent);
// init permission
let hasPermission = permission === 'rw' || permission === 'cloud-edit';
@@ -300,7 +287,7 @@ class MarkdownEditor extends React.Component {
loading: false,
fileInfo: {...fileInfo, mtime, size, starred, permission, lastModifier, id},
markdownContent,
value,
value: '',
readOnly: !hasPermission || hasDraft,
});
@@ -333,8 +320,36 @@ class MarkdownEditor extends React.Component {
window.location.href = url;
}
}, 100);
window.addEventListener('beforeunload', this.onUnload);
const eventBus = EventBus.getInstance();
this.unsubscribeInsertSeafileImage = eventBus.subscribe(EXTERNAL_EVENTS.ON_INSERT_IMAGE, this.onInsertImageToggle);
}
componentWillUnmount() {
window.removeEventListener('beforeunload', this.onUnload);
this.unsubscribeInsertSeafileImage();
if (!this.socket) return;
this.socket.emit('repo_update', {
request: 'unwatch_update',
repo_id: editorApi.repoID,
user: {
name: editorApi.name,
username: editorApi.username,
contact_email: editorApi.contact_email,
},
});
}
onUnload = (event) => {
const { contentChanged } = this.state;
if (!contentChanged) return;
this.clearTimer();
const confirmationMessage = gettext('Leave this page? The system may not save your changes.');
event.returnValue = confirmationMessage;
return confirmationMessage;
};
listFileTags = () => {
seafileAPI.listFileTags(repoID, filePath).then(res => {
let fileTagList = res.data.file_tags;
@@ -381,84 +396,82 @@ class MarkdownEditor extends React.Component {
});
};
autoSaveDraft = () => {
let that = this;
if (that.timer) {
return;
}
that.timer = setTimeout(() => {
let str = '';
if (this.state.editorMode == 'rich') {
let value = this.draftRichValue;
str = serialize(value);
}
else if (this.state.editorMode == 'plain') {
str = this.draftPlainValue;
}
let draftKey = editorApi.getDraftKey();
localStorage.setItem(draftKey, str);
that.setState({
showDraftSaved: true
});
setTimeout(() => {
that.setState({
showDraftSaved: false
});
}, 3000);
that.timer = null;
}, 60000);
};
openParentDirectory = () => {
window.location.href = editorApi.getParentDectionaryUrl();
};
onEdit = (editorMode) => {
if (editorMode === 'rich') {
window.seafileEditor.switchToRichTextEditor();
return;
}
if (editorMode === 'plain') {
window.seafileEditor.switchToPlainTextEditor();
}
};
toggleShareLinkDialog = () => {
this.openDialogs('share_link');
};
onInsertImageToggle = (selection) => {
this.editorSelection = selection;
this.openDialogs('insert_file');
};
toggleHistory = () => {
window.location.href = siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + Utils.encodePath(filePath);
};
getInsertLink = (repoID, filePath) => {
const selection = this.editorSelection;
const fileName = Utils.getFileName(filePath);
const suffix = fileName.slice(fileName.indexOf('.') + 1);
const eventBus = EventBus.getInstance();
if (IMAGE_SUFFIXES.includes(suffix)) {
let innerURL = serviceUrl + '/lib/' + repoID + '/file' + Utils.encodePath(filePath) + '?raw=1';
window.richMarkdownEditor.addLink(fileName, innerURL, true);
eventBus.dispatch(EXTERNAL_EVENTS.INSERT_IMAGE, { title: fileName, url: innerURL, isImage: true, selection });
return;
}
let innerURL = serviceUrl + '/lib/' + repoID + '/file' + Utils.encodePath(filePath);
window.richMarkdownEditor.addLink(fileName, innerURL);
eventBus.dispatch(EXTERNAL_EVENTS.INSERT_IMAGE, { title: fileName, url: innerURL, selection});
};
onContentChanged = (value) => {
this.setState({ contentChanged: value });
addParticipants = () => {
if (this.isParticipant || !window.showParticipants) return;
const { userName } = editorApi;
const { participants } = this.state;
if (participants && participants.length !== 0) {
const isParticipant = participants.some((participant) => {
return participant.email === userName;
});
if (isParticipant) return;
}
const emails = [userName];
editorApi.addFileParticipants(emails).then((res) => {
this.isParticipant = true;
this.listFileParticipants();
});
};
onSaving = (value) => {
this.setState({ saving: value });
onContentChanged = () => {
this.setState({ contentChanged: true });
};
onSaveEditorContent = () => {
this.setState({ saving: true });
const content = this.editorRef.current.getValue();
editorApi.saveContent(content).then(() => {
this.setState({
saving: false,
contentChanged: false,
});
this.lastModifyTime = new Date();
const message = gettext('Successfully saved');
toaster.success(message, {duration: 2,});
editorApi.getFileInfo().then((res) => {
this.setFileInfoMtime(res.data);
});
this.addParticipants();
}, () => {
this.setState({ saving: false });
const message = gettext('Failed to save');
toaster.danger(message, {duration: 2});
});
};
render() {
if (this.state.loading) {
return (
<div className="empty-loading-page">
<div className="lds-ripple page-centered"><div></div><div></div></div>
</div>
);
}
const { loading, editorMode, markdownContent, fileInfo, fileTagList } = this.state;
return (
<Fragment>
@@ -470,10 +483,9 @@ class MarkdownEditor extends React.Component {
collabUsers={this.state.collabUsers}
fileInfo={this.state.fileInfo}
toggleStar={this.toggleStar}
openParentDirectory={this.openParentDirectory}
openDialogs={this.openDialogs}
toggleShareLinkDialog={this.toggleShareLinkDialog}
onEdit={this.onEdit}
onEdit={this.setEditorMode}
toggleNewDraft={editorApi.createDraftFile}
showFileHistory={this.state.isShowHistory ? false : true }
toggleHistory={this.toggleHistory}
@@ -481,50 +493,28 @@ class MarkdownEditor extends React.Component {
editorMode={this.state.editorMode}
contentChanged={this.state.contentChanged}
saving={this.state.saving}
onSaveEditorContent={this.onSaveEditorContent}
showDraftSaved={this.state.showDraftSaved}
isLocked={this.state.isLocked}
lockedByMe={this.state.lockedByMe}
toggleLockFile={this.toggleLockFile}
/>
<SeafileEditor
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
fileInfo={this.state.fileInfo}
markdownContent={this.state.markdownContent}
<div className='sf-md-viewer-content'>
<RichMarkdownEditor
ref={this.editorRef}
mode={editorMode}
isFetching={loading}
initValue={fileName}
value={markdownContent}
editorApi={editorApi}
collabUsers={this.state.collabUsers}
setFileInfoMtime={this.setFileInfoMtime}
setEditorMode={this.setEditorMode}
setContent={this.setContent}
draftID={draftID}
isDraft={isDraft}
mode={this.state.mode}
emitSwitchEditor={this.emitSwitchEditor}
hasDraft={hasDraft}
editorMode={this.state.editorMode}
siteRoot={siteRoot}
autoSaveDraft={this.autoSaveDraft}
setDraftValue={this.setDraftValue}
clearTimer={this.clearTimer}
openDialogs={this.openDialogs}
deleteDraft={this.deleteDraft}
readOnly={this.state.readOnly}
onSave={this.onSaveEditorContent}
onContentChanged={this.onContentChanged}
onSaving={this.onSaving}
contentChanged={this.state.contentChanged}
fileTagList={this.state.fileTagList}
onFileTagChanged={this.onFileTagChanged}
participants={this.state.participants}
onParticipantsChange={this.onParticipantsChange}
markdownLint={fileName.toLowerCase() !== 'index.md'}
/>
{this.state.localDraftDialog &&
<LocalDraftDialog
localDraftDialog={this.state.localDraftDialog}
deleteDraft={this.deleteDraft}
closeDraftDialog={this.closeDraftDialog}
useDraft={this.useDraft}
/>
}
mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'}
isSupportInsertSeafileImage={true}
>
<DetailListView fileInfo={fileInfo} fileTagList={fileTagList} onFileTagChanged={this.onFileTagChanged}/>
</RichMarkdownEditor>
</div>
{this.state.showMarkdownEditorDialog && (
<React.Fragment>
{this.state.showInsertFileDialog &&

View File

@@ -1,113 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { EditorContext, Toolbar, MarkdownEditor, UserHelp } from '@seafile/seafile-editor';
import SidePanel from './side-panel';
import '../css/rich-editor.css';
const propTypes = {
scriptSource: PropTypes.string,
markdownContent: PropTypes.string,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
issues: PropTypes.object,
fileInfo: PropTypes.object,
readOnly: PropTypes.bool,
editorApi: PropTypes.object,
onSave: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
resetRichValue: PropTypes.func,
fileTagList: PropTypes.array,
onFileTagChanged: PropTypes.func,
participants: PropTypes.array,
onParticipantsChange: PropTypes.func,
openDialogs: PropTypes.func,
};
class RichMarkdownEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
isShowSidePanel: false,
isShowHelpPanel: false,
};
window.richMarkdownEditor = this;
}
toggleSidePanel = () => {
this.setState({
isShowSidePanel: !this.state.isShowSidePanel,
isShowHelpPanel: false,
});
};
showHelpDialog = () => {
this.setState({isShowSidePanel: false, isShowHelpPanel: true});
};
hideHelpDialog = () => {
this.setState({isShowHelpPanel: false});
};
insertRepoFile = () => {
if (this.props.readOnly) return;
this.props.openDialogs && this.props.openDialogs('insert_file');
};
addLink = (fileName, url, isImage) => {
const editorRef = EditorContext.getEditorRef();
editorRef.addLink(fileName, url, isImage);
};
render() {
const hasSidePanel = true;
const { isShowSidePanel, isShowHelpPanel } = this.state;
const { value } = this.props;
const isShowHelpWrapper = isShowSidePanel || isShowHelpPanel;
const helpWrapperStyle = isShowHelpPanel ? {width: '350px'} : {};
return (
<div className='seafile-markdown-editor'>
<div className='markdown-editor-toolbar'>
<Toolbar
hasSidePanel={hasSidePanel}
isShowSidePanel={isShowSidePanel}
toggleSidePanel={this.toggleSidePanel}
insertRepoFile={this.insertRepoFile}
/>
</div>
<div className='markdown-editor-content'>
<div className={`markdown-editor-wrapper ${isShowHelpWrapper ? '' : 'full-screen'}`}>
<MarkdownEditor
scriptSource={this.props.scriptSource}
value={value}
onSave={this.props.onSave}
editorApi={this.props.editorApi}
onChange={this.props.onChange}
resetRichValue={this.props.resetRichValue}
/>
</div>
<div className={`markdown-help-wrapper ${isShowHelpWrapper ? 'show' : ''}`} style={helpWrapperStyle}>
{isShowSidePanel && (
<SidePanel
document={value}
fileInfo={this.props.fileInfo}
fileTagList={this.props.fileTagList}
onFileTagChanged={this.props.onFileTagChanged}
participants={this.props.participants}
onParticipantsChange={this.props.onParticipantsChange}
/>
)}
{isShowHelpPanel && <UserHelp hideHelpDialog={this.hideHelpDialog} />}
</div>
</div>
</div>
);
}
}
RichMarkdownEditor.propTypes = propTypes;
export default RichMarkdownEditor;

View File

@@ -1,73 +0,0 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import PropTypes from 'prop-types';
import { Outline as OutlineView } from '@seafile/seafile-editor';
import DetailListView from './detail-list-view';
import '../css/side-panel.css';
const propTypes = {
document: PropTypes.array,
fileInfo: PropTypes.object.isRequired,
fileTagList: PropTypes.array,
onFileTagChanged: PropTypes.func.isRequired,
participants: PropTypes.array,
onParticipantsChange: PropTypes.func.isRequired,
};
class SidePanel extends React.PureComponent {
state = {
navItem: 'outline'
};
onOutlineClick = (event) => {
event.preventDefault();
this.setState({navItem: 'outline'});
};
onDetailClick = (event) => {
event.preventDefault();
this.setState({navItem: 'detail'});
};
render() {
var outlineActive = '';
var detailList = '';
if (this.state.navItem === 'outline') {
outlineActive = 'active';
} else if (this.state.navItem === 'detail') {
detailList = 'active';
}
return (
<div className="side-panel d-flex flex-column">
<ul className="flex-shrink-0 nav justify-content-around bg-white">
<li className="nav-item">
<a className={'nav-link ' + outlineActive} href="" onClick={this.onOutlineClick}><i className="iconfont icon-list-ul"/></a>
</li>
<li className="nav-item">
<a className={'nav-link ' + detailList} href="" onClick={this.onDetailClick}><i className={'iconfont icon-info-circle'}/></a>
</li>
</ul>
<div className="side-panel-content flex-fill">
{this.state.navItem === 'outline' &&
<OutlineView document={this.props.document} />
}
{this.state.navItem === 'detail' &&
<DetailListView
fileInfo={this.props.fileInfo}
fileTagList={this.props.fileTagList}
onFileTagChanged={this.props.onFileTagChanged}
/>
}
</div>
</div>
);
}
}
SidePanel.propTypes = propTypes;
export default SidePanel;

View File

@@ -1,268 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Text } from 'slate';
import { deserialize, serialize, PlainMarkdownEditor } from '@seafile/seafile-editor';
import toaster from '../../../components/toast';
import { gettext } from '../../../utils/constants';
import RichMarkdownEditor from '../rich-markdown-editor';
const propTypes = {
mode: PropTypes.string,
editorMode: PropTypes.string,
readOnly: PropTypes.bool,
isDraft: PropTypes.bool,
scriptSource: PropTypes.string,
markdownContent: PropTypes.string,
editorApi: PropTypes.object.isRequired,
collaUsers: PropTypes.array,
onContentChanged: PropTypes.func.isRequired,
onSaving: PropTypes.func.isRequired,
saving: PropTypes.bool,
fileTagList: PropTypes.array,
onFileTagChanged: PropTypes.func.isRequired,
participants: PropTypes.array.isRequired,
onParticipantsChange: PropTypes.func.isRequired,
markdownLint: PropTypes.bool,
setFileInfoMtime: PropTypes.func.isRequired,
setEditorMode: PropTypes.func,
autoSaveDraft: PropTypes.func,
setDraftValue: PropTypes.func,
clearTimer: PropTypes.func,
deleteDraft: PropTypes.func,
contentChanged: PropTypes.bool,
openDialogs: PropTypes.func,
fileInfo: PropTypes.object.isRequired,
collabUsers: PropTypes.array.isRequired,
emitSwitchEditor: PropTypes.func.isRequired,
isSaving: PropTypes.bool,
collabServer: PropTypes.string,
};
class SeafileEditor extends React.Component {
constructor(props) {
super(props);
const { mode, markdownContent, isDraft } = this.props;
const isEditMode = mode === 'editor' || isDraft;
const richValue = isEditMode ? deserialize(markdownContent) : deserialize('');
this.state = {
initialPlainValue: '',
currentContent: markdownContent,
richValue: richValue,
issues: { issue_list: []}
};
this.lastModifyTime = null;
this.autoSave = false;
this.isParticipant = false;
window.seafileEditor = this;
}
UNSAFE_componentWillMount() {
if (this.props.editorMode === 'rich') {
const document = this.state.richValue;
const firstNode = document[0];
/**
* if the markdown content is empty, the rich value contains
* only a paragraph which contains a empty text node
*
*/
if (document.length === 1 &&
firstNode.type === 'paragraph' &&
firstNode.children.length === 1 &&
Text.isText(firstNode.children[0]) &&
firstNode.children[0].text.length === 0) {
let headerContent = this.props.fileInfo.name.slice(0, this.props.fileInfo.name.lastIndexOf('.'));
const header = {
type: 'header_one',
children: [{text: headerContent, marks: []}]
};
document.push(header);
document.shift();
this.setState({richValue: document});
}
}
}
componentDidMount() {
window.addEventListener('beforeunload', this.onUnload);
// notify current user if others are also editing this file
const { collabUsers } = this.props;
const editingUsers = collabUsers.filter(ele => ele.is_editing === true && ele.myself === undefined);
if (editingUsers.length > 0) {
const message = gettext('Another user is editing this file!');
toaster.danger(message, {duration: 3});
}
}
componentWillUnmount() {
window.removeEventListener('beforeunload', this.onUnload);
}
onUnload = (event) => {
if (!this.props.contentChanged) return;
const confirmationMessage = gettext('Leave this page? The system may not save your changes.');
this.props.clearTimer();
this.props.deleteDraft && this.props.deleteDraft();
event.returnValue = confirmationMessage;
return confirmationMessage;
};
switchToPlainTextEditor = () => {
// TODO: performance, change to do serialize in async way
if (this.props.editorMode === 'rich') {
const value = this.state.richValue;
const str = serialize(value);
this.props.setEditorMode('plain');
this.setState({
initialPlainValue: str,
currentContent: str
});
}
if (this.props.collabServer) {
this.props.emitSwitchEditor(false);
}
};
switchToRichTextEditor = () => {
// TODO: performance, change to do deserialize in async way
this.setState({richValue: deserialize(this.state.currentContent)});
this.props.setEditorMode('rich');
if (this.props.collabServer) {
this.props.emitSwitchEditor(false);
}
};
saveContent = (str) => {
this.props.onSaving(true);
this.props.editorApi.saveContent(str).then(() => {
this.props.onSaving(false);
this.props.onContentChanged(false);
// remove markdown lint temporarily
// if (this.props.markdownLint) {
// const slateValue = this.state.richValue;
// this.props.editorApi.markdownLint(JSON.stringify(slateValue)).then((res) => {
// this.setState({
// issues: res.data
// });
// });
// }
this.lastModifyTime = new Date();
const message = gettext('Successfully saved');
toaster.success(message, {duration: 2,});
this.props.editorApi.getFileInfo().then((res) => {
this.props.setFileInfoMtime(res.data);
});
this.addParticipants();
}, () => {
this.props.onSaving(false);
const message = gettext('Failed to save');
toaster.danger(message, {duration: 2});
});
};
onRichEditorSave = () => {
if (this.props.isSaving) return;
const value = this.state.richValue;
const str = serialize(value);
this.saveContent(str);
this.props.clearTimer();
this.props.deleteDraft && this.props.deleteDraft();
};
onPlainEditorSave = () => {
if (this.props.isSaving) return;
const str = this.state.currentContent;
this.saveContent(str);
this.props.clearTimer();
this.props.deleteDraft && this.props.deleteDraft();
};
resetRichValue = () => {
const value = this.state.richValue;
this.setState({ richValue: value });
};
onChange = (value, operations) => {
if (this.props.editorMode === 'rich') {
this.setState({richValue: value,});
this.props.setDraftValue('rich', this.state.richValue);
const ops = operations.filter(o => {
return o.type !== 'set_selection' && o.type !== 'set_value';
});
if (ops.length !== 0) {
this.props.onContentChanged(true);
if (this.autoSave) this.props.autoSaveDraft();
}
} else {
this.setState({currentContent: value});
this.props.onContentChanged(true);
this.props.setDraftValue('rich', this.state.richValue);
this.props.autoSaveDraft();
}
};
addParticipants = () => {
if (this.isParticipant || !window.showParticipants) return;
const { userName, addFileParticipants } = this.props.editorApi;
const { participants } = this.props;
if (participants && participants.length !== 0) {
this.isParticipant = participants.every((participant) => {
return participant.email === userName;
});
if (this.isParticipant) return;
}
let emails = [userName];
addFileParticipants(emails).then((res) => {
this.isParticipant = true;
this.props.onParticipantsChange();
});
};
render() {
if (this.props.editorMode === 'rich') {
return (
<RichMarkdownEditor
scriptSource={this.props.scriptSource}
readOnly={this.props.readOnly}
value={this.state.richValue}
editorApi={this.props.editorApi}
fileInfo={this.props.fileInfo}
collaUsers={this.props.collaUsers}
onChange={this.onChange}
onSave={this.onRichEditorSave}
resetRichValue={this.resetRichValue}
fileTagList={this.props.fileTagList}
onFileTagChanged={this.props.onFileTagChanged}
participants={this.props.participants}
onParticipantsChange={this.props.onParticipantsChange}
openDialogs={this.props.openDialogs}
/>
);
}
return (
<PlainMarkdownEditor
scriptSource={this.props.scriptSource}
editorApi={this.props.editorApi}
initialValue={this.state.initialPlainValue}
currentContent={this.state.currentContent}
contentChanged={this.props.contentChanged}
fileInfo={this.props.fileInfo}
collabUsers={this.props.collabUsers}
onSave={this.onPlainEditorSave}
onChange={this.onChange}
/>
);
}
}
SeafileEditor.propTypes = propTypes;
export default SeafileEditor;

View File

@@ -3,8 +3,10 @@ import ReactDom from 'react-dom';
import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap';
import { Router } from '@gatsbyjs/reach-router';
import { I18nextProvider } from 'react-i18next';
import { siteRoot } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import i18n from '../../_i18n/i18n-seafile-editor';
import SidePanel from './side-panel';
import MainPanel from './main-panel';
@@ -292,4 +294,9 @@ class SysAdmin extends React.Component {
}
}
ReactDom.render(<SysAdmin />, document.getElementById('wrapper'));
ReactDom.render(
<I18nextProvider value={i18n}>
<SysAdmin />
</I18nextProvider>,
document.getElementById('wrapper')
);

View File

@@ -0,0 +1,114 @@
import React from 'react';
import PropTypes from 'prop-types';
import { mdStringToSlate } from '@seafile/seafile-editor';
import { isPublicWiki, repoID, serviceURL, slug } from '../../../utils/constants';
import { Utils } from '../../../utils/utils';
import { generateNavItems } from '../utils/generate-navs';
import NavItem from './nav-item';
import'./style.css';
const viewerPropTypes = {
indexContent: PropTypes.string.isRequired,
onLinkClick: PropTypes.func.isRequired,
};
class IndexMdViewer extends React.Component {
constructor(props) {
super(props);
this.links = [];
this.state = {
currentPath: '',
treeRoot: { name: '', href: '', children: [], isRoot: true },
};
}
componentDidMount() {
const { indexContent } = this.props;
const slateNodes = mdStringToSlate(indexContent);
const newSlateNodes = Utils.changeMarkdownNodes(slateNodes, this.changeInlineNode);
const treeRoot = generateNavItems(newSlateNodes);
this.setState({
treeRoot: treeRoot,
});
}
onLinkClick = (node) => {
const { currentPath } = this.state;
if (node.path === currentPath) return;
if (node.path) {
this.setState({ currentPath: node.path });
}
if (node.href) this.props.onLinkClick(node.href);
};
changeInlineNode = (item) => {
if (item.type == 'link' || item.type === 'image') {
let url;
// change image url
if (item.type == 'image' && isPublicWiki) {
url = item.data.src;
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
// different repo
if (!re.test(url)) {
return;
}
// get image path
let index = url.indexOf('/file');
let index2 = url.indexOf('?');
const imagePath = url.substring(index + 5, index2);
// replace url
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
}
else if (item.type == 'link') {
url = item.url;
/* eslint-disable */
let expression = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/
/* eslint-enable */
let re = new RegExp(expression);
// Solving relative paths
if (!re.test(url)) {
if (url.startsWith('./')) {
url = url.slice(2);
}
item.url = serviceURL + '/published/' + slug + '/' + url;
}
// change file url
else if (Utils.isInternalMarkdownLink(url, repoID)) {
let path = Utils.getPathFromInternalMarkdownLink(url, repoID);
// replace url
item.url = serviceURL + '/published/' + slug + path;
}
// change dir url
else if (Utils.isInternalDirLink(url, repoID)) {
let path = Utils.getPathFromInternalDirLink(url, repoID);
// replace url
item.url = serviceURL + '/published/' + slug + path;
}
}
}
return item;
};
render() {
const { treeRoot, currentPath } = this.state;
return (
<div className="mx-4 o-hidden">
{treeRoot.children.map(node => {
return (
<NavItem key={node.path} node={node} currentPath={currentPath} onLinkClick={this.onLinkClick} />
);
})}
</div>
);
}
}
IndexMdViewer.propTypes = viewerPropTypes;
export default IndexMdViewer;

View File

@@ -0,0 +1,91 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
const propTypes = {
node: PropTypes.object.isRequired,
currentPath: PropTypes.string,
onLinkClick: PropTypes.func.isRequired,
};
class NavItem extends React.Component {
constructor(props) {
super(props);
this.state = {
expanded: false
};
}
toggleExpanded = () => {
const { expanded } = this.state;
this.setState({ expanded: !expanded });
};
onLinkClick = (event) => {
event.preventDefault();
const { node } = this.props;
const { expanded } = this.state;
if (node.children && node.children.length > 0 && !expanded) {
this.setState({expanded: !expanded});
return;
}
this.props.onLinkClick(node);
};
itemClick = () => {
const { node } = this.props;
const { expanded } = this.state;
if (node.children && node.children.length > 0) {
this.setState({expanded: !expanded});
return;
}
};
renderLink = ({ href, name, path, children }) => {
const { currentPath } = this.props;
const className = classNames('wiki-nav-content', {
'no-children': !children || children.length === 0,
'wiki-nav-content-highlight': currentPath === path,
});
if (href && name) {
return (
<div className={className}>
<a href={href} data-path={path} onClick={this.onLinkClick} title={name}>{name}</a>
</div>
);
}
if (name) {
return <div className={className} onClick={this.itemClick}><span title={name}>{name}</span></div>;
}
return null;
};
render() {
const { node } = this.props;
const { expanded } = this.state;
if (node.children.length > 0) {
return (
<div className="pl-4 position-relative">
<span className="switch-btn" onClick={this.toggleExpanded}>
{<i className={`fa fa-caret-${expanded ? 'down': 'right'}`}></i>}
</span>
{this.renderLink(node)}
{expanded && node.children.map((child, index) => {
return (
<NavItem key={index} node={child} currentPath={this.props.currentPath} onLinkClick={this.props.onLinkClick} />
);
})}
</div>
);
}
return this.renderLink(node);
}
}
NavItem.propTypes = propTypes;
export default NavItem;

View File

@@ -1,7 +1,13 @@
.wiki-nav-content {
margin-top: 18px;
}
.wiki-nav-content a, .wiki-nav-content span {
.wiki-nav-content.no-children {
margin-left: 1rem;
}
.wiki-nav-content a,
.wiki-nav-content span {
color: #4d5156;
font-size: 14px;
text-overflow: ellipsis;
@@ -9,14 +15,17 @@
overflow: hidden;
display: block;
}
.wiki-nav-content-highlight a {
text-decoration: none;
color: #eb8205;
}
.wiki-nav-content a:hover {
text-decoration: none;
color: #eb8205;
}
.wiki-nav-content-highlight a {
text-decoration: none;
color: #eb8205;
}
.switch-btn {
position: absolute;
left: 0;

View File

@@ -0,0 +1,510 @@
import React, { Component } from 'react';
import moment from 'moment';
import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap';
import { Utils } from '../../utils/utils';
import { slug, siteRoot, initialPath, isDir, sharedToken, hasIndex, lang } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import Dirent from '../../models/dirent';
import TreeNode from '../../components/tree-view/tree-node';
import treeHelper from '../../components/tree-view/tree-helper';
import SidePanel from './side-panel';
import MainPanel from './main-panel';
import '../../css/layout.css';
import '../../css/side-panel.css';
import '../../css/toolbar.css';
import '../../css/search.css';
import './wiki.css';
moment.locale(lang);
class Wiki extends Component {
constructor(props) {
super(props);
this.state = {
path: '',
pathExist: true,
closeSideBar: false,
isViewFile: true,
isDataLoading: false,
direntList: [],
content: '',
permission: '',
lastModified: '',
latestContributor: '',
isTreeDataLoading: true,
treeData: treeHelper.buildTree(),
currentNode: null,
indexNode: null,
indexContent: '',
};
window.onpopstate = this.onpopstate;
this.indexPath = '/index.md';
this.homePath = '/home.md';
this.pythonWrapper = null;
}
UNSAFE_componentWillMount() {
if (!Utils.isDesktop()) {
this.setState({ closeSideBar: true });
}
}
componentDidMount() {
this.loadSidePanel(initialPath);
this.loadWikiData(initialPath);
this.links = document.querySelectorAll('#wiki-file-content a');
this.links.forEach(link => link.addEventListener('click', this.onConentLinkClick));
}
componentWillUnmount() {
this.links.forEach(link => link.removeEventListener('click', this.onConentLinkClick));
}
loadSidePanel = (initialPath) => {
if (hasIndex) {
this.loadIndexNode();
return;
}
// load dir list
initialPath = isDir === 'None' ? '/' : initialPath;
this.loadNodeAndParentsByPath(initialPath);
};
loadWikiData = (initialPath) => {
this.pythonWrapper = document.getElementById('wiki-file-content');
if (isDir === 'False') {
// this.showFile(initialPath);
this.setState({path: initialPath});
return;
}
// if it is a file list, remove the template content provided by python
this.removePythonWrapper();
if (isDir === 'True') {
this.showDir(initialPath);
return;
}
if (isDir === 'None' && initialPath === '/home.md') {
this.showDir('/');
return;
}
if (isDir === 'None') {
this.setState({pathExist: false});
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(initialPath);
window.history.pushState({url: fileUrl, path: initialPath}, initialPath, fileUrl);
}
};
loadIndexNode = () => {
seafileAPI.listWikiDir(slug, '/').then(res => {
let tree = this.state.treeData;
this.addFirstResponseListToNode(res.data.dirent_list, tree.root);
let indexNode = tree.getNodeByPath(this.indexPath);
seafileAPI.getWikiFileContent(slug, indexNode.path).then(res => {
this.setState({
treeData: tree,
indexNode: indexNode,
indexContent: res.data.content,
isTreeDataLoading: false,
});
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
showDir = (dirPath) => {
this.removePythonWrapper();
this.loadDirentList(dirPath);
// update location url
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(dirPath);
window.history.pushState({url: fileUrl, path: dirPath}, dirPath, fileUrl);
};
showFile = (filePath) => {
this.setState({
isDataLoading: true,
isViewFile: true,
path: filePath,
});
this.removePythonWrapper();
seafileAPI.getWikiFileContent(slug, filePath).then(res => {
let data = res.data;
this.setState({
isDataLoading: false,
content: data.content,
permission: data.permission,
lastModified: moment.unix(data.last_modified).fromNow(),
latestContributor: data.latest_contributor,
});
});
const hash = window.location.hash;
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(filePath) + hash;
if (filePath === '/home.md') {
window.history.replaceState({url: fileUrl, path: filePath}, filePath, fileUrl);
} else {
window.history.pushState({url: fileUrl, path: filePath}, filePath, fileUrl);
}
};
loadDirentList = (dirPath) => {
this.setState({isDataLoading: true});
seafileAPI.listWikiDir(slug, dirPath).then(res => {
let direntList = res.data.dirent_list.map(item => {
let dirent = new Dirent(item);
return dirent;
});
if (dirPath === '/') {
direntList = direntList.filter(item => {
if (item.type === 'dir') {
let name = item.name.toLowerCase();
return name !== 'drafts' && name !== 'images' && name !== 'downloads';
}
return true;
});
}
direntList = Utils.sortDirents(direntList, 'name', 'asc');
this.setState({
path: dirPath,
isViewFile: false,
direntList: direntList,
isDataLoading: false,
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
loadTreeNodeByPath = (path) => {
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(path);
if (!node.isLoaded) {
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
let parentNode = tree.getNodeByPath(node.parentNode.path);
parentNode.isExpanded = true;
this.setState({
treeData: tree,
currentNode: node
});
});
} else {
let parentNode = tree.getNodeByPath(node.parentNode.path);
parentNode.isExpanded = true;
this.setState({treeData: tree, currentNode: node}); //tree
}
};
loadNodeAndParentsByPath = (path) => {
let tree = this.state.treeData.clone();
if (Utils.isMarkdownFile(path)) {
path = Utils.getDirName(path);
}
seafileAPI.listWikiDir(slug, path, true).then(res => {
let direntList = res.data.dirent_list;
let results = {};
for (let i = 0; i < direntList.length; i++) {
let object = direntList[i];
let key = object.parent_dir;
if (!results[key]) {
results[key] = [];
}
results[key].push(object);
}
for (let key in results) {
let node = tree.getNodeByPath(key);
if (!node.isLoaded && node.path === '/') {
this.addFirstResponseListToNode(results[key], node);
} else if (!node.isLoaded) {
this.addResponseListToNode(results[key], node);
}
}
this.setState({
isTreeDataLoading: false,
treeData: tree
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
removePythonWrapper = () => {
if (this.pythonWrapper) {
document.body.removeChild(this.pythonWrapper);
this.pythonWrapper = null;
}
};
onConentLinkClick = (event) => {
event.preventDefault();
event.stopPropagation();
let link = '';
if (event.target.tagName !== 'A') {
let target = event.target.parentNode;
while (target.tagName !== 'A') {
target = target.parentNode;
}
link = target.href;
} else {
link = event.target.href;
}
this.onLinkClick(link);
};
onLinkClick = (link) => {
const url = link;
if (Utils.isWikiInternalMarkdownLink(url, slug)) {
let path = Utils.getPathFromWikiInternalMarkdownLink(url, slug);
this.showFile(path);
} else if (Utils.isWikiInternalDirLink(url, slug)) {
let path = Utils.getPathFromWikiInternalDirLink(url, slug);
this.showDir(path);
} else {
window.location.href = url;
}
if (!this.state.closeSideBar) {
this.setState({ closeSideBar: true });
}
};
onpopstate = (event) => {
if (event.state && event.state.path) {
let path = event.state.path;
if (Utils.isMarkdownFile(path)) {
this.showFile(path);
} else {
this.loadDirentList(path);
this.setState({
path: path,
isViewFile: false
});
}
}
};
onSearchedClick = (item) => {
let path = item.is_dir ? item.path.slice(0, item.path.length - 1) : item.path;
if (this.state.currentPath === path) {
return;
}
// load sidePanel
let index = -1;
let paths = Utils.getPaths(path);
for (let i = 0; i < paths.length; i++) {
// eslint-disable-next-line no-use-before-define
let node = this.state.treeData.getNodeByPath(node);
if (!node) {
index = i;
break;
}
}
if (index === -1) { // all the data has been loaded already.
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(item.path);
treeHelper.expandNode(node);
this.setState({treeData: tree});
} else {
this.loadNodeAndParentsByPath(path);
}
// load mainPanel
if (item.is_dir) {
this.showDir(path);
} else {
if (Utils.isMarkdownFile(path)) {
this.showFile(path);
} else {
let url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(path);
let newWindow = window.open('about:blank');
newWindow.location.href = url;
}
}
};
onMenuClick = () => {
this.setState({closeSideBar: !this.state.closeSideBar});
};
onMainNavBarClick = (nodePath) => {
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(nodePath);
tree.expandNode(node);
this.setState({treeData: tree, currentNode: node});
this.showDir(node.path);
};
onDirentClick = (dirent) => {
let direntPath = Utils.joinPath(this.state.path, dirent.name);
if (dirent.isDir()) { // is dir
this.loadTreeNodeByPath(direntPath);
this.showDir(direntPath);
} else { // is file
if (Utils.isMarkdownFile(direntPath)) {
this.showFile(direntPath);
} else {
const w=window.open('about:blank');
const url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(direntPath);
w.location.href = url;
}
}
};
onCloseSide = () => {
this.setState({closeSideBar: !this.state.closeSideBar});
};
onNodeClick = (node) => {
if (!this.state.pathExist) {
this.setState({pathExist: true});
}
if (node.object.isDir()) {
if (!node.isLoaded) {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
tree.collapseNode(node);
this.setState({treeData: tree});
});
}
if (node.path === this.state.path) {
if (node.isExpanded) {
let tree = treeHelper.collapseNode(this.state.treeData, node);
this.setState({treeData: tree});
} else {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
tree.expandNode(node);
this.setState({treeData: tree});
}
}
}
if (node.path === this.state.path ) {
return;
}
if (node.object.isDir()) { // isDir
this.showDir(node.path);
} else {
if (Utils.isMarkdownFile(node.path)) {
if (node.path !== this.state.path) {
this.showFile(node.path);
}
this.onCloseSide();
} else {
const w = window.open('about:blank');
const url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(node.path);
w.location.href = url;
}
}
};
onNodeCollapse = (node) => {
let tree = treeHelper.collapseNode(this.state.treeData, node);
this.setState({treeData: tree});
};
onNodeExpanded = (node) => {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
if (!node.isLoaded) {
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
this.setState({treeData: tree});
});
} else {
tree.expandNode(node);
this.setState({treeData: tree});
}
};
addFirstResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;
let direntList = list.map(item => {
return new Dirent(item);
});
direntList = direntList.filter(item => {
if (item.type === 'dir') {
let name = item.name.toLowerCase();
return name !== 'drafts' && name !== 'images' && name !== 'downloads';
}
return true;
});
direntList = Utils.sortDirents(direntList, 'name', 'asc');
let nodeList = direntList.map(object => {
return new TreeNode({object});
});
node.addChildren(nodeList);
};
addResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;
let direntList = list.map(item => {
return new Dirent(item);
});
direntList = Utils.sortDirents(direntList, 'name', 'asc');
let nodeList = direntList.map(object => {
return new TreeNode({object});
});
node.addChildren(nodeList);
};
render() {
return (
<div id="main" className="wiki-main">
<SidePanel
isTreeDataLoading={this.state.isTreeDataLoading}
closeSideBar={this.state.closeSideBar}
currentPath={this.state.path}
treeData={this.state.treeData}
indexNode={this.state.indexNode}
indexContent={this.state.indexContent}
onCloseSide={this.onCloseSide}
onNodeClick={this.onNodeClick}
onNodeCollapse={this.onNodeCollapse}
onNodeExpanded={this.onNodeExpanded}
onLinkClick={this.onLinkClick}
/>
<MainPanel
path={this.state.path}
pathExist={this.state.pathExist}
isViewFile={this.state.isViewFile}
isDataLoading={this.state.isDataLoading}
content={this.state.content}
permission={this.state.permission}
lastModified={this.state.lastModified}
latestContributor={this.state.latestContributor}
direntList={this.state.direntList}
onLinkClick={this.onLinkClick}
onMenuClick={this.onMenuClick}
onSearchedClick={this.onSearchedClick}
onMainNavBarClick={this.onMainNavBarClick}
onDirentClick={this.onDirentClick}
/>
<MediaQuery query="(max-width: 767.8px)">
<Modal isOpen={!this.state.closeSideBar} toggle={this.onCloseSide} contentClassName="d-none"></Modal>
</MediaQuery>
</div>
);
}
}
export default Wiki;

View File

@@ -1,10 +1,10 @@
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { gettext, siteRoot, repoID, slug, username, permission } from '../../utils/constants';
import Logo from '../../components/logo';
import Loading from '../../components/loading';
import TreeView from '../../components/tree-view/tree-view';
import IndexContentViewer from '../../components/index-viewer';
import IndexMdViewer from './index-md-viewer';
const propTypes = {
closeSideBar: PropTypes.bool.isRequired,
@@ -29,21 +29,18 @@ class SidePanel extends Component {
renderIndexView = () => {
return (
<Fragment>
<div className="wiki-pages-container">
<div style={{marginTop: '2px'}}></div>
<IndexContentViewer
<IndexMdViewer
indexContent={this.props.indexContent}
onLinkClick={this.props.onLinkClick}
/>
</div>
</Fragment>
);
};
renderTreeView = () => {
return (
<Fragment>
<div className="wiki-pages-container">
{this.props.treeData && (
<TreeView
@@ -56,7 +53,6 @@ class SidePanel extends Component {
/>
)}
</div>
</Fragment>
);
};

View File

@@ -0,0 +1,91 @@
class TreeNode {
constructor({ name, href, parentNode }) {
this.name = name;
this.href = href;
this.parentNode = parentNode || null;
this.children = [];
}
setParent(parentNode) {
this.parentNode = parentNode;
}
addChildren(nodeList) {
// nodeList.forEach((node) => {
// node.setParent(this);
// });
this.children = nodeList;
}
}
const setNodePath = (node, parentNodePath) => {
let name = node.name;
let path = parentNodePath === '/' ? parentNodePath + name : parentNodePath + '/' + name;
node.path = path;
if (node.children.length > 0) {
node.children.forEach(child => {
setNodePath(child, path);
});
}
};
// translate slate_paragraph_node to treeNode
const transParagraph = (paragraphNode) => {
let treeNode;
if (paragraphNode.children[1] && paragraphNode.children[1].type === 'link') {
// paragraph node is a link node
const linkNode = paragraphNode.children[1];
const textNode = linkNode.children[0];
const name = textNode ? textNode.text : '';
treeNode = new TreeNode({ name: name, href: linkNode.url });
} else if (paragraphNode.children[0]) {
// paragraph first child node is a text node, then get node name
const textNode = paragraphNode.children[0];
const name = textNode.text ? textNode.text : '';
treeNode = new TreeNode({ name: name, href: '' });
} else {
treeNode = new TreeNode({ name: '', href: '' });
}
return treeNode;
};
// slateNodes is list items of an unordered list or ordered list, translate them to treeNode and add to parentTreeNode
const transSlateToTree = (slateNodes, parentTreeNode) => {
let treeNodes = slateNodes.map((slateNode) => {
// item has children(unordered list)
if (slateNode.children.length === 2 && (slateNode.children[1].type === 'unordered_list' || slateNode.children[1].type === 'ordered_list')) {
// slateNode.nodes[0] is paragraph, create TreeNode, set name and href
const paragraphNode = slateNode.children[0];
const treeNode = transParagraph(paragraphNode);
// slateNode.nodes[1] is list, set it as TreeNode's children
const listNode = slateNode.children[1];
// Add sub list items to the tree node
return transSlateToTree(listNode.children, treeNode);
} else {
// item doesn't have children list
if (slateNode.children[0] && (slateNode.children[0].type === 'paragraph')) {
return transParagraph(slateNode.children[0]);
} else {
// list item contain table/code_block/blockqupta
return new TreeNode({ name: '', href: '' });
}
}
});
parentTreeNode.addChildren(treeNodes);
return parentTreeNode;
};
export const generateNavItems = (slateNodes) => {
let treeRoot = new TreeNode({ name: '', href: '' });
slateNodes.forEach((node) => {
if (node.type === 'unordered_list' || node.type === 'ordered_list') {
treeRoot = transSlateToTree(node.children, treeRoot);
setNodePath(treeRoot, '/');
}
});
return treeRoot;
};

View File

@@ -0,0 +1,160 @@
.wiki-side-panel .panel-top {
background: #fff;
}
.wiki-side-nav {
flex:auto;
display:flex;
flex-direction:column;
overflow:hidden; /* for ff */
border-right:1px solid #eee;
}
.wiki-pages-heading {
position: relative;
font-size: 1rem;
font-weight: normal;
padding: 0.5rem 0 0.5rem 2rem;
border-bottom: 1px solid #e8e8e8;
line-height: 1.5;
height: 40px;
background-color: #f9f9f9;
margin-bottom: 0;
}
.heading-icon {
position: absolute;
right: 1rem;
top: 25%;
color: #888;
font-size: 0.8125rem;
}
.wiki-pages-container {
flex: 1;
overflow: hidden;
padding-bottom: 10px;
}
.wiki-pages-container:hover {
overflow: auto;
}
.wiki-pages-container .tree-view {
margin-left: -10px;
margin-top: 14px;
padding-left:0;
}
img[src=""] {
opacity: 0;
}
.wiki-side-panel {
flex: 0 0 20%;
display:flex;
flex-direction:column;
overflow:hidden;
}
@media (max-width: 767px) {
.wiki-side-panel {
z-index: 1051;
}
}
.wiki-main-panel {
flex: 1 0 80%;
display:flex;
flex-direction:column;
min-height: 0;
}
.wiki-main-panel .main-panel-north {
background-color: #fff;
}
.cur-view-content .wiki-page-container {
margin: 0 -1rem -1.25rem;
padding: 30px 1rem 1.25rem;
display: flex;
flex: 1;
padding-left: 30px;
overflow-y: auto;
}
.cur-view-content .wiki-page-content {
width: calc(100% - 200px);
padding-right: 30px;
}
@media (max-width: 991.98px) {
.cur-view-content .wiki-page-container {
padding: 0 14px;
padding-top: 30px;
}
.cur-view-content .wiki-page-content {
width: 100%;
padding-right: 0;
}
}
.wiki-page-container .article {
margin: 0;
padding: 0 10px;
}
.wiki-page-container .article h1 {
margin-top: 0;
}
.wiki-page-container .article span[data-url] {
cursor: pointer;
}
.wiki-page-container .article .ml-2 {
text-decoration: underline;
}
.wiki-page-container .article .ml-2:hover {
text-decoration: underline;
color:#eb8205;
}
.wiki-page-container .outline-h2,
.wiki-page-container .outline-h3 {
height: 24px;
font-size: 12px;
color: #4d5156;
}
.wiki-page-container .outline-h2.active,
.wiki-page-container .outline-h3.active {
color: #eb8205;
}
.wiki-page-container .sf-slate-viewer-scroll-container {
background-color: #fff !important;
padding: 0px !important;
overflow: inherit;
}
.wiki-page-container .sf-slate-viewer-article-container {
margin: 0 !important;
}
.wiki-page-container .article {
border: none;
}
.wiki-page-container .sf-slate-viewer-outline {
top: 79px;
width: 200px;
}
@media (max-width: 767px) {
.wiki-page-container .article {
padding: 0 !important;
}
}
#wiki-page-last-modified {
padding: 40px 10px;
font-size:12px;
color: #666;
}

View File

@@ -65,13 +65,6 @@ class FileContent extends React.Component {
return Utils.changeMarkdownNodes(value, this.changeImageURL);
};
updateForNoOutline = () => {
const $outline = document.querySelector('.md-view .seafile-markdown-outline');
const $main = document.querySelector('.md-view .article');
$outline.className += ' d-none';
$main.className += ' article-no-outline';
};
render() {
if (err) {
return <SharedFileViewTip />;
@@ -82,21 +75,14 @@ class FileContent extends React.Component {
}
return (
<div className="shared-file-view-body">
<div className="md-view">
<div className="shared-file-view-body md-view">
<MarkdownViewer
scriptSource={mediaUrl + 'js/mathjax/tex-svg.js'}
markdownContent={this.state.markdownContent}
showTOC={true}
updateForNoOutline={this.updateForNoOutline}
activeTitleIndex={''}
serviceURL={serviceURL}
sharedToken={sharedToken}
repoID={repoID}
modifyValueBeforeRender={this.modifyValueBeforeRender}
value={this.state.markdownContent}
isShowOutline={true}
mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'}
beforeRenderCallback={this.modifyValueBeforeRender}
/>
</div>
</div>
);
}
}

View File

@@ -1,56 +0,0 @@
var unified = require('unified');
var markdown = require('remark-parse');
var slug = require('remark-slug');
var breaks = require('remark-breaks');
var remark2rehype = require('remark-rehype');
var format = require('rehype-format');
var raw = require('rehype-raw');
var xtend = require('xtend');
var toHTML = require('hast-util-to-html');
var sanitize = require('hast-util-sanitize');
var gh = require('hast-util-sanitize/lib/github');
var deepmerge = require('deepmerge').default;
function stringify(config) {
var settings = xtend(config, this.data('settings'));
var schema = deepmerge(gh, {
'attributes': {
'input': [
'type',
],
'li': [
'className'
],
'code': [
'className',
],
},
'tagNames': [
'input',
'code'
]
});
this.Compiler = compiler;
function compiler(tree) {
// use sanity to remove dangerous html, the default is
var hast = sanitize(tree, schema);
return toHTML(hast, settings);
}
}
// markdown -> mdast -> html AST -> html
var processor = unified()
.use(markdown, {commonmark: true})
.use(breaks)
.use(slug)
.use(remark2rehype, {allowDangerousHTML: true})
.use(raw)
.use(format)
.use(stringify);
var processorGetAST = unified()
.use(markdown, {commonmark: true})
.use(slug);
export { processor, processorGetAST };

View File

@@ -1,512 +1,5 @@
import React, { Component } from 'react';
import React from 'react';
import ReactDom from 'react-dom';
import moment from 'moment';
import MediaQuery from 'react-responsive';
import { Modal } from 'reactstrap';
import { slug, siteRoot, initialPath, isDir, sharedToken, hasIndex } from './utils/constants';
import { Utils } from './utils/utils';
import { seafileAPI } from './utils/seafile-api';
import Dirent from './models/dirent';
import TreeNode from './components/tree-view/tree-node';
import treeHelper from './components/tree-view/tree-helper';
import SidePanel from './pages/wiki/side-panel';
import MainPanel from './pages/wiki/main-panel';
import { lang } from './utils/constants';
import './css/layout.css';
import './css/side-panel.css';
import './css/wiki.css';
import './css/toolbar.css';
import './css/search.css';
moment.locale(lang);
class Wiki extends Component {
constructor(props) {
super(props);
this.state = {
path: '',
pathExist: true,
closeSideBar: false,
isViewFile: true,
isDataLoading: false,
direntList: [],
content: '',
permission: '',
lastModified: '',
latestContributor: '',
isTreeDataLoading: true,
treeData: treeHelper.buildTree(),
currentNode: null,
indexNode: null,
indexContent: '',
};
window.onpopstate = this.onpopstate;
this.indexPath = '/index.md';
this.homePath = '/home.md';
this.pythonWrapper = null;
}
UNSAFE_componentWillMount() {
if (!Utils.isDesktop()) {
this.setState({ closeSideBar: true });
}
}
componentDidMount() {
this.loadSidePanel(initialPath);
this.loadWikiData(initialPath);
this.links = document.querySelectorAll('#wiki-file-content a');
this.links.forEach(link => link.addEventListener('click', this.onConentLinkClick));
}
componentWillUnmount() {
this.links.forEach(link => link.removeEventListener('click', this.onConentLinkClick));
}
loadSidePanel = (initialPath) => {
if (hasIndex) {
this.loadIndexNode();
return;
}
// load dir list
initialPath = isDir === 'None' ? '/' : initialPath;
this.loadNodeAndParentsByPath(initialPath);
};
loadWikiData = (initialPath) => {
this.pythonWrapper = document.getElementById('wiki-file-content');
if (isDir === 'False') {
// this.showFile(initialPath);
this.setState({path: initialPath});
return;
}
// if it is a file list, remove the template content provided by python
this.removePythonWrapper();
if (isDir === 'True') {
this.showDir(initialPath);
return;
}
if (isDir === 'None' && initialPath === '/home.md') {
this.showDir('/');
return;
}
if (isDir === 'None') {
this.setState({pathExist: false});
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(initialPath);
window.history.pushState({url: fileUrl, path: initialPath}, initialPath, fileUrl);
}
};
loadIndexNode = () => {
seafileAPI.listWikiDir(slug, '/').then(res => {
let tree = this.state.treeData;
this.addFirstResponseListToNode(res.data.dirent_list, tree.root);
let indexNode = tree.getNodeByPath(this.indexPath);
seafileAPI.getWikiFileContent(slug, indexNode.path).then(res => {
this.setState({
treeData: tree,
indexNode: indexNode,
indexContent: res.data.content,
isTreeDataLoading: false,
});
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
showDir = (dirPath) => {
this.removePythonWrapper();
this.loadDirentList(dirPath);
// update location url
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(dirPath);
window.history.pushState({url: fileUrl, path: dirPath}, dirPath, fileUrl);
};
showFile = (filePath) => {
this.setState({
isDataLoading: true,
isViewFile: true,
path: filePath,
});
this.removePythonWrapper();
seafileAPI.getWikiFileContent(slug, filePath).then(res => {
let data = res.data;
this.setState({
isDataLoading: false,
content: data.content,
permission: data.permission,
lastModified: moment.unix(data.last_modified).fromNow(),
latestContributor: data.latest_contributor,
});
});
const hash = window.location.hash;
let fileUrl = siteRoot + 'published/' + slug + Utils.encodePath(filePath) + hash;
if (filePath === '/home.md') {
window.history.replaceState({url: fileUrl, path: filePath}, filePath, fileUrl);
} else {
window.history.pushState({url: fileUrl, path: filePath}, filePath, fileUrl);
}
};
loadDirentList = (dirPath) => {
this.setState({isDataLoading: true});
seafileAPI.listWikiDir(slug, dirPath).then(res => {
let direntList = res.data.dirent_list.map(item => {
let dirent = new Dirent(item);
return dirent;
});
if (dirPath === '/') {
direntList = direntList.filter(item => {
if (item.type === 'dir') {
let name = item.name.toLowerCase();
return name !== 'drafts' && name !== 'images' && name !== 'downloads';
}
return true;
});
}
direntList = Utils.sortDirents(direntList, 'name', 'asc');
this.setState({
path: dirPath,
isViewFile: false,
direntList: direntList,
isDataLoading: false,
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
loadTreeNodeByPath = (path) => {
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(path);
if (!node.isLoaded) {
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
let parentNode = tree.getNodeByPath(node.parentNode.path);
parentNode.isExpanded = true;
this.setState({
treeData: tree,
currentNode: node
});
});
} else {
let parentNode = tree.getNodeByPath(node.parentNode.path);
parentNode.isExpanded = true;
this.setState({treeData: tree, currentNode: node}); //tree
}
};
loadNodeAndParentsByPath = (path) => {
let tree = this.state.treeData.clone();
if (Utils.isMarkdownFile(path)) {
path = Utils.getDirName(path);
}
seafileAPI.listWikiDir(slug, path, true).then(res => {
let direntList = res.data.dirent_list;
let results = {};
for (let i = 0; i < direntList.length; i++) {
let object = direntList[i];
let key = object.parent_dir;
if (!results[key]) {
results[key] = [];
}
results[key].push(object);
}
for (let key in results) {
let node = tree.getNodeByPath(key);
if (!node.isLoaded && node.path === '/') {
this.addFirstResponseListToNode(results[key], node);
} else if (!node.isLoaded) {
this.addResponseListToNode(results[key], node);
}
}
this.setState({
isTreeDataLoading: false,
treeData: tree
});
}).catch(() => {
this.setState({isLoadFailed: true});
});
};
removePythonWrapper = () => {
if (this.pythonWrapper) {
document.body.removeChild(this.pythonWrapper);
this.pythonWrapper = null;
}
};
onConentLinkClick = (event) => {
event.preventDefault();
event.stopPropagation();
let link = '';
if (event.target.tagName !== 'A') {
let target = event.target.parentNode;
while (target.tagName !== 'A') {
target = target.parentNode;
}
link = target.href;
} else {
link = event.target.href;
}
this.onLinkClick(link);
};
onLinkClick = (link) => {
const url = link;
if (Utils.isWikiInternalMarkdownLink(url, slug)) {
let path = Utils.getPathFromWikiInternalMarkdownLink(url, slug);
this.showFile(path);
} else if (Utils.isWikiInternalDirLink(url, slug)) {
let path = Utils.getPathFromWikiInternalDirLink(url, slug);
this.showDir(path);
} else {
window.location.href = url;
}
if (!this.state.closeSideBar) {
this.setState({ closeSideBar: true });
}
};
onpopstate = (event) => {
if (event.state && event.state.path) {
let path = event.state.path;
if (Utils.isMarkdownFile(path)) {
this.showFile(path);
} else {
this.loadDirentList(path);
this.setState({
path: path,
isViewFile: false
});
}
}
};
onSearchedClick = (item) => {
let path = item.is_dir ? item.path.slice(0, item.path.length - 1) : item.path;
if (this.state.currentPath === path) {
return;
}
// load sidePanel
let index = -1;
let paths = Utils.getPaths(path);
for (let i = 0; i < paths.length; i++) {
// eslint-disable-next-line no-use-before-define
let node = this.state.treeData.getNodeByPath(node);
if (!node) {
index = i;
break;
}
}
if (index === -1) { // all the data has been loaded already.
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(item.path);
treeHelper.expandNode(node);
this.setState({treeData: tree});
} else {
this.loadNodeAndParentsByPath(path);
}
// load mainPanel
if (item.is_dir) {
this.showDir(path);
} else {
if (Utils.isMarkdownFile(path)) {
this.showFile(path);
} else {
let url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(path);
let newWindow = window.open('about:blank');
newWindow.location.href = url;
}
}
};
onMenuClick = () => {
this.setState({closeSideBar: !this.state.closeSideBar});
};
onMainNavBarClick = (nodePath) => {
let tree = this.state.treeData.clone();
let node = tree.getNodeByPath(nodePath);
tree.expandNode(node);
this.setState({treeData: tree, currentNode: node});
this.showDir(node.path);
};
onDirentClick = (dirent) => {
let direntPath = Utils.joinPath(this.state.path, dirent.name);
if (dirent.isDir()) { // is dir
this.loadTreeNodeByPath(direntPath);
this.showDir(direntPath);
} else { // is file
if (Utils.isMarkdownFile(direntPath)) {
this.showFile(direntPath);
} else {
const w=window.open('about:blank');
const url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(direntPath);
w.location.href = url;
}
}
};
onCloseSide = () => {
this.setState({closeSideBar: !this.state.closeSideBar});
};
onNodeClick = (node) => {
if (!this.state.pathExist) {
this.setState({pathExist: true});
}
if (node.object.isDir()) {
if (!node.isLoaded) {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
tree.collapseNode(node);
this.setState({treeData: tree});
});
}
if (node.path === this.state.path) {
if (node.isExpanded) {
let tree = treeHelper.collapseNode(this.state.treeData, node);
this.setState({treeData: tree});
} else {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
tree.expandNode(node);
this.setState({treeData: tree});
}
}
}
if (node.path === this.state.path ) {
return;
}
if (node.object.isDir()) { // isDir
this.showDir(node.path);
} else {
if (Utils.isMarkdownFile(node.path)) {
if (node.path !== this.state.path) {
this.showFile(node.path);
}
this.onCloseSide();
} else {
const w = window.open('about:blank');
const url = siteRoot + 'd/' + sharedToken + '/files/?p=' + Utils.encodePath(node.path);
w.location.href = url;
}
}
};
onNodeCollapse = (node) => {
let tree = treeHelper.collapseNode(this.state.treeData, node);
this.setState({treeData: tree});
};
onNodeExpanded = (node) => {
let tree = this.state.treeData.clone();
node = tree.getNodeByPath(node.path);
if (!node.isLoaded) {
seafileAPI.listWikiDir(slug, node.path).then(res => {
this.addResponseListToNode(res.data.dirent_list, node);
this.setState({treeData: tree});
});
} else {
tree.expandNode(node);
this.setState({treeData: tree});
}
};
addFirstResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;
let direntList = list.map(item => {
return new Dirent(item);
});
direntList = direntList.filter(item => {
if (item.type === 'dir') {
let name = item.name.toLowerCase();
return name !== 'drafts' && name !== 'images' && name !== 'downloads';
}
return true;
});
direntList = Utils.sortDirents(direntList, 'name', 'asc');
let nodeList = direntList.map(object => {
return new TreeNode({object});
});
node.addChildren(nodeList);
};
addResponseListToNode = (list, node) => {
node.isLoaded = true;
node.isExpanded = true;
let direntList = list.map(item => {
return new Dirent(item);
});
direntList = Utils.sortDirents(direntList, 'name', 'asc');
let nodeList = direntList.map(object => {
return new TreeNode({object});
});
node.addChildren(nodeList);
};
render() {
return (
<div id="main" className="wiki-main">
<SidePanel
isTreeDataLoading={this.state.isTreeDataLoading}
closeSideBar={this.state.closeSideBar}
currentPath={this.state.path}
treeData={this.state.treeData}
indexNode={this.state.indexNode}
indexContent={this.state.indexContent}
onCloseSide={this.onCloseSide}
onNodeClick={this.onNodeClick}
onNodeCollapse={this.onNodeCollapse}
onNodeExpanded={this.onNodeExpanded}
onLinkClick={this.onLinkClick}
/>
<MainPanel
path={this.state.path}
pathExist={this.state.pathExist}
isViewFile={this.state.isViewFile}
isDataLoading={this.state.isDataLoading}
content={this.state.content}
permission={this.state.permission}
lastModified={this.state.lastModified}
latestContributor={this.state.latestContributor}
direntList={this.state.direntList}
onLinkClick={this.onLinkClick}
onMenuClick={this.onMenuClick}
onSearchedClick={this.onSearchedClick}
onMainNavBarClick={this.onMainNavBarClick}
onDirentClick={this.onDirentClick}
/>
<MediaQuery query="(max-width: 767.8px)">
<Modal isOpen={!this.state.closeSideBar} toggle={this.onCloseSide} contentClassName="d-none"></Modal>
</MediaQuery>
</div>
);
}
}
import Wiki from './pages/wiki';
ReactDom.render(<Wiki />, document.getElementById('wrapper'));

View File

@@ -1,126 +1,126 @@
{
"bold": "Tučně",
"italic": "Kurzíva",
"inline_code": "Kód",
"header_one": "Záhlaví 1",
"header_two": "Záhlaví 2",
"header_three": "Záhlaví 3",
"header_four": "Záhlaví 4",
"header_five": "Záhlaví 5",
"header_six": "Záhlaví 6",
"paragraph": "Odstavec",
"quote": "Citace",
"ordered_list": "Číslovaný seznam",
"unordered_list": "Nečíslovaný seznam",
"check_list_item": "Zkontrolovat položku seznamu",
"insert_image": "Vložit obrázek",
"insert_formula": "Insert Formula",
"formula": "Formula",
"insert_file": "Vložit soubor",
"code": "Řádkový kód",
"code_block": "Blok kódu",
"insert_link": "Vložit odkaz",
"insert_table": "Vložit tabulku",
"save": "Uložit",
"more": "Více",
"invalid_url": "Chybná URL",
"link_address": "Adresa odkazu",
"image_address": "Adresa obrázku",
"submit": "Odeslat",
"cancel": "Storno",
"switch_to_plain_text_editor": "Přepnout do textového editoru",
"switch_to_rich_text_editor": "Přepnout do rozšířeného textového editoru",
"switch_to_viewer": "Přepnout do značkovacího prohlížeče",
"help": "Pomoc",
"remove_table": "Odebrat tabulku",
"column": "Sloupec",
"row": "Řádek",
"Insert_Row_Before": "Vložit řádku před",
"Insert_Row_After": "Vložit řádek za",
"Insert_Column_Before": "Vložit sloupec před",
"Insert_Column_After": "Vložit sloupec za",
"Remove_Row": "Odstranit řádek",
"Remove_Column": "Odstranit sloupec",
"Insert_Row": "Vložit řádek",
"Insert_Column": "Vložit sloupec",
"set_align": "Nastavit zarovnání",
"left": "Vlevo",
"center": "Střed",
"right": "Vpravo",
"file_saved": "Soubor uložen",
"file_failed_to_save": "Soubor nebyl uložen",
"star": "Přidat hvězdičku",
"unstar": "Odebrat hvězdičku",
"back_to_parent_directory":"Zpět do nadřazeného adresáře",
"edit": "Upravit",
"copy": "Kopírovat",
"copied": "Zkopírováno",
"internal_link": "Interní odkaz",
"copy_internal_link": "Interní odkaz byl zkopírován do schránky",
"internal_link_desc": "Interní odkaz směřuje na soubor nebo složku u které má uživatel oprávnění ke čtení.",
"share": "Sdílet",
"share_link": "Veřejný odkaz",
"generate": "Generovat",
"add_password_protection": "Přidat ochranu heslem",
"password": "Heslo",
"at_least_8_characters": "nejméně 8 znaků",
"password_again": "Heslo znovu",
"add_auto_expiration": "Přidat automatickou expiraci",
"days": "dní",
"please_enter_password": "Zadejte heslo",
"greater_than_or_equal_to": "Vyšší nebo rovno",
"less_than_or_equal_to": "Nižší nebo rovno",
"set_permission": "Nastavit oprávnění",
"preview_and_download": "Zobrazit a stáhnout",
"preview_only": "Pouze zobrazit",
"please_enter_valid_days": "Zadejte platné dny",
"please_enter_a_non-negative_integer": "Vložte prosím nezáporné celé číslo",
"please_enter_days": "Prosím zadejte dny",
"password_is_too_short": "Heslo je příliš krátké.",
"passwords_do_not_match": "Hesla nesouhlasí",
"return_to_wiki_page": "Návrat na stránku Wiki",
"insert_network_image": "Vložit síťový obrázek",
"upload_local_image": "Nahrát lokální obrázek",
"add_link": "Přidat odkaz",
"file_history": "Historie souboru",
"history_version": "Historie verzí",
"back_to_viewer": "Zpět na prohlížeč",
"link_title": "Název odkazu",
"local_draft": "Místní koncept",
"use_draft": "Použít koncept",
"delete_draft": "Smazat koncept",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "Máte neuložený koncept. Chcete ho použít?",
"local_draft_saved": "Místní koncept byl uložen",
"new_draft": "Nový návrh",
"view_draft": "Zobrazit koncept",
"publish": "Zveřejnit",
"this_file_has_a_draft": "Tento soubor má koncept.",
"delete": "Smazat",
"comments": "Komentáře",
"add_a_comment": "Přidat komentář…",
"no_comment_yet": "Žádné komentáře",
"Bold": "Tučně",
"Italic": "Kurzíva",
"Inline_code": "Kód",
"Header_one": "Záhlaví 1",
"Header_two": "Záhlaví 2",
"Header_three": "Záhlaví 3",
"Header_four": "Záhlaví 4",
"Header_five": "Záhlaví 5",
"Header_six": "Záhlaví 6",
"Paragraph": "Odstavec",
"Quote": "Citace",
"Ordered_list": "Číslovaný seznam",
"Unordered_list": "Nečíslovaný seznam",
"Check_list_item": "Zkontrolovat položku seznamu",
"Insert_image": "Vložit obrázek",
"Insert_formula": "Insert Formula",
"Formula": "Formula",
"Insert_file": "Vložit soubor",
"Code": "Řádkový kód",
"Code_block": "Blok kódu",
"Insert_link": "Vložit odkaz",
"Insert_table": "Vložit tabulku",
"Save": "Uložit",
"More": "Více",
"Invalid_url": "Chybná URL",
"Link_address": "Adresa odkazu",
"Image_address": "Adresa obrázku",
"Submit": "Odeslat",
"Cancel": "Storno",
"Switch_to_plain_text_editor": "Přepnout do textového editoru",
"Switch_to_rich_text_editor": "Přepnout do rozšířeného textového editoru",
"Switch_to_viewer": "Přepnout do značkovacího prohlížeče",
"Help": "Pomoc",
"Remove_table": "Odebrat tabulku",
"Column": "Sloupec",
"Row": "Řádek",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insert row",
"Insert_column": "Insert column",
"Set_align": "Nastavit zarovnání",
"Left": "Vlevo",
"Center": "Střed",
"Right": "Vpravo",
"File_saved": "Soubor uložen",
"File_failed_to_save": "Soubor nebyl uložen",
"Star": "Přidat hvězdičku",
"Unstar": "Odebrat hvězdičku",
"Back_to_parent_directory": "Zpět do nadřazeného adresáře",
"Edit": "Upravit",
"Copy": "Kopírovat",
"Copied": "Zkopírováno",
"Internal_link": "Interní odkaz",
"Copy_internal_link": "Interní odkaz byl zkopírován do schránky",
"Internal_link_desc": "Interní odkaz směřuje na soubor nebo složku u které má uživatel oprávnění ke čtení.",
"Share": "Sdílet",
"Share_link": "Veřejný odkaz",
"Generate": "Generovat",
"Add_password_protection": "Přidat ochranu heslem",
"Password": "Heslo",
"At_least_8_characters": "nejméně 8 znaků",
"Password_again": "Heslo znovu",
"Add_auto_expiration": "Přidat automatickou expiraci",
"Days": "dní",
"Please_enter_password": "Zadejte heslo",
"Greater_than_or_equal_to": "Vyšší nebo rovno",
"Less_than_or_equal_to": "Nižší nebo rovno",
"Set_permission": "Nastavit oprávnění",
"Preview_and_download": "Zobrazit a stáhnout",
"Preview_only": "Pouze zobrazit",
"Please_enter_valid_days": "Zadejte platné dny",
"Please_enter_a_non-negative_integer": "Vložte prosím nezáporné celé číslo",
"Please_enter_days": "Prosím zadejte dny",
"Password_is_too_short": "Heslo je příliš krátké.",
"Passwords_do_not_match": "Hesla nesouhlasí",
"Return_to_wiki_page": "Návrat na stránku Wiki",
"Insert_network_image": "Vložit síťový obrázek",
"Upload_local_image": "Nahrát lokální obrázek",
"Add_link": "Přidat odkaz",
"File_history": "Historie souboru",
"History_version": "Historie verzí",
"Back_to_viewer": "Zpět na prohlížeč",
"Link_title": "Název odkazu",
"Local_draft": "Místní koncept",
"Use_draft": "Použít koncept",
"Delete_draft": "Smazat koncept",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "Máte neuložený koncept. Chcete ho použít?",
"Local_draft_saved": "Místní koncept byl uložen",
"New_draft": "Nový návrh",
"View_draft": "Zobrazit koncept",
"Publish": "Zveřejnit",
"This_file_has_a_draft": "Tento soubor má koncept.",
"Delete": "Smazat",
"Comments": "Komentáře",
"Add_a_comment": "Přidat komentář…",
"No_comment_yet": "Žádné komentáře",
"Mark_as_Resolved": "Označit jako vyřešené",
"ask_for_review": "Požádat o kontrolu",
"review_already_exists": "Kontrola již existuje. ",
"view_review": "Zobrazit kontrolu",
"there_is_an_associated_review_with_this_file": "K tomuto souboru je přiřazená kontrola",
"start_review": "Začít kontrolu",
"this_file_is_in_draft_stage": "Tento soubor je ve fázi návrhu.",
"this_file_is_in_review_stage": "Tento soubor je ve fázi kontroly.",
"this_file_has_been_updated": "Tento soubor byl aktualizován.",
"refresh": "Obnovit",
"related_files": "související soubory",
"related_file": "související soubor",
"no_tags": "Žádné značky",
"Ask_for_review": "Požádat o kontrolu",
"Review_already_exists": "Kontrola již existuje. ",
"View_review": "Zobrazit kontrolu",
"There_is_an_associated_review_with_this_file": "K tomuto souboru je přiřazená kontrola",
"Start_review": "Začít kontrolu",
"This_file_is_in_draft_stage": "Tento soubor je ve fázi návrhu.",
"This_file_is_in_review_stage": "Tento soubor je ve fázi kontroly.",
"This_file_has_been_updated": "Tento soubor byl aktualizován.",
"Refresh": "Obnovit",
"Related_files": "související soubory",
"Related_file": "související soubor",
"No_tags": "Žádné značky",
"Date": "Datum",
"Participants": "Účastníci",
"Meeting_note": "Poznámky ze schůzky",
"Chooser_document_type": "Výběr typu dokumentu",
"Empty": "Prázdný",
"no_related_files": "Žádné související soubory",
"no_out_line": "Bez obrysu",
"No_related_files": "Žádné související soubory",
"No_out_line": "Bez obrysu",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Úpravy souborů v tomto prohlížeči mohou způsobit malé problémy se zobrazením.",
"no_document_improvement_suggestion": "Žádný návrh na zlepšení dokumentu",
"No_document_improvement_suggestion": "Žádný návrh na zlepšení dokumentu",
"Hide_side_panel": "Skrýt postranní panel",
"Show_side_panel": "Zobrazit postranní panel",
"Show_resolved_comments": "Zobrazit vyřešené komentáře",
@@ -131,25 +131,16 @@
"Insert_library_image": "Vložit obrázek knihovny",
"Size": "Velikost",
"Location": "Umístění",
"Last_Update": "Poslední aktualizace",
"Last_update": "Last update",
"Tags": "Štítky",
"Related_Files": "Související soubory",
"Add_participants": "Přidat účastníky",
"markdownLint": {
"missing_h1": {
"description": "V dokumentu není žádný h1",
"issue" : "Chybí h1"
},
"heading_end_with_colon": {
"description": "Koncová interpunkce v záhlaví by neměla být dvojtečka",
"issue": "Záhlaví končí dvojtečkou"
},
"heading_increase_irregular": {
"description": "Úrovně nadpisů by se měly zvyšovat vždy pouze o jednu úroveň",
"issue": "Problém s úrovní nadpisu"
}
},
"Clear_format": "Clear format",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Shortcut help",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Klávesové zkratky",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Vložit podpoložku",
"Increase_depth": "Zvýšit hloubku"
}
}, {
},
{
"shortcutType": "Zkratky záhlaví",
"shortcutData": {
"Heading_1": "Záhlaví 1",
@@ -172,7 +164,8 @@
"Heading_5": "Záhlaví 5",
"Heading_6": "Záhlaví 6"
}
}, {
},
{
"shortcutType": "Zkratky bloků kódu",
"shortcutData": {
"Make_code_block": "Vytvořit blok kódu",
@@ -180,37 +173,43 @@
"Escape_code_block": "Opustit blok kódu",
"Insert_indent": "Vložit odrážku"
}
}, {
},
{
"shortcutType": "Zkratky bloku citace",
"shortcutData": {
"Make_Block_quote": "Vytvořit blokovou citaci",
"Escape_Block_quote": "Opustit blokovou citaci"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Zkratky tabulky",
"shortcutData": {
"Insert_Table_Row": "Vložit řádku tabulky",
"Insert_table_row": "Insert table tow",
"Escape_table": "Opustit tabulku"
}
}, {
},
{
"shortcutType": "Zkratky vzorečku",
"shortcutData": {
"Insert_Formula": "Insert Formula"
"Insert_formula": "Insert formula"
}
}, {
},
{
"shortcutType": "Řádkové zkratky",
"shortcutData": {
"Bold": "Tučně",
"Italic": "Kurzíva",
"Italic_Bold": "Tučná kurzíva",
"Italic_bold": "Italic bold",
"Inline_code": "Řádkový kód"
}
}, {
},
{
"shortcutType": "Uložit zkratky",
"shortcutData": {
"Save_file": "Uložit soubor"
}
}, {
},
{
"shortcutType": "Zkratky obrázku",
"shortcutData": {
"Paste_screen_shot": "Vložit snímek obrazovky",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Fett",
"italic": "Kursiv",
"inline_code": "Code",
"header_one": "Überschrift 1",
"header_two": "Überschrift 2",
"header_three": "Überschrift 3",
"header_four": "Überschrift 4",
"header_five": "Überschrift 5",
"header_six": "Überschrift 6",
"paragraph": "Absatz",
"quote": "Blockquote",
"ordered_list": "Nummerierte Liste",
"unordered_list": "Ungeordnete Liste",
"check_list_item": "Checkbox Liste",
"insert_image": "Bild",
"insert_formula": "Formel einfügen",
"formula": "Formel",
"insert_file": "Datei",
"code": "Inline-Code",
"code_block": "Codeblock",
"insert_link": "Link",
"insert_table": "Tabelle",
"save": "Speichern",
"more": "Mehr",
"invalid_url": "Ungültige Adresse",
"link_address": "Link-URL",
"image_address": "Bild-URL",
"submit": "Absenden",
"cancel": "Abbrechen",
"switch_to_plain_text_editor": "Zum Plain Text Editor wechseln",
"switch_to_rich_text_editor": "Zum Rich Text Editor wechseln",
"switch_to_viewer": "Zur Markdown-Vorschau wechseln",
"help": "Hilfe",
"remove_table": "Tabelle entfernen",
"column": "Spalte",
"row": "Zeile",
"Insert_Row_Before": "Zeile darüber einfügen",
"Insert_Row_After": "Zeile darunter einfügen",
"Insert_Column_Before": "Spalte links einfügen",
"Insert_Column_After": "Spalte rechts einfügen",
"Remove_Row": "Zeile entfernen",
"Remove_Column": "Spalte entfernen",
"Insert_Row": "Zeile einfügen",
"Insert_Column": "Spalte einfügen",
"set_align": "Ausrichtung festlegen",
"left": "Links",
"center": "Zentrieren",
"right": "Rechts",
"file_saved": "Die Datei wurde gespeichert.",
"file_failed_to_save": "Die Datei konnte nicht gespeichert werden.",
"star": "Zu Favoriten hinzufügen",
"unstar": "Aus Favoriten entfernen",
"back_to_parent_directory":"Zurück zum übergeordneten Verzeichnis",
"edit": "Bearbeiten",
"copy": "Kopieren",
"copied": "Kopiert",
"internal_link": "Internen Link anzeigen",
"copy_internal_link": "Der interne Link wurde in die Zwischenablage kopiert.",
"internal_link_desc": "Interne Links sind Verweise auf Dateien bzw. Ordner, die nur von Benutzer/innen mit mindestens Leserechten für die Dateien bzw. Ordner genutzt werden können. Interne Links eignen sich insbesondere für die interne Kommunikation in Ticket-/CRM-Systemen sowie E-Mails und Chats.",
"share": "Freigeben",
"share_link": "Download-Link",
"generate": "Erstellen",
"add_password_protection": "Passwort hinzufügen",
"password": "Passwort",
"at_least_8_characters": "mindestens 8 Zeichen",
"password_again": "Passwort erneut eingeben",
"add_auto_expiration": "Befristung hinzufügen",
"days": "Tage",
"please_enter_password": "Bitte geben Sie ein Passwort ein",
"greater_than_or_equal_to": "Größer oder gleich",
"less_than_or_equal_to": "Weniger oder gleich",
"set_permission": "Rechte festlegen",
"preview_and_download": "Vorschau und Herunterladen",
"preview_only": "Nur Vorschau erlaubt",
"please_enter_valid_days": "Bitte geben Sie eine gültige Anzahl von Tagen ein",
"please_enter_a_non-negative_integer": "Bitte geben Sie eine Zahl größer oder gleich Null ein",
"please_enter_days": "Bitte geben Sie Tage ein",
"password_is_too_short": "Passwort ist zu kurz",
"passwords_do_not_match": "Passwörter stimmen nicht überein",
"return_to_wiki_page": "Zurück zur Wiki-Seite",
"insert_network_image": "Bild per URL einfügen",
"upload_local_image": "Bild hochladen und einfügen",
"add_link": "Link hinzufügen",
"file_history": "Dateiversionen",
"history_version": "Versionen",
"back_to_viewer": "Zurück zur Vorschau",
"link_title": "Linktext",
"local_draft": "Lokaler Entwurf",
"use_draft": "Entwurf verwenden",
"delete_draft": "Entwurf löschen",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "Es gibt einen ungespeicherten Entwurf. Möchten Sie ihn verwenden?",
"local_draft_saved": "Lokaler Entwurf gespeichert",
"new_draft": "Neuer Entwurf",
"view_draft": "Entwurf anzeigen",
"publish": "Veröffentlichen",
"this_file_has_a_draft": "Zu dieser Datei gibt es einen Entwurf.",
"delete": "Löschen",
"comments": "Kommentare",
"add_a_comment": "Kommentar einfügen",
"no_comment_yet": "Keine Kommentare vorhanden",
"Bold": "Fett",
"Italic": "Kursiv",
"Inline_code": "Code",
"Header_one": "Überschrift 1",
"Header_two": "Überschrift 2",
"Header_three": "Überschrift 3",
"Header_four": "Überschrift 4",
"Header_five": "Überschrift 5",
"Header_six": "Überschrift 6",
"Paragraph": "Absatz",
"Quote": "Blockquote",
"Ordered_list": "Nummerierte Liste",
"Unordered_list": "Ungeordnete Liste",
"Check_list_item": "Checkbox Liste",
"Insert_image": "Bild",
"Insert_formula": "Formel einfügen",
"Formula": "Formel",
"Insert_file": "Datei",
"Code": "Inline-Code",
"Code_block": "Codeblock",
"Insert_link": "Link",
"Insert_table": "Tabelle",
"Save": "Speichern",
"More": "Mehr",
"Invalid_url": "Ungültige Adresse",
"Link_address": "Link-URL",
"Image_address": "Bild-URL",
"Submit": "Speichern",
"Cancel": "Abbrechen",
"Switch_to_plain_text_editor": "Zum Plain Text Editor wechseln",
"Switch_to_rich_text_editor": "Zum Rich Text Editor wechseln",
"Switch_to_viewer": "Zur Markdown-Vorschau wechseln",
"Help": "Hilfe",
"Remove_table": "Tabelle entfernen",
"Column": "Spalte",
"Row": "Zeile",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insert row",
"Insert_column": "Insert column",
"Set_align": "Ausrichtung festlegen",
"Left": "Links",
"Center": "Zentrieren",
"Right": "Rechts",
"File_saved": "Die Datei wurde gespeichert.",
"File_failed_to_save": "Die Datei konnte nicht gespeichert werden.",
"Star": "Zu Favoriten hinzufügen",
"Unstar": "Aus Favoriten entfernen",
"Back_to_parent_directory": "Zurück zum übergeordneten Verzeichnis",
"Edit": "Bearbeiten",
"Copy": "Kopieren",
"Copied": "Kopiert",
"Internal_link": "Internen Link anzeigen",
"Copy_internal_link": "Der interne Link wurde in den Zwischenspeicher kopiert.",
"Internal_link_desc": "Interne Links sind Verweise auf Dateien bzw. Ordner, die nur von Benutzer/innen mit mindestens Leserechten für die Dateien bzw. Ordner genutzt werden können. Interne Links eignen sich insbesondere für die interne Kommunikation in Ticket-/CRM-Systemen sowie E-Mails und Chats.",
"Share": "Freigeben",
"Share_link": "Download-Link",
"Generate": "Erstellen",
"Add_password_protection": "Passwort hinzufügen",
"Password": "Passwort",
"At_least_8_characters": "mindestens 8 Zeichen",
"Password_again": "Passwort erneut eingeben",
"Add_auto_expiration": "Befristung hinzufügen",
"Days": "Tage",
"Please_enter_password": "Bitte geben Sie ein Passwort ein",
"Greater_than_or_equal_to": "Größer oder gleich",
"Less_than_or_equal_to": "Weniger oder gleich",
"Set_permission": "Berechtigung festlegen",
"Preview_and_download": "Vorschau und Herunterladen",
"Preview_only": "Nur Vorschau erlaubt",
"Please_enter_valid_days": "Bitte geben Sie eine gültige Anzahl von Tagen ein",
"Please_enter_a_non-negative_integer": "Bitte geben Sie eine Zahl größer oder gleich Null ein",
"Please_enter_days": "Bitte geben Sie Tage ein",
"Password_is_too_short": "Das Passwort ist zu kurz",
"Passwords_do_not_match": "Passwörter stimmen nicht überein",
"Return_to_wiki_page": "Zurück zur Wiki-Seite",
"Insert_network_image": "Bild per URL einfügen",
"Upload_local_image": "Bild hochladen und einfügen",
"Add_link": "Link hinzufügen",
"File_history": "Dateiversionen",
"History_version": "Versionen",
"Back_to_viewer": "Zurück zur Vorschau",
"Link_title": "Linktext",
"Local_draft": "Lokaler Entwurf",
"Use_draft": "Entwurf verwenden",
"Delete_draft": "Entwurf löschen",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "Es gibt einen ungespeicherten Entwurf. Möchten Sie ihn verwenden?",
"Local_draft_saved": "Lokaler Entwurf gespeichert",
"New_draft": "Neuer Entwurf",
"View_draft": "Entwurf anzeigen",
"Publish": "Veröffentlichen",
"This_file_has_a_draft": "Zu dieser Datei gibt es einen Entwurf.",
"Delete": "Löschen",
"Comments": "Kommentare",
"Add_a_comment": "Kommentar einfügen",
"No_comment_yet": "Keine Kommentare vorhanden",
"Mark_as_Resolved": "Als erledigt markieren",
"ask_for_review": "Um ein Review bitten",
"review_already_exists": "Es gibt bereits ein Review.",
"view_review": "Review anzeigen",
"there_is_an_associated_review_with_this_file": "Es gibt ein Review zu dieser Datei.",
"start_review": "Review schreiben",
"this_file_is_in_draft_stage": "Die Datei hat den Status Entwurf",
"this_file_is_in_review_stage": "Die Datei hat den Status Review.",
"this_file_has_been_updated": "Die Datei wurde aktualisiert.",
"refresh": "Aktualisieren",
"related_files": "Zugehörige Dateien",
"related_file": "Zugehörige Datei",
"no_tags": "Keine Tags",
"Ask_for_review": "Um ein Review bitten",
"Review_already_exists": "Es gibt bereits ein Review.",
"View_review": "Review anzeigen",
"There_is_an_associated_review_with_this_file": "Es gibt ein Review zu dieser Datei.",
"Start_review": "Review schreiben",
"This_file_is_in_draft_stage": "Die Datei hat den Status Entwurf",
"This_file_is_in_review_stage": "Die Datei hat den Status Review.",
"This_file_has_been_updated": "Die Datei wurde aktualisiert.",
"Refresh": "Aktualisieren",
"Related_files": "Zugehörige Dateien",
"Related_file": "Zugehörige Datei",
"No_tags": "Keine Tags",
"Date": "Datum",
"Participants": "Teilnehmer",
"Meeting_note": "Besprechungsnotiz",
"Chooser_document_type": "Auswahl Dokumenttyp",
"Empty": "Leer",
"no_related_files": "Keine zugehörigen Dateien",
"no_out_line": "Keine Gliederung",
"No_related_files": "Keine zugehörigen Dateien",
"No_out_line": "Keine Gliederung",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Beim Bearbeiten von Dateien in diesem Browser können leichte Probleme bei der Anzeige auftreten.",
"no_document_improvement_suggestion": "Keine Vorschläge zur Verbesserung des Dokuments",
"No_document_improvement_suggestion": "Keine Vorschläge zur Verbesserung des Dokuments",
"Hide_side_panel": "Seitenleiste verbergen",
"Show_side_panel": "Seitenleiste anzeigen",
"Show_resolved_comments": "Erledigte Kommentare anzeigen",
@@ -131,25 +131,16 @@
"Insert_library_image": "Bild aus Bibliothek einfügen",
"Size": "Größe",
"Location": "Ort",
"Last_Update": "Letzte Änderung",
"Last_update": "Last update",
"Tags": "Tags",
"Related_Files": "Zugehörige Dateien",
"Add_participants": "Teilnehmer hinzufügen",
"markdownLint": {
"missing_h1": {
"description": "Es gibt keine Hauptüberschrift (h1) in dem Text",
"issue" : "Hauptüberschrift (h1) fehlt"
},
"heading_end_with_colon": {
"description": "Überschriften dürfen nicht mit einem Doppelpunkt enden.",
"issue": "Überschrift endet mit einem Doppelpunkt"
},
"heading_increase_irregular": {
"description": "Überschriften sollten in aufeinander folgenden Stufen angelegt werden",
"issue": "Stufe der Überschrift überprüfen"
}
},
"Clear_format": "Clear format",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Hilfe Tastenkombinationen",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Tastenkombinationen",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Textzeile einfügen",
"Increase_depth": "Einzug erhöhen"
}
}, {
},
{
"shortcutType": "Überschriften",
"shortcutData": {
"Heading_1": "Überschrift 1",
@@ -172,7 +164,8 @@
"Heading_5": "Überschrift 5",
"Heading_6": "Überschrift 6"
}
}, {
},
{
"shortcutType": "Codeblock",
"shortcutData": {
"Make_code_block": "Codeblock anlegen",
@@ -180,37 +173,43 @@
"Escape_code_block": "Codeblock beenden",
"Insert_indent": "Einzug erhöhen"
}
}, {
},
{
"shortcutType": "Blockquote",
"shortcutData": {
"Make_Block_quote": "Blockquote einfügen",
"Escape_Block_quote": "Blockquote beenden"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Tabellen",
"shortcutData": {
"Insert_Table_Row": "Tabellenzeile einfügen",
"Insert_table_row": "Insert table tow",
"Escape_table": "Tabelle beenden"
}
}, {
},
{
"shortcutType": "Formeln",
"shortcutData": {
"Insert_Formula": "Formel einfügen"
"Insert_formula": "Insert formula"
}
}, {
},
{
"shortcutType": "Textformatierung",
"shortcutData": {
"Bold": "Fett",
"Italic": "Kursiv",
"Italic_Bold": "Kursiv fett",
"Italic_bold": "Italic bold",
"Inline_code": "Inline-Code"
}
}, {
},
{
"shortcutType": "Speichern",
"shortcutData": {
"Save_file": "Datei speichern"
}
}, {
},
{
"shortcutType": "Bilder",
"shortcutData": {
"Paste_screen_shot": "Bild aus Zwischenablage einfügen",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Bold",
"italic": "Italic",
"inline_code": "Code",
"header_one": "Heading 1",
"header_two": "Heading 2",
"header_three": "Heading 3",
"header_four": "Heading 4",
"header_five": "Heading 5",
"header_six": "Heading 6",
"paragraph": "Paragraph",
"quote": "Quote",
"ordered_list": "Ordered List",
"unordered_list": "Unordered List",
"check_list_item": "Check List Item",
"insert_image": "Insert Image",
"insert_formula": "Insert Formula",
"formula": "Formula",
"insert_file": "Insert File",
"code": "Inline Code",
"code_block": "Code Block",
"insert_link": "Insert Link",
"insert_table": "Insert Table",
"save": "Save",
"more": "More",
"invalid_url": "Invalid URL",
"link_address": "Link address",
"image_address": "Image address",
"submit": "Submit",
"cancel": "Cancel",
"switch_to_plain_text_editor": "Switch to Plain Text Editor",
"switch_to_rich_text_editor": "Switch to Rich Text Editor",
"switch_to_viewer": "Switch to Markdown Viewer",
"help": "Help",
"remove_table": "Remove Table",
"column": "Column",
"row": "Row",
"Insert_Row_Before": "Insert Row Before",
"Insert_Row_After": "Insert Row After",
"Insert_Column_Before": "Insert Column Before",
"Insert_Column_After": "Insert Column After",
"Remove_Row": "Remove Row",
"Remove_Column": "Remove Column",
"Insert_Row": "Insert Row",
"Insert_Column": "Insert Column",
"set_align": "Set align",
"left": "Left",
"center": "Center",
"right": "Right",
"file_saved": "File saved.",
"file_failed_to_save": "File failed to save.",
"star": "Add star",
"unstar": "Remove star",
"back_to_parent_directory":"Back to parent directory",
"edit": "Edit",
"copy": "Copy",
"copied": "Copied",
"internal_link": "Internal Link",
"copy_internal_link": "Internal link has been copied to clipboard",
"internal_link_desc": "An internal link is a link to a file or folder that can be accessed by users with read permission to the file or folder.",
"share": "Share",
"share_link": "Share Link",
"generate": "Generate",
"add_password_protection": "Add password protection",
"password": "Password",
"at_least_8_characters": "at least 8 characters",
"password_again": "Password again",
"add_auto_expiration": "Add auto expiration",
"days": "days",
"please_enter_password": "Please enter password",
"greater_than_or_equal_to": "Greater than or equal to",
"less_than_or_equal_to": "Less than or equal to",
"set_permission": "Set permission",
"preview_and_download": "Preview and download",
"preview_only": "Preview only",
"please_enter_valid_days": "Please enter valid days",
"please_enter_a_non-negative_integer": "Please enter a non-negative integer",
"please_enter_days": "Please enter days",
"password_is_too_short": "Password is too short",
"passwords_do_not_match": "Passwords do not match",
"return_to_wiki_page": "Return to Wiki Page",
"insert_network_image": "Insert network image",
"upload_local_image": "Upload local image",
"add_link": "Add link",
"file_history": "File History",
"history_version": "History Versions",
"back_to_viewer": "Back To Viewer",
"link_title": "Link title",
"local_draft": "Local draft",
"use_draft": "Use draft",
"delete_draft": "Delete draft",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "You have an unsaved draft. Do you like to use it?",
"local_draft_saved": "Local draft saved",
"new_draft": "New Draft",
"view_draft": "View Draft",
"publish": "Publish",
"this_file_has_a_draft": "This file has a draft.",
"delete": "Delete",
"comments": "Comments",
"add_a_comment": "Add a comment...",
"no_comment_yet": "No comment yet.",
"Bold": "Bold",
"Italic": "Italic",
"Inline_code": "Code",
"Header_one": "Heading 1",
"Header_two": "Heading 2",
"Header_three": "Heading 3",
"Header_four": "Heading 4",
"Header_five": "Heading 5",
"Header_six": "Heading 6",
"Paragraph": "Paragraph",
"Quote": "Quote",
"Ordered_list": "Ordered List",
"Unordered_list": "Unordered List",
"Check_list_item": "Check List Item",
"Insert_image": "Insert Image",
"Insert_formula": "Insert Formula",
"Formula": "Formula",
"Insert_file": "Insert File",
"Code": "Inline Code",
"Code_block": "Code Block",
"Insert_link": "Insert Link",
"Insert_table": "Insert Table",
"Save": "Save",
"More": "More",
"Invalid_url": "Invalid URL",
"Link_address": "Link address",
"Image_address": "Image address",
"Submit": "Submit",
"Cancel": "Cancel",
"Switch_to_plain_text_editor": "Switch to Plain Text Editor",
"Switch_to_rich_text_editor": "Switch to Rich Text Editor",
"Switch_to_viewer": "Switch to Markdown Viewer",
"Help": "Help",
"Remove_table": "Remove Table",
"Column": "Column",
"Row": "Row",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insert row",
"Insert_column": "Insert column",
"Set_align": "Set align",
"Left": "Left",
"Center": "Center",
"Right": "Right",
"File_saved": "File saved.",
"File_failed_to_save": "File failed to save.",
"Star": "Add star",
"Unstar": "Remove star",
"Back_to_parent_directory": "Back to parent directory",
"Edit": "Edit",
"Copy": "Copy",
"Copied": "Copied",
"Internal_link": "Internal Link",
"Copy_internal_link": "Internal link has been copied to clipboard",
"Internal_link_desc": "An internal link is a link to a file or folder that can be accessed by users with read permission to the file or folder.",
"Share": "Share",
"Share_link": "Share Link",
"Generate": "Generate",
"Add_password_protection": "Add password protection",
"Password": "Password",
"At_least_8_characters": "at least 8 characters",
"Password_again": "Password again",
"Add_auto_expiration": "Add auto expiration",
"Days": "days",
"Please_enter_password": "Please enter password",
"Greater_than_or_equal_to": "Greater than or equal to",
"Less_than_or_equal_to": "Less than or equal to",
"Set_permission": "Set permission",
"Preview_and_download": "Preview and download",
"Preview_only": "Preview only",
"Please_enter_valid_days": "Please enter valid days",
"Please_enter_a_non-negative_integer": "Please enter a non-negative integer",
"Please_enter_days": "Please enter days",
"Password_is_too_short": "Password is too short",
"Passwords_do_not_match": "Passwords do not match",
"Return_to_wiki_page": "Return to Wiki Page",
"Insert_network_image": "Insert network image",
"Upload_local_image": "Upload local image",
"Add_link": "Add link",
"File_history": "File History",
"History_version": "History Versions",
"Back_to_viewer": "Back To Viewer",
"Link_title": "Link title",
"Local_draft": "Local draft",
"Use_draft": "Use draft",
"Delete_draft": "Delete draft",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "You have an unsaved draft. Do you like to use it?",
"Local_draft_saved": "Local draft saved",
"New_draft": "New Draft",
"View_draft": "View Draft",
"Publish": "Publish",
"This_file_has_a_draft": "This file has a draft.",
"Delete": "Delete",
"Comments": "Comments",
"Add_a_comment": "Add a comment...",
"No_comment_yet": "No comment yet.",
"Mark_as_Resolved": "Mark as Resolved",
"ask_for_review": "Ask for review",
"review_already_exists": "Review already exists",
"view_review": "View review",
"there_is_an_associated_review_with_this_file": "There is an associated review with this file.",
"start_review": "Start Review",
"this_file_is_in_draft_stage": "This file is in draft stage.",
"this_file_is_in_review_stage": "This file is in review stage.",
"this_file_has_been_updated": "This file has been updated.",
"refresh": "Refresh",
"related_files": "related files",
"related_file": "related file",
"no_tags": "No tags",
"Ask_for_review": "Ask for review",
"Review_already_exists": "Review already exists",
"View_review": "View review",
"There_is_an_associated_review_with_this_file": "There is an associated review with this file.",
"Start_review": "Start Review",
"This_file_is_in_draft_stage": "This file is in draft stage.",
"This_file_is_in_review_stage": "This file is in review stage.",
"This_file_has_been_updated": "This file has been updated.",
"Refresh": "Refresh",
"Related_files": "related files",
"Related_file": "related file",
"No_tags": "No tags",
"Date": "Date",
"Participants": "Participants",
"Meeting_note": "Meeting note",
"Chooser_document_type": "Chooser document type",
"Empty": "Empty",
"no_related_files": "No related files",
"no_out_line": "No outline",
"No_related_files": "No related files",
"No_out_line": "No outline",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Editing files in this browser can lead to slight display problems.",
"no_document_improvement_suggestion": "No document improvement suggestion",
"No_document_improvement_suggestion": "No document improvement suggestion",
"Hide_side_panel": "Hide side panel",
"Show_side_panel": "Show side panel",
"Show_resolved_comments": "Show resolved comments",
@@ -131,25 +131,16 @@
"Insert_library_image": "Insert library image",
"Size": "Size",
"Location": "Location",
"Last_Update": "Last Update",
"Last_update": "Last update",
"Tags": "Tags",
"Related_Files": "Related Files",
"Add_participants": "Add participants",
"markdownLint": {
"missing_h1": {
"description": "There is no h1 in the document",
"issue" : "Missing h1"
},
"heading_end_with_colon": {
"description": "Trailing punctuation in heading should not be a colon",
"issue": "Heading ends width colon"
},
"heading_increase_irregular": {
"description": "Heading levels should only increment by one level at a time",
"issue": "Heading level issue"
}
},
"Clear_format": "Clear format",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Shortcut help",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Keyboard shortcuts",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Insert child in item",
"Increase_depth": "Increase depth"
}
}, {
},
{
"shortcutType": "Head shortcuts",
"shortcutData": {
"Heading_1": "Heading 1",
@@ -172,7 +164,8 @@
"Heading_5": "Heading 5",
"Heading_6": "Heading 6"
}
}, {
},
{
"shortcutType": "Code block shortcuts",
"shortcutData": {
"Make_code_block": "Make code block",
@@ -180,37 +173,43 @@
"Escape_code_block": "Escape code block",
"Insert_indent": "Insert indent"
}
}, {
},
{
"shortcutType": "Block quote shortcuts",
"shortcutData": {
"Make_Block_quote": "Make Block quote",
"Escape_Block_quote": "Escape Block quote"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Table shortcuts",
"shortcutData": {
"Insert_Table_Row": "Insert Table Row",
"Insert_table_row": "Insert table tow",
"Escape_table": "Escape table"
}
}, {
},
{
"shortcutType": "Formula shortcuts",
"shortcutData": {
"Insert_Formula": "Insert Formula"
"Insert_formula": "Insert formula"
}
}, {
},
{
"shortcutType": "Inline shortcuts",
"shortcutData": {
"Bold": "Bold",
"Italic": "Italic",
"Italic_Bold": "Italic Bold",
"Italic_bold": "Italic bold",
"Inline_code": "Inline code"
}
}, {
},
{
"shortcutType": "Save shortcuts",
"shortcutData": {
"Save_file": "Save file"
}
}, {
},
{
"shortcutType": "Image shortcuts",
"shortcutData": {
"Paste_screen_shot": "Paste screen shot",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Negrita",
"italic": "Itálica",
"inline_code": "Código",
"header_one": "Encabezado 1",
"header_two": "Encabezado 2",
"header_three": "Encabezado 3",
"header_four": "Encabezado 4",
"header_five": "Encabezado 5",
"header_six": "Encabezado 6",
"paragraph": "Párrafo",
"quote": "Cita",
"ordered_list": "Lista Ordenada",
"unordered_list": "Lista Desordenada",
"check_list_item": "Check List Item",
"insert_image": "Insertar Imagen",
"insert_formula": "Insertar Fórmula",
"formula": "Fórmula",
"insert_file": "Insertar Archivo",
"code": "Inline Code",
"code_block": "Bloque de Código",
"insert_link": "Insertar Enlace",
"insert_table": "Insertar Tabla",
"save": "Guardar",
"more": "Más",
"invalid_url": "URL Inválida",
"link_address": "Dirección del enlace",
"image_address": "Dirección de la imagen",
"submit": "Enviar",
"cancel": "Cancelar",
"switch_to_plain_text_editor": "Cambiar a editor de texto sin formato",
"switch_to_rich_text_editor": "Cambiar a editor de texto enriquecido",
"switch_to_viewer": "Cambiar a visualizador Markdown",
"help": "Ayuda",
"remove_table": "Eliminar tabla",
"column": "Columna",
"row": "Fila",
"Insert_Row_Before": "Insertar Línea Antes",
"Insert_Row_After": "Insertar Línea Después",
"Insert_Column_Before": "Insertar Columna Antes",
"Insert_Column_After": "Insertar Columna Después",
"Remove_Row": "Eliminar Fila",
"Remove_Column": "Eliminar Columna",
"Insert_Row": "Insertar Fila",
"Insert_Column": "Insertar Columna",
"set_align": "Establecer alineación",
"left": "Izquierda",
"center": "Centrar",
"right": "derecha",
"file_saved": "Archivo guardado",
"file_failed_to_save": "Fallo al guardar archivo",
"star": "Add star",
"unstar": "Remove star",
"back_to_parent_directory":"Volver a la carpeta superior",
"edit": "Editar",
"copy": "Copiar",
"copied": "Copiado",
"internal_link": "Enlace interno",
"copy_internal_link": "El enlace interno ha sido copiado al portapapeles",
"internal_link_desc": "Un enlace interno es un enlace a un archivo o carpeta que puede ser accedido por usuarios con permiso de lectura al archivo o carpeta. ",
"share": "Compartir",
"share_link": "Compartir enlace",
"generate": "Generar",
"add_password_protection": "Agregar protección por contraseña",
"password": "Contraseña ",
"at_least_8_characters": "al menos 8 caracteres",
"password_again": "Repetir contraseña",
"add_auto_expiration": "Agregar vencimiento automático",
"days": "días",
"please_enter_password": "Ingresa una contraseña",
"greater_than_or_equal_to": "Mayor o igual que",
"less_than_or_equal_to": "Menor o igual que",
"set_permission": "Establecer permiso",
"preview_and_download": "Vista previa y descargar",
"preview_only": "Vista previa solamente",
"please_enter_valid_days": "Ingresa cantidad válida de días",
"please_enter_a_non-negative_integer": "Por favor, ingrese un número entero no negativo",
"please_enter_days": "Ingresa cantidad de días",
"password_is_too_short": "Contraseña demasiado corta",
"passwords_do_not_match": "Las contraseñas no concuerdan",
"return_to_wiki_page": "Volver a la página del Wiki",
"insert_network_image": "Insertar imágen desde la red",
"upload_local_image": "Subir imagen local",
"add_link": "Agregar enlace",
"file_history": "Historial del Archivo",
"history_version": "Historial de Versiones",
"back_to_viewer": "Volver al Visualizador",
"link_title": "Título del enlace",
"local_draft": "Borrador local",
"use_draft": "Usar borrador",
"delete_draft": "Eliminar borrador",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "Tienes un borrador sin guardar. ¿Deseas utilizarlo?",
"local_draft_saved": "Borrador local guardado",
"new_draft": "Nuevo Borrador",
"view_draft": "Ver Borrador",
"publish": "Publicar",
"this_file_has_a_draft": "Este archivo tiene un borrador",
"delete": "Borrar",
"comments": "Comentarios",
"add_a_comment": "Agregar un comentario...",
"no_comment_yet": "No hay comentarios.",
"Bold": "Negrita",
"Italic": "Itálica",
"Inline_code": "Código",
"Header_one": "Encabezado 1",
"Header_two": "Encabezado 2",
"Header_three": "Encabezado 3",
"Header_four": "Encabezado 4",
"Header_five": "Encabezado 5",
"Header_six": "Encabezado 6",
"Paragraph": "Párrafo",
"Quote": "Cita",
"Ordered_list": "Lista Ordenada",
"Unordered_list": "Lista Desordenada",
"Check_list_item": "Check List Item",
"Insert_image": "Insertar Imagen",
"Insert_formula": "Insertar Fórmula",
"Formula": "Fórmula",
"Insert_file": "Insertar Archivo",
"Code": "Inline Code",
"Code_block": "Bloque de Código",
"Insert_link": "Insertar Enlace",
"Insert_table": "Insertar Tabla",
"Save": "Guardar",
"More": "Más",
"Invalid_url": "URL Inválida",
"Link_address": "Dirección del enlace",
"Image_address": "Dirección de la imagen",
"Submit": "Enviar",
"Cancel": "Cancelar",
"Switch_to_plain_text_editor": "Cambiar a editor de texto sin formato",
"Switch_to_rich_text_editor": "Cambiar a editor de texto enriquecido",
"Switch_to_viewer": "Cambiar a visualizador Markdown",
"Help": "Ayuda",
"Remove_table": "Eliminar tabla",
"Column": "Columna",
"Row": "Fila",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insert row",
"Insert_column": "Insert column",
"Set_align": "Establecer alineación",
"Left": "Izquierda",
"Center": "Centrar",
"Right": "derecha",
"File_saved": "Archivo guardado",
"File_failed_to_save": "Fallo al guardar archivo",
"Star": "Add star",
"Unstar": "Remove star",
"Back_to_parent_directory": "Volver a la carpeta superior",
"Edit": "Editar",
"Copy": "Copiar",
"Copied": "Copiado",
"Internal_link": "Enlace interno",
"Copy_internal_link": "El enlace interno ha sido copiado al portapapeles",
"Internal_link_desc": "Un enlace interno es un enlace a un archivo o carpeta que puede ser accedido por usuarios con permiso de lectura al archivo o carpeta. ",
"Share": "Compartir",
"Share_link": "Compartir enlace",
"Generate": "Generar",
"Add_password_protection": "Agregar protección por contraseña",
"Password": "Contraseña ",
"At_least_8_characters": "al menos 8 caracteres",
"Password_again": "Repetir contraseña",
"Add_auto_expiration": "Agregar vencimiento automático",
"Days": "días",
"Please_enter_password": "Ingresa una contraseña",
"Greater_than_or_equal_to": "Mayor o igual que",
"Less_than_or_equal_to": "Menor o igual que",
"Set_permission": "Establecer permiso",
"Preview_and_download": "Vista previa y descargar",
"Preview_only": "Vista previa solamente",
"Please_enter_valid_days": "Ingresa cantidad válida de días",
"Please_enter_a_non-negative_integer": "Por favor, ingrese un número entero no negativo",
"Please_enter_days": "Ingresa cantidad de días",
"Password_is_too_short": "Contraseña demasiado corta",
"Passwords_do_not_match": "Las contraseñas no concuerdan",
"Return_to_wiki_page": "Volver a la página del Wiki",
"Insert_network_image": "Insertar imágen desde la red",
"Upload_local_image": "Subir imagen local",
"Add_link": "Agregar enlace",
"File_history": "Historial del Archivo",
"History_version": "Historial de Versiones",
"Back_to_viewer": "Volver al Visualizador",
"Link_title": "Título del enlace",
"Local_draft": "Borrador local",
"Use_draft": "Usar borrador",
"Delete_draft": "Eliminar borrador",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "Tienes un borrador sin guardar. ¿Deseas utilizarlo?",
"Local_draft_saved": "Borrador local guardado",
"New_draft": "Nuevo Borrador",
"View_draft": "Ver Borrador",
"Publish": "Publicar",
"This_file_has_a_draft": "Este archivo tiene un borrador",
"Delete": "Borrar",
"Comments": "Comentarios",
"Add_a_comment": "Agregar un comentario...",
"No_comment_yet": "No hay comentarios.",
"Mark_as_Resolved": "Marcar como Resuelto",
"ask_for_review": "Solicitar revisión",
"review_already_exists": "La revisión ya existe",
"view_review": "Ver revisión",
"there_is_an_associated_review_with_this_file": "Hay una revisión asociada con este archivo",
"start_review": "Iniciar revisión",
"this_file_is_in_draft_stage": "Este archivo está en la etapa de borrador",
"this_file_is_in_review_stage": "Este archivo está en estado de revisión.",
"this_file_has_been_updated": "Este archivo ha sido actualizado.",
"refresh": "Refrescar",
"related_files": "archivos relacionados",
"related_file": "archivo relacionado",
"no_tags": "Sin etiquetas",
"Ask_for_review": "Solicitar revisión",
"Review_already_exists": "La revisión ya existe",
"View_review": "Ver revisión",
"There_is_an_associated_review_with_this_file": "Hay una revisión asociada con este archivo",
"Start_review": "Iniciar revisión",
"This_file_is_in_draft_stage": "Este archivo está en la etapa de borrador",
"This_file_is_in_review_stage": "Este archivo está en estado de revisión.",
"This_file_has_been_updated": "Este archivo ha sido actualizado.",
"Refresh": "Refrescar",
"Related_files": "archivos relacionados",
"Related_file": "archivo relacionado",
"No_tags": "Sin etiquetas",
"Date": "Fecha",
"Participants": "Participantes",
"Meeting_note": "Nota de la reunión",
"Chooser_document_type": "Elija el tipo de documento",
"Empty": "Vacío",
"no_related_files": "Sin archivos relacionados",
"no_out_line": "No hay esquema",
"No_related_files": "Sin archivos relacionados",
"No_out_line": "No hay esquema",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Editar archivos en este navegador puede producir algunos problemas en el display.",
"no_document_improvement_suggestion": "No hay sugerencias para mejorar el documento",
"No_document_improvement_suggestion": "No hay sugerencias para mejorar el documento",
"Hide_side_panel": "Ocultar panel lateral",
"Show_side_panel": "Mostrar panel lateral",
"Show_resolved_comments": "Mostrar comentarios resueltos",
@@ -131,25 +131,16 @@
"Insert_library_image": "Insertar imagen desde la biblioteca",
"Size": "Tamaño",
"Location": "Ubicación",
"Last_Update": "Última actualización",
"Last_update": "Last update",
"Tags": "Rótulos",
"Related_Files": "Archivos Relacionados",
"Add_participants": "Agregar participantes",
"markdownLint": {
"missing_h1": {
"description": "No hay h1 en el documento",
"issue" : "Falta h1"
},
"heading_end_with_colon": {
"description": "Un encabezado no debe finalizar con el signo Dos Puntos",
"issue": "El encabezado finaliza con el signo Dos Puntos"
},
"heading_increase_irregular": {
"description": "Los niveles del encabezado sólo deben incrementarse de a uno por vez",
"issue": "Problema con nivel de encabezado"
}
},
"Clear_format": "Clear format",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Ayuda de atajos",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Atajos de teclado",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Insert child in item",
"Increase_depth": "Increase depth"
}
}, {
},
{
"shortcutType": "Head shortcuts",
"shortcutData": {
"Heading_1": "Encabezado 1",
@@ -172,7 +164,8 @@
"Heading_5": "Encabezado 5",
"Heading_6": "Encabezado 6"
}
}, {
},
{
"shortcutType": "Code block shortcuts",
"shortcutData": {
"Make_code_block": "Crear bloque de código",
@@ -180,37 +173,43 @@
"Escape_code_block": "Escape code block",
"Insert_indent": "Insert indent"
}
}, {
},
{
"shortcutType": "Block quote shortcuts",
"shortcutData": {
"Make_Block_quote": "Make Block quote",
"Escape_Block_quote": "Escape Block quote"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Atajos de tabla",
"shortcutData": {
"Insert_Table_Row": "Insertar fila de tabla",
"Insert_table_row": "Insert table tow",
"Escape_table": "Escape table"
}
}, {
},
{
"shortcutType": "Atajos de fórmula",
"shortcutData": {
"Insert_Formula": "Insertar Fórmula"
"Insert_formula": "Insert formula"
}
}, {
},
{
"shortcutType": "Inline shortcuts",
"shortcutData": {
"Bold": "Negrita",
"Italic": "Itálica",
"Italic_Bold": "Negrita itálica",
"Italic_bold": "Italic bold",
"Inline_code": "Inline code"
}
}, {
},
{
"shortcutType": "Guardar atajos",
"shortcutData": {
"Save_file": "Guardar archivo"
}
}, {
},
{
"shortcutType": "Atajos de imagen",
"shortcutData": {
"Paste_screen_shot": "Pegar captura de pantalla",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Gras",
"italic": "Italique",
"inline_code": "Code",
"header_one": "Titre 1",
"header_two": "Titre 2",
"header_three": "Titre 3",
"header_four": "Titre 4",
"header_five": "Titre 5",
"header_six": "Titre 6",
"paragraph": "Paragraphe",
"quote": "Blockquote",
"ordered_list": "Numérotation",
"unordered_list": "Enumeration",
"check_list_item": "Case à chocher",
"insert_image": "Image",
"insert_formula": "Insérer formule",
"formula": "Formule",
"insert_file": "Fichier",
"code": "Ligne de code",
"code_block": "Bloc de code",
"insert_link": "Lien",
"insert_table": "Tableau",
"save": "Sauvegarder",
"more": "Plus",
"invalid_url": "L'adresse n'est pas valide",
"link_address": "Adresse du lien",
"image_address": "Adresse de l'image",
"submit": "Soumettre",
"cancel": "Annuler",
"switch_to_plain_text_editor": "Basculer en éditeur de texte plein",
"switch_to_rich_text_editor": "Basculer en éditeur de texte riche",
"switch_to_viewer": "Basculer en visualiseur Markdown",
"help": "Aide",
"remove_table": "Supprimer le tableau",
"column": "Colonne",
"row": "ligne",
"Insert_Row_Before": "Insérer au-dessus",
"Insert_Row_After": "Insérer en-dessous",
"Insert_Column_Before": "Insérer à gauche",
"Insert_Column_After": "Insérer à droite",
"Remove_Row": "Supprimer la ligne",
"Remove_Column": "Supprimer la colonne",
"Insert_Row": "Insérer une ligne",
"Insert_Column": "Insérer une colonne",
"set_align": "Ajuster l'alignement",
"left": "Gauche",
"center": "Centrer",
"right": "Droite",
"file_saved": "Le fichier a été sauvegardé.",
"file_failed_to_save": "Échec de la sauvegarde du fichier",
"star": "Ajouter à favoris",
"unstar": "Enlever des favoris",
"back_to_parent_directory":"Retour au répertoire parent",
"edit": "Modifier",
"copy": "Copier",
"copied": "Copié",
"internal_link": "Afficher le lien interne",
"copy_internal_link": "Le lien interne a été copié dans le presse-papiers.",
"internal_link_desc": "Un lien interne est un lien vers un fichier ou un dossier accessible en lecture par un utilisateur.",
"share": "Partager",
"share_link": "Lien de téléchargement",
"generate": "Créer",
"add_password_protection": "Ajouter un mot de passe",
"password": "Mot de passe",
"at_least_8_characters": "Au moins 8 caractères",
"password_again": "Mot de passe (à nouveau)",
"add_auto_expiration": "Ajouter une date d'expiration",
"days": "jours",
"please_enter_password": "Entrez un mot de passe",
"greater_than_or_equal_to": "Plus grand ou égale à",
"less_than_or_equal_to": "Plus petit ou égal à",
"set_permission": "Définir la permission",
"preview_and_download": "Prévisualiser et télécharger",
"preview_only": "Aperçu uniquement",
"please_enter_valid_days": "Saisissez un nombre de jours valide",
"please_enter_a_non-negative_integer": "Veuillez introduire un intégrateur non-négatif",
"please_enter_days": "Veuillez entrer un nombre de jours",
"password_is_too_short": "Le mot de passe est trop court",
"passwords_do_not_match": "Les mots de passe ne correspondent pas.",
"return_to_wiki_page": "Retour à la page du Wiki",
"insert_network_image": "Insérer une image du réseau",
"upload_local_image": "Insérer une image locale",
"add_link": "Ajouter un lien",
"file_history": "Historique du fichier",
"history_version": "Historique des versions",
"back_to_viewer": "Retour au visualiseur",
"link_title": "Titre du lien",
"local_draft": "Brouillon local",
"use_draft": "Utiliser le brouillon",
"delete_draft": "Supprimer le brouillon",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "Vous avez un brouillon qui n'est pas sauvegardé. Voulez-vous l'utiliser ?",
"local_draft_saved": "Brouillon local sauvegardé",
"new_draft": "Nouveau brouillon",
"view_draft": "Voir le brouillon",
"publish": "Publier",
"this_file_has_a_draft": "Ce fichier possède un brouillon.",
"delete": "Supprimer",
"comments": "Commentaires",
"add_a_comment": "Ajouter un commentaire",
"no_comment_yet": "Aucun commentaire disponible",
"Bold": "Gras",
"Italic": "Italique",
"Inline_code": "Code",
"Header_one": "Titre 1",
"Header_two": "Titre 2",
"Header_three": "Titre 3",
"Header_four": "Titre 4",
"Header_five": "Titre 5",
"Header_six": "Titre 6",
"Paragraph": "Paragraphe",
"Quote": "Blockquote",
"Ordered_list": "Liste ordonée",
"Unordered_list": "Liste non-ordonée",
"Check_list_item": "Liste à chocher",
"Insert_image": "Image",
"Insert_formula": "Insérer formule",
"Formula": "Formule",
"Insert_file": "Fichier",
"Code": "Ligne de code",
"Code_block": "Bloc de code",
"Insert_link": "Lien",
"Insert_table": "Tableau",
"Save": "Sauvegarder",
"More": "Plus",
"Invalid_url": "L'adresse n'est pas valide.",
"Link_address": "Adresse du lien",
"Image_address": "Adresse de l'image",
"Submit": "Soummettre",
"Cancel": "Annuler",
"Switch_to_plain_text_editor": "Basculer en éditeur de texte plein",
"Switch_to_rich_text_editor": "Basculer en éditeur de texte riche",
"Switch_to_viewer": "Basculer en visualiseur Markdown",
"Help": "Aide",
"Remove_table": "Supprimer le tableau",
"Column": "Colonne",
"Row": "Ligne",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insérer une ligne",
"Insert_column": "Insérer une colonne",
"Set_align": "Ajuster l'alignement",
"Left": "Gauche",
"Center": "Centrer",
"Right": "Droite",
"File_saved": "Le fichier a été sauvegardé.",
"File_failed_to_save": "Échec de la sauvegarde du fichier",
"Star": "Ajouter à favoris",
"Unstar": "Enlever des favoris",
"Back_to_parent_directory": "Retour au répertoire parent",
"Edit": "Modifier",
"Copy": "Copier",
"Copied": "Copié",
"Internal_link": "Afficher le lien interne",
"Copy_internal_link": "Le lien interne a été copié dans le presse-papiers.",
"Internal_link_desc": "Un lien interne est un lien vers un fichier ou un dossier accessible en lecture par un utilisateur.",
"Share": "Partager",
"Share_link": "Lien de téléchargement",
"Generate": "Créer",
"Add_password_protection": "Ajouter un mot de passe",
"Password": "Mot de passe",
"At_least_8_characters": "Au moins 8 caractères",
"Password_again": "Mot de passe (à nouveau)",
"Add_auto_expiration": "Ajouter une date d'expiration",
"Days": "jours",
"Please_enter_password": "Entrez un mot de passe",
"Greater_than_or_equal_to": "Plus grand ou égale à",
"Less_than_or_equal_to": "Plus petit ou égal à",
"Set_permission": "Définir la permission",
"Preview_and_download": "Prévisualiser et télécharger",
"Preview_only": "Aperçu uniquement",
"Please_enter_valid_days": "Saisissez un nombre de jours valide.",
"Please_enter_a_non-negative_integer": "Veuillez introduire un intégrateur non-négatif.",
"Please_enter_days": "Veuillez entrer un nombre de jours.",
"Password_is_too_short": "Le mot de passe est trop court.",
"Passwords_do_not_match": "Les mots de passe ne correspondent pas.",
"Return_to_wiki_page": "Retour à la page du Wiki",
"Insert_network_image": "Insérer une image du réseau",
"Upload_local_image": "Insérer une image locale",
"Add_link": "Ajouter un lien",
"File_history": "Voir historique",
"History_version": "Historique des versions",
"Back_to_viewer": "Retour au visualiseur",
"Link_title": "Titre du lien",
"Local_draft": "Brouillon local",
"Use_draft": "Utiliser le brouillon",
"Delete_draft": "Supprimer le brouillon",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "Vous avez un brouillon qui n'est pas sauvegardé. Voulez-vous l'utiliser ?",
"Local_draft_saved": "Brouillon local sauvegardé",
"New_draft": "Nouveau brouillon",
"View_draft": "Voir le brouillon",
"Publish": "Publier",
"This_file_has_a_draft": "Ce fichier possède un brouillon.",
"Delete": "Supprimer",
"Comments": "Commentaires",
"Add_a_comment": "Ajouter un commentaire",
"No_comment_yet": "Aucun commentaire disponible",
"Mark_as_Resolved": "Marquer com pris en compte",
"ask_for_review": "Demande d'un avis",
"review_already_exists": "Un avis existe déjà",
"view_review": "Voir l'avis",
"there_is_an_associated_review_with_this_file": "Il y a un avis associé à ce fichier.",
"start_review": "Commencer l'avis",
"this_file_is_in_draft_stage": "Ce fichier est à l'état de brouillon.",
"this_file_is_in_review_stage": "Ce fichier est à l'état d'avis.",
"this_file_has_been_updated": "Ce fichier à été mis à jour.",
"refresh": "Rafraichir",
"related_files": "Fichiers relatifs",
"related_file": "Fichier relatif",
"no_tags": "Pas de tag",
"Ask_for_review": "Demande d'un avis",
"Review_already_exists": "Un avis existe déjà.",
"View_review": "Voir l'avis",
"There_is_an_associated_review_with_this_file": "Il y a un avis associé à ce fichier.",
"Start_review": "Commencer l'avis",
"This_file_is_in_draft_stage": "Ce fichier est à l'état de brouillon.",
"This_file_is_in_review_stage": "Ce fichier est à l'état d'avis.",
"This_file_has_been_updated": "Ce fichier à été mis à jour.",
"Refresh": "Rafraichir",
"Related_files": "Fichiers relatifs",
"Related_file": "Fichier relatif",
"No_tags": "Pas de tag",
"Date": "Date",
"Participants": "Participants",
"Meeting_note": "Note de réunion",
"Chooser_document_type": "Choisir un type de document",
"Empty": "Vide",
"no_related_files": "Aucun fichier relatif",
"no_out_line": "Pas de contour",
"No_related_files": "Aucun fichier relatif",
"No_out_line": "Pas de contour",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "L'édition de fichiers dans ce navigateur peut entraîner de légers problèmes d'affichage.",
"no_document_improvement_suggestion": "Aucune proposition pour améliorer le document",
"No_document_improvement_suggestion": "Aucune proposition pour améliorer le document",
"Hide_side_panel": "Fermer",
"Show_side_panel": "Afficher détails",
"Show_resolved_comments": "Voir les commentaires pris en compte",
@@ -131,25 +131,16 @@
"Insert_library_image": "Insérer une image dune bibliothèque",
"Size": "Taille",
"Location": "Emplacement",
"Last_Update": "Mise à jour",
"Last_update": "Dernière mise à jour",
"Tags": "Tags",
"Related_Files": "Fichiers relatifs",
"Add_participants": "Ajouter des participants",
"markdownLint": {
"missing_h1": {
"description": "Il n'y a pas de h1 dans le document",
"issue" : "h1 manquant"
},
"heading_end_with_colon": {
"description": "La ponctuation de fin de titre ne doit pas être deux points",
"issue": "Fin du titre largeur de colonne"
},
"heading_increase_irregular": {
"description": "Le niveau des titres ne doit être augmenté que d'un niveau à la fois.",
"issue": "Problème niveau de titre"
}
},
"Clear_format": "Sans formatage",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Aide raccourcis",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Raccourcis clavier",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Insérer enfant dans l'élément",
"Increase_depth": "Améliorer la profondeur"
}
}, {
},
{
"shortcutType": "Raccourcis en-tête",
"shortcutData": {
"Heading_1": "Titre 1",
@@ -172,7 +164,8 @@
"Heading_5": "Titre 5",
"Heading_6": "Titre 6"
}
}, {
},
{
"shortcutType": "Raccourcis de blocs de code",
"shortcutData": {
"Make_code_block": "Faire un bloc de code",
@@ -180,37 +173,43 @@
"Escape_code_block": "Sortir du bloc de code",
"Insert_indent": "Insérer un espace"
}
}, {
},
{
"shortcutType": "Raccourcis blocs de citation",
"shortcutData": {
"Make_Block_quote": "Faire un bloc de citation",
"Escape_Block_quote": "Sortir du bloc de citation"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Raccourcis tableau",
"shortcutData": {
"Insert_Table_Row": "Insérer une ligne à la table",
"Insert_table_row": "Insert table tow",
"Escape_table": "Sortir de la table"
}
}, {
},
{
"shortcutType": "Raccourcis formule",
"shortcutData": {
"Insert_Formula": "Insérer formule"
"Insert_formula": "Insérer formule"
}
}, {
},
{
"shortcutType": "Raccourcis en ligne",
"shortcutData": {
"Bold": "Gras",
"Italic": "Italique",
"Italic_Bold": "Italique Gras",
"Italic_bold": "Italic bold",
"Inline_code": "Ligne de code"
}
}, {
},
{
"shortcutType": "Raccourcis sauvegarde",
"shortcutData": {
"Save_file": "Sauvegarder le fichier"
}
}, {
},
{
"shortcutType": "Raccourcis image",
"shortcutData": {
"Paste_screen_shot": "Coller la capture d'écran",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Grassetto",
"italic": "Corsivo",
"inline_code": "Codice",
"header_one": "Titolo 1",
"header_two": "Titolo 2",
"header_three": "Titolo 3",
"header_four": "Titolo 4",
"header_five": "Intestazione 5",
"header_six": "Intestazione 6",
"paragraph": "Paragrafo",
"quote": "Citazione",
"ordered_list": "Lista ordinata",
"unordered_list": "Lista non ordinata",
"check_list_item": "Controlla la voce dell'elenco",
"insert_image": "Inserisci Immagine",
"insert_formula": "Insert Formula",
"formula": "Formula",
"insert_file": "Insert File",
"code": "Codice in linea",
"code_block": "Codice",
"insert_link": "Inserisci Collegamento",
"insert_table": "Inserisci tabella",
"save": "Salvare",
"more": "Altro",
"invalid_url": "URL non valida",
"link_address": "Indirizzo collegamento",
"image_address": "Indirizzo Immagine",
"submit": "Invia",
"cancel": "Annulla",
"switch_to_plain_text_editor": "Passa all'Editor di testo semplice",
"switch_to_rich_text_editor": "Passa all'Editor di testo formattato",
"switch_to_viewer": "Passa alla vista di tipo Markdown",
"help": "Aiuto",
"remove_table": "Rimuovere Tabella",
"column": "Colonna",
"row": "Riga",
"Insert_Row_Before": "Insert Row Before",
"Insert_Row_After": "Insert Row After",
"Insert_Column_Before": "Insert Column Before",
"Insert_Column_After": "Insert Column After",
"Remove_Row": "Remove Row",
"Remove_Column": "Remove Column",
"Insert_Row": "Insert Row",
"Insert_Column": "Insert Column",
"set_align": "Imposta allineamento",
"left": "Sinistra",
"center": "Centrato",
"right": "Destra",
"file_saved": "File salvato.",
"file_failed_to_save": "Errore salvataggio file.",
"star": "Aggiungi asterisco",
"unstar": "Rimozione asterisco",
"back_to_parent_directory":"Torna alla cartella precedente",
"edit": "Modifica",
"copy": "Copia",
"copied": "Copiato",
"internal_link": "Collegamento interno",
"copy_internal_link": "Il collegamento interno è stato copiato negli appunti",
"internal_link_desc": "Un collegamento interno è un collegamento a un file o una cartella a cui gli utenti possono accedere con autorizzazione di lettura al file o alla cartella.",
"share": "Condividi",
"share_link": "Condividi Collegamento",
"generate": "Generare",
"add_password_protection": "Aggiungi la protezione password",
"password": "Password",
"at_least_8_characters": "almeno 8 caratteri",
"password_again": "Ridigita password",
"add_auto_expiration": "Aggiungi la scadenza automatica",
"days": "giorni",
"please_enter_password": "Per favore, inserisci la password",
"greater_than_or_equal_to": "Maggiore o uguale a ",
"less_than_or_equal_to": "Minore o uguale a",
"set_permission": "Imposta permessi",
"preview_and_download": "Anteprima e scarica",
"preview_only": "Solo Anteprima",
"please_enter_valid_days": "Si prega di inserire giorni validi",
"please_enter_a_non-negative_integer": "Prego inserire un intero non negativo",
"please_enter_days": "Prego inserire i giorni",
"password_is_too_short": "La password è troppo corta",
"passwords_do_not_match": "Le password non corrispondono",
"return_to_wiki_page": "Torna alla pagina Wiki",
"insert_network_image": "Inserisci immagine di rete",
"upload_local_image": "Inserisci immagine locale",
"add_link": "Aggiungi collegamento",
"file_history": "Cronologia dei file",
"history_version": "Versioni cronologia",
"back_to_viewer": "Torma alla vista",
"link_title": "Link al titolo",
"local_draft": "Bozza locale",
"use_draft": "Usa bozza",
"delete_draft": "Rimuovi Bozza",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "Hai una bozza non salvata. La vuoi utilizzare?",
"local_draft_saved": "Bozza salvata in locale",
"new_draft": "Nuova Bozza",
"view_draft": "Bozza",
"publish": "Pubblica",
"this_file_has_a_draft": "Questo file è una bozza",
"delete": "Elimina",
"comments": "Commenti",
"add_a_comment": "Aggiungi un commento...",
"no_comment_yet": "Ancora nessun commento.",
"Bold": "Grassetto",
"Italic": "Corsivo",
"Inline_code": "Codice",
"Header_one": "Titolo 1",
"Header_two": "Titolo 2",
"Header_three": "Titolo 3",
"Header_four": "Titolo 4",
"Header_five": "Intestazione 5",
"Header_six": "Intestazione 6",
"Paragraph": "Paragrafo",
"Quote": "Citazione",
"Ordered_list": "Lista ordinata",
"Unordered_list": "Lista non ordinata",
"Check_list_item": "Controlla la voce dell'elenco",
"Insert_image": "Inserisci Immagine",
"Insert_formula": "Insert Formula",
"Formula": "Formula",
"Insert_file": "Insert File",
"Code": "Codice in linea",
"Code_block": "Codice",
"Insert_link": "Inserisci Collegamento",
"Insert_table": "Inserisci tabella",
"Save": "Salvare",
"More": "Altro",
"Invalid_url": "URL non valida",
"Link_address": "Indirizzo collegamento",
"Image_address": "Indirizzo Immagine",
"Submit": "Invia",
"Cancel": "Annulla",
"Switch_to_plain_text_editor": "Passa all'Editor di testo semplice",
"Switch_to_rich_text_editor": "Passa all'Editor di testo formattato",
"Switch_to_viewer": "Passa alla vista di tipo Markdown",
"Help": "Aiuto",
"Remove_table": "Rimuovere Tabella",
"Column": "Colonna",
"Row": "Riga",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Insert row",
"Insert_column": "Insert column",
"Set_align": "Imposta allineamento",
"Left": "Sinistra",
"Center": "Centrato",
"Right": "Destra",
"File_saved": "File salvato.",
"File_failed_to_save": "Errore salvataggio file.",
"Star": "Aggiungi asterisco",
"Unstar": "Rimozione asterisco",
"Back_to_parent_directory": "Torna alla cartella precedente",
"Edit": "Modifica",
"Copy": "Copia",
"Copied": "Copiato",
"Internal_link": "Collegamento interno",
"Copy_internal_link": "Il collegamento interno è stato copiato negli appunti",
"Internal_link_desc": "Un collegamento interno è un collegamento a un file o una cartella a cui gli utenti possono accedere con autorizzazione di lettura al file o alla cartella.",
"Share": "Condividi",
"Share_link": "Condividi Collegamento",
"Generate": "Generare",
"Add_password_protection": "Aggiungi la protezione password",
"Password": "Password",
"At_least_8_characters": "almeno 8 caratteri",
"Password_again": "Ridigita password",
"Add_auto_expiration": "Aggiungi la scadenza automatica",
"Days": "giorni",
"Please_enter_password": "Per favore, inserisci la password",
"Greater_than_or_equal_to": "Maggiore o uguale a ",
"Less_than_or_equal_to": "Minore o uguale a",
"Set_permission": "Imposta permessi",
"Preview_and_download": "Anteprima e download",
"Preview_only": "Solo Anteprima",
"Please_enter_valid_days": "Si prega di inserire giorni validi",
"Please_enter_a_non-negative_integer": "Prego inserire un intero non negativo",
"Please_enter_days": "Prego inserire i giorni",
"Password_is_too_short": "La password è troppo corta",
"Passwords_do_not_match": "Le password non corrispondono",
"Return_to_wiki_page": "Torna alla pagina Wiki",
"Insert_network_image": "Inserisci immagine di rete",
"Upload_local_image": "Inserisci immagine locale",
"Add_link": "Aggiungi collegamento",
"File_history": "Cronologia dei file",
"History_version": "Versioni cronologia",
"Back_to_viewer": "Torma alla vista",
"Link_title": "Link al titolo",
"Local_draft": "Bozza locale",
"Use_draft": "Usa bozza",
"Delete_draft": "Rimuovi Bozza",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "Hai una bozza non salvata. La vuoi utilizzare?",
"Local_draft_saved": "Bozza salvata in locale",
"New_draft": "Nuova Bozza",
"View_draft": "Bozza",
"Publish": "Pubblica",
"This_file_has_a_draft": "Questo file è una bozza",
"Delete": "Elimina",
"Comments": "Commenti",
"Add_a_comment": "Aggiungi un commento...",
"No_comment_yet": "Ancora nessun commento.",
"Mark_as_Resolved": "Mark as Resolved",
"ask_for_review": "Richiedi una revisione",
"review_already_exists": "Revisione già esistente",
"view_review": "Visualizza revisione",
"there_is_an_associated_review_with_this_file": "C'è una recensione associata con questo file.",
"start_review": "Inizia Revisione",
"this_file_is_in_draft_stage": "Questo file è in fase di bozza.",
"this_file_is_in_review_stage": "Questo file è in fase di revisione.",
"this_file_has_been_updated": "Questo file è stato aggiornato.",
"refresh": "Aggiornare",
"related_files": "file correlati",
"related_file": "file correlato",
"no_tags": "Nessun tag",
"Ask_for_review": "Richiedi una revisione",
"Review_already_exists": "Revisione già esistente",
"View_review": "Visualizza revisione",
"There_is_an_associated_review_with_this_file": "C'è una recensione associata con questo file.",
"Start_review": "Inizia Revisione",
"This_file_is_in_draft_stage": "Questo file è in fase di bozza.",
"This_file_is_in_review_stage": "Questo file è in fase di revisione.",
"This_file_has_been_updated": "Questo file è stato aggiornato.",
"Refresh": "Aggiornare",
"Related_files": "file correlati",
"Related_file": "file correlato",
"No_tags": "Nessun tag",
"Date": "Data",
"Participants": "Participants",
"Meeting_note": "Meeting note",
"Chooser_document_type": "Chooser document type",
"Empty": "Vuoto",
"no_related_files": "Nessun file correlato",
"no_out_line": "No outline",
"No_related_files": "Nessun file correlato",
"No_out_line": "No outline",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Editing files in this browser can lead to slight display problems.",
"no_document_improvement_suggestion": "No document improvement suggestion",
"No_document_improvement_suggestion": "No document improvement suggestion",
"Hide_side_panel": "Hide side panel",
"Show_side_panel": "Show side panel",
"Show_resolved_comments": "Mostra commenti risolti",
@@ -131,25 +131,16 @@
"Insert_library_image": "Insert library image",
"Size": "Dimensione",
"Location": "Posizione",
"Last_Update": "Ultimo aggiornamento",
"Last_update": "Last update",
"Tags": "Tag",
"Related_Files": "File correlati",
"Add_participants": "Add participants",
"markdownLint": {
"missing_h1": {
"description": "There is no h1 in the document",
"issue" : "Missing h1"
},
"heading_end_with_colon": {
"description": "Trailing punctuation in heading should not be a colon",
"issue": "Heading ends width colon"
},
"heading_increase_irregular": {
"description": "Heading levels should only increment by one level at a time",
"issue": "Heading level issue"
}
},
"Clear_format": "Clear format",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Shortcut help",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Tasti rapidi",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Inserisci un elemento figlio sotto questo elemento",
"Increase_depth": "Aumenta la profondità"
}
}, {
},
{
"shortcutType": "Scorciatoie principali",
"shortcutData": {
"Heading_1": "Titolo 1",
@@ -172,7 +164,8 @@
"Heading_5": "Intestazione 5",
"Heading_6": "Intestazione 6"
}
}, {
},
{
"shortcutType": "Scorciatoie di codice",
"shortcutData": {
"Make_code_block": "Crea un blocco di codice",
@@ -180,37 +173,43 @@
"Escape_code_block": "Codice di escape",
"Insert_indent": "Inserisci indentazione"
}
}, {
},
{
"shortcutType": "Blocco scorciatoie di citazione",
"shortcutData": {
"Make_Block_quote": "Crea blocco citazioni",
"Escape_Block_quote": "Escape Blocco Codice"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Scorciatoie Tabella",
"shortcutData": {
"Insert_Table_Row": "Inserisci riga nella tabella",
"Insert_table_row": "Insert table tow",
"Escape_table": "Escape tabella"
}
}, {
},
{
"shortcutType": "Formula shortcuts",
"shortcutData": {
"Insert_Formula": "Insert Formula"
"Insert_formula": "Insert formula"
}
}, {
},
{
"shortcutType": "Scorciatoie in linea",
"shortcutData": {
"Bold": "Grassetto",
"Italic": "Corsivo",
"Italic_Bold": "Corsivo Grassetto",
"Italic_bold": "Italic bold",
"Inline_code": "Codice in linea"
}
}, {
},
{
"shortcutType": "Salva scorciatoie",
"shortcutData": {
"Save_file": "Salva file"
}
}, {
},
{
"shortcutType": "Scorciatoie per le immagini",
"shortcutData": {
"Paste_screen_shot": "Incolla la schermata",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,126 +1,126 @@
{
"bold": "Полужирный",
"italic": "Курсив",
"inline_code": "Код",
"header_one": "Заголовок 1",
"header_two": "Заголовок 2",
"header_three": "Заголовок 3",
"header_four": "Заголовок 4",
"header_five": "Заголовок 5",
"header_six": "Заголовок 6",
"paragraph": "Параграф",
"quote": "Цитата",
"ordered_list": "Нумерованный список",
"unordered_list": "Маркированный список",
"check_list_item": "Проверка элемента списка",
"insert_image": "Вставить изображение",
"insert_formula": "Вставить формулу",
"formula": "Формула",
"insert_file": "Вставить файл",
"code": "Встроенный код",
"code_block": "Блок кода",
"insert_link": "Вставить ссылку",
"insert_table": "Вставить таблицу",
"save": "Сохранить",
"more": "Подробнее",
"invalid_url": "Недопустимый URL",
"link_address": "Адрес ссылки",
"image_address": "Адрес изображения",
"submit": "Отправить",
"cancel": "Отменить",
"switch_to_plain_text_editor": "Переключиться на обычный текстовый редактор",
"switch_to_rich_text_editor": "Переключиться на визуальный редактор",
"switch_to_viewer": "Переключиться на просмотр Markdown",
"help": "Помощь",
"remove_table": "Удалить таблицу",
"column": "Столбец",
"row": "Строка",
"Insert_Row_Before": "Вставить строку перед",
"Insert_Row_After": "Вставить строку после",
"Insert_Column_Before": "Вставить столбец перед",
"Insert_Column_After": "Вставить столбец после",
"Remove_Row": "Удалить строку",
"Remove_Column": "Удалить столбец",
"Insert_Row": "Вставить строку",
"Insert_Column": "Вставить столбец",
"set_align": "Установить выравнивание",
"left": "Слева",
"center": "По центру",
"right": "Справа",
"file_saved": "Файл сохранён.",
"file_failed_to_save": "Не удалось сохранить файл.",
"star": "Добавить пометку",
"unstar": "Удалить пометку",
"back_to_parent_directory":"Вернуться в родительский каталог",
"edit": "Редактировать",
"copy": "Копировать",
"copied": "Скопировано",
"internal_link": "Внутренняя ссылка",
"copy_internal_link": "Внутренняя ссылка скопирована в буфер обмена",
"internal_link_desc": "Внутренняя ссылка - это ссылка на файл или папку, к которым могут обращаться пользователи с правами на чтение файла или папки.",
"share": "Общий доступ",
"share_link": "Общедоступная ссылка",
"generate": "Создать",
"add_password_protection": "Защитить паролем",
"password": "Пароль",
"at_least_8_characters": "не менее 8 символов",
"password_again": "Подтвердите пароль",
"add_auto_expiration": "Добавить автоистечение срока действия",
"days": "дней",
"please_enter_password": "Пожалуйста, введите пароль",
"greater_than_or_equal_to": "Больше или равно",
"less_than_or_equal_to": "Меньше или равно",
"set_permission": "Установить разрешения",
"preview_and_download": "Предпросмотр и скачивание",
"preview_only": "Только предпросмотр",
"please_enter_valid_days": "Пожалуйста, введите действительные дни",
"please_enter_a_non-negative_integer": "Пожалуйста, введите неотрицательное целое число",
"please_enter_days": "Пожалуйста, введите дни",
"password_is_too_short": "Пароль слишком короткий",
"passwords_do_not_match": "Пароли не совпадают",
"return_to_wiki_page": "Вернуться на страницу Вики",
"insert_network_image": "Вставить удалённое изображение",
"upload_local_image": "Загрузить локальное изображение",
"add_link": "Добавить ссылку",
"file_history": "История файла",
"history_version": "История версий",
"back_to_viewer": "Вернуться к просмотру",
"link_title": "Название ссылки",
"local_draft": "Локальный черновик",
"use_draft": "Использовать черновик",
"delete_draft": "Удалить черновик",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "У вас есть несохранённый черновик. Хотите использовать его?",
"local_draft_saved": "Локальный черновик сохранён",
"new_draft": "Новый черновик",
"view_draft": "Просмотр черновика",
"publish": "Опубликовать",
"this_file_has_a_draft": "Этот файл имеет черновик.",
"delete": "Удалить",
"comments": "Комментарии",
"add_a_comment": "Добавить комментарий...",
"no_comment_yet": "Комментариев пока нет.",
"Bold": "Полужирный",
"Italic": "Курсив",
"Inline_code": "Код",
"Header_one": "Заголовок 1",
"Header_two": "Заголовок 2",
"Header_three": "Заголовок 3",
"Header_four": "Заголовок 4",
"Header_five": "Заголовок 5",
"Header_six": "Заголовок 6",
"Paragraph": "Параграф",
"Quote": "Цитата",
"Ordered_list": "Нумерованный список",
"Unordered_list": "Маркированный список",
"Check_list_item": "Проверка элемента списка",
"Insert_image": "Вставить изображение",
"Insert_formula": "Вставить формулу",
"Formula": "Формула",
"Insert_file": "Вставить файл",
"Code": "Встроенный код",
"Code_block": "Блок кода",
"Insert_link": "Вставить ссылку",
"Insert_table": "Вставить таблицу",
"Save": "Сохранить",
"More": "Подробнее",
"Invalid_url": "Недопустимый URL",
"Link_address": "Адрес ссылки",
"Image_address": "Адрес изображения",
"Submit": "Отправить",
"Cancel": "Отменить",
"Switch_to_plain_text_editor": "Переключиться на обычный текстовый редактор",
"Switch_to_rich_text_editor": "Переключиться на визуальный редактор",
"Switch_to_viewer": "Переключиться на просмотр Markdown",
"Help": "Помощь",
"Remove_table": "Удалить таблицу",
"Column": "Столбец",
"Row": "Строка",
"Insert_row_before": "Insert row before",
"Insert_row_after": "Insert row after",
"Insert_column_before": "Insert column before",
"Insert_column_after": "Insert column after",
"Remove_row": "Remove row",
"Remove_column": "Remove column",
"Insert_row": "Вставить строку",
"Insert_column": "Вставить столбец",
"Set_align": "Установить выравнивание",
"Left": "Слева",
"Center": "По центру",
"Right": "Справа",
"File_saved": "Файл сохранён.",
"File_failed_to_save": "Не удалось сохранить файл.",
"Star": "Добавить пометку",
"Unstar": "Удалить пометку",
"Back_to_parent_directory": "Вернуться в родительский каталог",
"Edit": "Редактировать",
"Copy": "Копировать",
"Copied": "Скопировано",
"Internal_link": "Внутренняя ссылка",
"Copy_internal_link": "Внутренняя ссылка скопирована в буфер обмена",
"Internal_link_desc": "Внутренняя ссылка - это ссылка на файл или папку, к которым могут обращаться пользователи с правами на чтение файла или папки.",
"Share": "Общий доступ",
"Share_link": "Общедоступная ссылка",
"Generate": "Создать",
"Add_password_protection": "Защитить паролем",
"Password": "Пароль",
"At_least_8_characters": "не менее 8 символов",
"Password_again": "Подтвердите пароль",
"Add_auto_expiration": "Добавить автоистечение срока действия",
"Days": "дней",
"Please_enter_password": "Пожалуйста, введите пароль",
"Greater_than_or_equal_to": "Больше или равно",
"Less_than_or_equal_to": "Меньше или равно",
"Set_permission": "Установить разрешения",
"Preview_and_download": "Предпросмотр и скачивание",
"Preview_only": "Только предпросмотр",
"Please_enter_valid_days": "Пожалуйста, введите действительные дни",
"Please_enter_a_non-negative_integer": "Пожалуйста, введите неотрицательное целое число",
"Please_enter_days": "Пожалуйста, введите дни",
"Password_is_too_short": "Пароль слишком короткий",
"Passwords_do_not_match": "Пароли не совпадают",
"Return_to_wiki_page": "Вернуться на страницу Вики",
"Insert_network_image": "Вставить удалённое изображение",
"Upload_local_image": "Загрузить локальное изображение",
"Add_link": "Добавить ссылку",
"File_history": "История файла",
"History_version": "История версий",
"Back_to_viewer": "Вернуться к просмотру",
"Link_title": "Название ссылки",
"Local_draft": "Локальный черновик",
"Use_draft": "Использовать черновик",
"Delete_draft": "Удалить черновик",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "У вас есть несохранённый черновик. Хотите использовать его?",
"Local_draft_saved": "Локальный черновик сохранён",
"New_draft": "Новый черновик",
"View_draft": "Просмотр черновика",
"Publish": "Опубликовать",
"This_file_has_a_draft": "Этот файл имеет черновик.",
"Delete": "Удалить",
"Comments": "Комментарии",
"Add_a_comment": "Добавить комментарий...",
"No_comment_yet": "Комментариев пока нет.",
"Mark_as_Resolved": "Отметить как решённый",
"ask_for_review": "Спросить отзыв",
"review_already_exists": "Отзыв уже существует",
"view_review": "Просмотр отзыва",
"there_is_an_associated_review_with_this_file": "Есть связанный отзыв с этим файлом.",
"start_review": "Начать отзыв",
"this_file_is_in_draft_stage": "Этот файл находится в стадии черновика.",
"this_file_is_in_review_stage": "Этот файл находится на стадии проверки.",
"this_file_has_been_updated": "Этот файл был обновлён.",
"refresh": "Обновить",
"related_files": "связанные файлы",
"related_file": "связанный файл",
"no_tags": "Нет меток",
"Ask_for_review": "Спросить отзыв",
"Review_already_exists": "Отзыв уже существует",
"View_review": "Просмотр отзыва",
"There_is_an_associated_review_with_this_file": "Есть связанный отзыв с этим файлом.",
"Start_review": "Начать отзыв",
"This_file_is_in_draft_stage": "Этот файл находится в стадии черновика.",
"This_file_is_in_review_stage": "Этот файл находится на стадии проверки.",
"This_file_has_been_updated": "Этот файл был обновлён.",
"Refresh": "Обновить",
"Related_files": "связанные файлы",
"Related_file": "связанный файл",
"No_tags": "Нет меток",
"Date": "Дата",
"Participants": "Участники",
"Meeting_note": "Заметка о встрече",
"Chooser_document_type": "Выбор типа документа",
"Empty": "Пусто",
"no_related_files": "Нет связанных файлов",
"no_out_line": "Нет контура",
"No_related_files": "Нет связанных файлов",
"No_out_line": "Нет контура",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "Изменение файлов в этом браузере может привести к небольшим проблемам с отображением.",
"no_document_improvement_suggestion": "Нет предложений по улучшению документа",
"No_document_improvement_suggestion": "Нет предложений по улучшению документа",
"Hide_side_panel": "Скрыть боковую панель",
"Show_side_panel": "Показать боковую панель",
"Show_resolved_comments": "Показать разрешённые комментарии",
@@ -131,25 +131,16 @@
"Insert_library_image": "Вставить изображение библиотеки",
"Size": "Размер",
"Location": "Местонахождение",
"Last_Update": "Последнее обновление",
"Last_update": "Последнее обновление",
"Tags": "Метки",
"Related_Files": "Связанные файлы",
"Add_participants": "Добавить участников",
"markdownLint": {
"missing_h1": {
"description": "В документе нет h1",
"issue" : "Отсутствует h1"
},
"heading_end_with_colon": {
"description": "Завершающая пунктуация в заголовке не должна быть двоеточием",
"issue": "Заголовок заканчивается двоеточием"
},
"heading_increase_irregular": {
"description": "Уровни заголовков должны увеличиваться только на один уровень за раз",
"issue": "Проблема уровня заголовка"
}
},
"Clear_format": "Очистить формат",
"Image_address_invalid": "Image address invalid",
"Shortcut_help": "Справка по горячим клавишам",
"Link_address_required": "Link address required",
"Link_address_invalid": "Link address invalid",
"Link_title_required": "Link title required",
"Blank_title_not_allowed": "Blank title not allowed",
"userHelp": {
"title": "Горячие клавиши",
"userHelpData": [
@@ -162,7 +153,8 @@
"Insert_child_in_item": "Вставить дочерний в элемент",
"Increase_depth": "Увеличить глубину"
}
}, {
},
{
"shortcutType": "Горячие клавиши для заголовка",
"shortcutData": {
"Heading_1": "Заголовок 1",
@@ -172,7 +164,8 @@
"Heading_5": "Заголовок 5",
"Heading_6": "Заголовок 6"
}
}, {
},
{
"shortcutType": "Горячие клавиши для кода",
"shortcutData": {
"Make_code_block": "Создать блок кода",
@@ -180,37 +173,43 @@
"Escape_code_block": "Выделить блок кода",
"Insert_indent": "Вставить отступ"
}
}, {
},
{
"shortcutType": "Горячие клавиши для блока цитаты",
"shortcutData": {
"Make_Block_quote": "Создать блок цитаты",
"Escape_Block_quote": "Выделить блок цитаты"
"Make_block_quote": "Make block quote",
"Escape_block_quote": "Escape block quote"
}
}, {
},
{
"shortcutType": "Горячие клавиши для таблицы",
"shortcutData": {
"Insert_Table_Row": "Вставить строку таблицы",
"Insert_table_row": "Insert table tow",
"Escape_table": "Выделить таблицу"
}
}, {
},
{
"shortcutType": "Горячие клавиши для формул",
"shortcutData": {
"Insert_Formula": "Вставить формулу"
"Insert_formula": "Вставить формулу"
}
}, {
},
{
"shortcutType": "Встроенные горячие клавиши",
"shortcutData": {
"Bold": "Полужирный",
"Italic": "Курсив",
"Italic_Bold": "Курсив полужирный",
"Italic_bold": "Italic bold",
"Inline_code": "Встроенный код"
}
}, {
},
{
"shortcutType": "Сохранить горячие клавиши",
"shortcutData": {
"Save_file": "Сохранить файл"
}
}, {
},
{
"shortcutType": "Горячие клавиши для изображений",
"shortcutData": {
"Paste_screen_shot": "Вставить скриншот",
@@ -218,5 +217,7 @@
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -1,121 +1,124 @@
{
"bold": "粗体",
"italic": "斜体",
"inline_code": "代码",
"header_one": "一级标题",
"header_two": "二级标题",
"header_three": "三级标题",
"header_four": "四级标题",
"header_five": "五级标题",
"header_six": "六级标题",
"paragraph": "段落",
"quote": "引用",
"ordered_list": "有序列表",
"unordered_list": "无序列表",
"check_list_item": "任务列表",
"insert_image": "插入图片",
"insert_formula": "插入公式",
"formula": "公式",
"insert_file": "插入文件",
"code": "行内代码",
"code_block": "代码块",
"insert_link": "添加链接",
"insert_table": "添加表格",
"save": "保存",
"more": "更多",
"invalid_url": "无效链接",
"link_address": "链接地址",
"image_address": "图片地址",
"submit": "提交",
"cancel": "取消",
"switch_to_plain_text_editor": "切换至普通文本编辑器",
"switch_to_rich_text_editor": "切换至富文本编辑器",
"switch_to_viewer": "切换到只读模式",
"help": "帮助",
"remove_table": "删除表格",
"Insert_Row_Before": "上方插入行",
"Insert_Row_After": "下方插入行",
"Insert_Column_Before": "左边插入",
"Insert_Column_After": "右边插入",
"Remove_Row": "删除当前行",
"Remove_Column": "删除当前列",
"Insert_Row": "插入行",
"Insert_Column": "插入列",
"column": "",
"row": "",
"set_align": "对齐方式",
"left": "左对齐",
"center": "居中",
"right": "右对齐",
"file_saved": "保存文件成功",
"file_failed_to_save": "保存文件失败",
"star": "添加星标",
"unstar": "移除星标",
"back_to_parent_directory":"返回上级目录",
"edit":"编辑",
"copy": "复制",
"copied": "已复制",
"internal_link": "内部链接",
"copy_internal_link": "内部链接已复制到剪贴板",
"internal_link_desc": "内部链接是指向文件或目录的链接,只有对该文件或目录有访问权限的人可以访问。",
"share": "共享",
"share_link": "共享链接",
"generate": "生成链接",
"add_password_protection": "增加密码保护",
"password": "密码",
"at_least_8_characters": "至少8个字符",
"password_again": "请再次输入密码",
"add_auto_expiration": "增加自动过期",
"days": "天",
"please_enter_password": "请输入密码",
"greater_than_or_equal_to": "大于或等于",
"less_than_or_equal_to": "小于或等于",
"set_permission": "设置权限",
"preview_and_download": "预览与下载",
"preview_only": "仅查看",
"please_enter_valid_days": "请输入有效的天数",
"please_enter_a_non-negative_integer": "请输入一个非负整数",
"please_enter_days": "请输入天数",
"password_is_too_short": "密码长度太短",
"passwords_do_not_match": "两次输入的密码不一致",
"return_to_wiki_page": "返回维基页面",
"insert_network_image": "插入网络图片",
"upload_local_image": "上传本地图片",
"add_link": "加入链接",
"file_history": "文件历史",
"history_version": "历史版本",
"back_to_viewer": "返回查看页面",
"link_title": "链接标题",
"local_draft": "本地草稿",
"use_draft": "使用草稿",
"delete_draft": "删除草稿",
"you_have_an_unsaved_draft_do_you_like_to_use_it": "有未保存的草稿,使用草稿吗?",
"local_draft_saved": "本地草稿已保存",
"new_draft": "创建草稿",
"view_draft": "查看草稿",
"publish": "发布",
"this_file_has_a_draft": "这个文件有一个草稿.",
"delete": "删除",
"comments": "评论",
"add_a_comment": "增加评论",
"no_comment_yet": "还没有评论",
"Bold": "粗体",
"Italic": "斜体",
"Inline_code": "代码",
"Header_one": "一级标题",
"Header_two": "二级标题",
"Header_three": "三级标题",
"Header_four": "四级标题",
"Header_five": "五级标题",
"Header_six": "六级标题",
"Paragraph": "段落",
"Quote": "引用",
"Ordered_list": "有序列表",
"Unordered_list": "无序列表",
"Check_list_item": "任务列表",
"Insert_image": "插入图片",
"Insert_formula": "插入公式",
"Formula": "公式",
"Insert_file": "插入文件",
"Code": "行内代码",
"Code_block": "代码块",
"Insert_link": "添加链接",
"Insert_table": "添加表格",
"Save": "保存",
"More": "更多",
"Invalid_url": "无效链接",
"Link_address": "链接地址",
"Image_address": "图片地址",
"Submit": "提交",
"Cancel": "取消",
"Switch_to_plain_text_editor": "切换至普通文本编辑器",
"Switch_to_rich_text_editor": "切换至富文本编辑器",
"Switch_to_viewer": "切换到只读模式",
"Help": "帮助",
"Remove_table": "删除表格",
"Column": "",
"Row": "行",
"Insert_row_before": "上方插入",
"Insert_row_after": "下方插入",
"Insert_column_before": "左边插入列",
"Insert_column_after": "右边插入列",
"Remove_row": "删除当前行",
"Remove_column": "删除当前列",
"Insert_row": "插入行",
"Insert_column": "插入列",
"Set_align": "对齐方式",
"Left": "左对齐",
"Center": "居中",
"Right": "右对齐",
"File_saved": "保存文件成功",
"File_failed_to_save": "保存文件失败",
"Star": "添加星标",
"Unstar": "移除星标",
"Back_to_parent_directory": "返回上级目录",
"Edit": "编辑",
"Copy": "复制",
"Copied": "已复制",
"Internal_link": "内部链接",
"Copy_internal_link": "内部链接已复制到剪贴板",
"Internal_link_desc": "内部链接是指向文件或目录的链接,只有对该文件或目录有访问权限的人可以访问。",
"Share": "共享",
"Share_link": "共享链接",
"Generate": "生成链接",
"Add_password_protection": "增加密码保护",
"Password": "密码",
"At_least_8_characters": "至少8个字符",
"Password_again": "请再次输入密码",
"Add_auto_expiration": "增加自动过期",
"Days": "天",
"Please_enter_password": "请输入密码",
"Greater_than_or_equal_to": "大于或等于",
"Less_than_or_equal_to": "小于或等于",
"Set_permission": "设置权限",
"Preview_and_download": "预览与下载",
"Preview_only": "仅查看",
"Please_enter_valid_days": "请输入有效的天数",
"Please_enter_a_non-negative_integer": "请输入一个非负整数",
"Please_enter_days": "请输入天数",
"Password_is_too_short": "密码长度太短",
"Passwords_do_not_match": "两次输入的密码不一致",
"Return_to_wiki_page": "返回维基页面",
"Insert_network_image": "插入网络图片",
"Upload_local_image": "上传本地图片",
"Add_link": "加入链接",
"File_history": "文件历史",
"History_version": "历史版本",
"Back_to_viewer": "返回查看页面",
"Link_title": "链接标题",
"Local_draft": "本地草稿",
"Use_draft": "使用草稿",
"Delete_draft": "删除草稿",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "有未保存的草稿,使用草稿吗?",
"Local_draft_saved": "本地草稿已保存",
"New_draft": "创建草稿",
"View_draft": "查看草稿",
"Publish": "发布",
"This_file_has_a_draft": "这个文件有一个草稿.",
"Delete": "删除",
"Comments": "评论",
"Add_a_comment": "增加评论",
"No_comment_yet": "还没有评论",
"Mark_as_Resolved": "标记为已解决",
"ask_for_review": "发起评审",
"review_already_exists": "评审已存在",
"view_review": "查看评审",
"there_is_an_associated_review_with_this_file": "有一个与此文件相关联的评审。",
"start_review": "开始评审",
"this_file_is_in_draft_stage": "该文件处于草稿阶段。",
"this_file_is_in_review_stage": "该文件处于评审阶段。",
"this_file_has_been_updated": "这个文件已被修改。",
"refresh": "刷新",
"related_files": "相关文件",
"related_file": "相关文件",
"no_tags": "没有标签",
"date": "日期",
"participants": "参与",
"no_related_files": "没有相关文件",
"no_out_line": "没有大纲",
"Ask_for_review": "发起评审",
"Review_already_exists": "评审已存在",
"Ciew_review": "查看评审",
"There_is_an_associated_review_with_this_file": "有一个与此文件相关联的评审。",
"Start_review": "开始评审",
"This_file_is_in_draft_stage": "该文件处于草稿阶段。",
"This_file_is_in_review_stage": "该文件处于评审阶段。",
"This_file_has_been_updated": "这个文件已被修改。",
"Refresh": "刷新",
"Related_files": "相关文件",
"Related_file": "相关文件",
"No_tags": "没有标签",
"Date": "日期",
"Participants": "参与",
"Meeting_note": "会议记录",
"Chooser_document_type": "选择文档类型",
"Empty": "空",
"No_related_files": "没有相关文件",
"No_out_line": "没有大纲",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "在此浏览器中,编辑文件可能导致轻微的显示问题。",
"no_document_improvement_suggestion": "没有文档改进建议",
"Hide_side_panel": "隐藏侧旁栏",
@@ -128,24 +131,10 @@
"Insert_library_image": "插入资料库图片",
"Size": "大小",
"Location": "位置",
"Last_Update": "更新时间",
"Last_update": "更新时间",
"Tags": "标签",
"Related_Files": "相关文档",
"Add_participants": "增加文件参与人",
"markdownLint": {
"missing_h1": {
"description": "文档缺少一级标题",
"issue" : "缺少一级标题"
},
"heading_end_with_colon": {
"description": "标题末尾的标点符号不应该是冒号",
"issue": "标题末尾是冒号"
},
"heading_increase_irregular": {
"description": "标题级别一次只能增加一级",
"issue": "标题级别不规范"
}
},
"Shortcut_help": "快捷键帮助",
"userHelp": {
"title": "键盘快捷键",
@@ -180,40 +169,42 @@
}, {
"shortcutType": "引用快捷键",
"shortcutData": {
"Make_Block_quote": "生成引用",
"Escape_Block_quote": "退出引用"
"Make_block_quote": "生成引用",
"Escape_block_quote": "退出引用"
}
}, {
"shortcutType": "表格快捷键",
"shortcutData": {
"Insert_Table_Row": "插入行",
"Insert_table_row": "插入行",
"Escape_table": "退出表格"
}
}, {
"shortcutType": "公式快捷键",
"shortcutData": {
"Insert_Formula": "插入公式"
"Insert_formula": "插入公式"
}
}, {
"shortcutType":"行级操作",
"shortcutType": "行内快捷键",
"shortcutData": {
"Bold": "粗体",
"Italic": "斜体",
"Italic_Bold": "斜体粗",
"Italic_bold": "斜体粗",
"Inline_code": "行内代码"
}
}, {
"shortcutType": "文件保存",
"shortcutType": "保存快捷键",
"shortcutData": {
"Save_file": "保存文件"
}
}, {
"shortcutType": "图片操作",
"shortcutType": "图片快捷键",
"shortcutData": {
"Paste_screen_shot": "上传截图",
"Drag_image_from_anywhere_to_upload_it": "拖拽任意图片上传"
"Paste_screen_shot": "粘贴屏幕截图",
"Drag_image_from_anywhere_to_upload_it": "从任意地方拖动图像以上传"
}
}
]
}
},
"Select_field": "Select field",
"Font_style": "Font style"
}

View File

@@ -0,0 +1,210 @@
{
"Bold": "粗体",
"Italic": "斜体",
"Inline_code": "代码",
"Header_one": "一级标题",
"Header_two": "二级标题",
"Header_three": "三级标题",
"Header_four": "四级标题",
"Header_five": "五级标题",
"Header_six": "六级标题",
"Paragraph": "段落",
"Quote": "引用",
"Ordered_list": "有序列表",
"Unordered_list": "无序列表",
"Check_list_item": "任务列表",
"Insert_image": "插入图片",
"Insert_formula": "插入公式",
"Formula": "公式",
"Insert_file": "插入文件",
"Code": "行内代码",
"Code_block": "代码块",
"Insert_link": "添加链接",
"Insert_table": "添加表格",
"Save": "保存",
"More": "更多",
"Invalid_url": "无效链接",
"Link_address": "链接地址",
"Image_address": "图片地址",
"Submit": "提交",
"Cancel": "取消",
"Switch_to_plain_text_editor": "切换至普通文本编辑器",
"Switch_to_rich_text_editor": "切换至富文本编辑器",
"Switch_to_viewer": "切换到只读模式",
"Help": "帮助",
"Remove_table": "删除表格",
"Column": "列",
"Row": "行",
"Insert_row_before": "上方插入行",
"Insert_row_after": "下方插入行",
"Insert_column_before": "左边插入列",
"Insert_column_after": "右边插入列",
"Remove_row": "删除当前行",
"Remove_column": "删除当前列",
"Insert_row": "插入行",
"Insert_column": "插入列",
"Set_align": "对齐方式",
"Left": "左对齐",
"Center": "居中",
"Right": "右对齐",
"File_saved": "保存文件成功",
"File_failed_to_save": "保存文件失败",
"Star": "添加星标",
"Unstar": "移除星标",
"Back_to_parent_directory": "返回上级目录",
"Edit": "编辑",
"Copy": "复制",
"Copied": "已复制",
"Internal_link": "内部链接",
"Copy_internal_link": "内部链接已复制到剪贴板",
"Internal_link_desc": "内部链接是指向文件或目录的链接,只有对该文件或目录有访问权限的人可以访问。",
"Share": "共享",
"Share_link": "共享链接",
"Generate": "生成链接",
"Add_password_protection": "增加密码保护",
"Password": "密码",
"At_least_8_characters": "至少8个字符",
"Password_again": "请再次输入密码",
"Add_auto_expiration": "增加自动过期",
"Days": "天",
"Please_enter_password": "请输入密码",
"Greater_than_or_equal_to": "大于或等于",
"Less_than_or_equal_to": "小于或等于",
"Set_permission": "设置权限",
"Preview_and_download": "预览与下载",
"Preview_only": "仅查看",
"Please_enter_valid_days": "请输入有效的天数",
"Please_enter_a_non-negative_integer": "请输入一个非负整数",
"Please_enter_days": "请输入天数",
"Password_is_too_short": "密码长度太短",
"Passwords_do_not_match": "两次输入的密码不一致",
"Return_to_wiki_page": "返回维基页面",
"Insert_network_image": "插入网络图片",
"Upload_local_image": "上传本地图片",
"Add_link": "加入链接",
"File_history": "文件历史",
"History_version": "历史版本",
"Back_to_viewer": "返回查看页面",
"Link_title": "链接标题",
"Local_draft": "本地草稿",
"Use_draft": "使用草稿",
"Delete_draft": "删除草稿",
"You_have_an_unsaved_draft_do_you_like_to_use_it": "有未保存的草稿,使用草稿吗?",
"Local_draft_saved": "本地草稿已保存",
"New_draft": "创建草稿",
"View_draft": "查看草稿",
"Publish": "发布",
"This_file_has_a_draft": "这个文件有一个草稿.",
"Delete": "删除",
"Comments": "评论",
"Add_a_comment": "增加评论",
"No_comment_yet": "还没有评论",
"Mark_as_Resolved": "标记为已解决",
"Ask_for_review": "发起评审",
"Review_already_exists": "评审已存在",
"Ciew_review": "查看评审",
"There_is_an_associated_review_with_this_file": "有一个与此文件相关联的评审。",
"Start_review": "开始评审",
"This_file_is_in_draft_stage": "该文件处于草稿阶段。",
"This_file_is_in_review_stage": "该文件处于评审阶段。",
"This_file_has_been_updated": "这个文件已被修改。",
"Refresh": "刷新",
"Related_files": "相关文件",
"Related_file": "相关文件",
"No_tags": "没有标签",
"Date": "日期",
"Participants": "参与人",
"Meeting_note": "会议记录",
"Chooser_document_type": "选择文档类型",
"Empty": "空",
"No_related_files": "没有相关文件",
"No_out_line": "没有大纲",
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "在此浏览器中,编辑文件可能导致轻微的显示问题。",
"no_document_improvement_suggestion": "没有文档改进建议",
"Hide_side_panel": "隐藏侧旁栏",
"Show_side_panel": "显示侧旁栏",
"Show_resolved_comments": "显示已解决的评论",
"Update": "更新",
"Width": "宽度",
"Height": "高度",
"Full_screen": "全屏",
"Insert_library_image": "插入资料库图片",
"Size": "大小",
"Location": "位置",
"Last_update": "更新时间",
"Tags": "标签",
"Related_Files": "相关文档",
"Add_participants": "增加文件参与人",
"Shortcut_help": "快捷键帮助",
"userHelp": {
"title": "键盘快捷键",
"userHelpData": [
{
"shortcutType": "列表快捷键",
"shortcutData": {
"Make_list": "生成列表",
"Make_ordered_list": "生成有序列表",
"Insert_new_item": "插入列表项",
"Insert_child_in_item": "插入新段落",
"Increase_depth": "增加列表项深度"
}
}, {
"shortcutType": "标题快捷键",
"shortcutData": {
"Heading_1": "一级标题",
"Heading_2": "二级标题",
"Heading_3": "三级标题",
"Heading_4": "四级标题",
"Heading_5": "五级标题",
"Heading_6": "六级标题"
}
}, {
"shortcutType": "代码块快捷键",
"shortcutData": {
"Make_code_block": "生成代码块",
"Insert_new_line": "插入行",
"Escape_code_block": "退出代码块",
"Insert_indent": "缩进"
}
}, {
"shortcutType": "引用快捷键",
"shortcutData": {
"Make_block_quote": "生成引用",
"Escape_block_quote": "退出引用"
}
}, {
"shortcutType": "表格快捷键",
"shortcutData": {
"Insert_table_row": "插入行",
"Escape_table": "退出表格"
}
}, {
"shortcutType": "公式快捷键",
"shortcutData": {
"Insert_formula": "插入公式"
}
}, {
"shortcutType": "行内快捷键",
"shortcutData": {
"Bold": "粗体",
"Italic": "斜体",
"Italic_bold": "斜体粗体",
"Inline_code": "行内代码"
}
}, {
"shortcutType": "保存快捷键",
"shortcutData": {
"Save_file": "保存文件"
}
}, {
"shortcutType": "图片快捷键",
"shortcutData": {
"Paste_screen_shot": "粘贴屏幕截图",
"Drag_image_from_anywhere_to_upload_it": "从任意地方拖动图像以上传"
}
}
]
},
"Select_field": "Select field",
"Font_style": "Font style"
}