mirror of https://github.com/mindoc-org/mindoc.git
commit
c4d05d2a25
27
README.md
27
README.md
|
@ -42,7 +42,9 @@ MinDoc 的前身是 [SmartWiki](https://github.com/lifei6671/SmartWiki) 文档
|
|||
对于没有Golang使用经验的用户,可以从 [https://github.com/mindoc-org/mindoc/releases](https://github.com/mindoc-org/mindoc/releases) 这里下载编译完的程序。
|
||||
|
||||
如果有Golang开发经验,建议通过编译安装,要求golang版本不小于1.13(需支持`CGO`和`go mod`)。
|
||||
> 注意: CentOS7上GLibC版本低,需要源码编译, 编译好的二进制文件无法运行。
|
||||
|
||||
## 常规编译
|
||||
```bash
|
||||
# 克隆源码
|
||||
git clone https://github.com/mindoc-org/mindoc.git
|
||||
|
@ -64,6 +66,31 @@ MinDoc 如果使用MySQL储存数据,则编码必须是`utf8mb4_general_ci`。
|
|||
|
||||
**默认程序会自动初始化一个超级管理员用户:admin 密码:123456 。请登录后重新设置密码。**
|
||||
|
||||
## Linux系统中不依赖gLibC的编译方式
|
||||
|
||||
### 安装 musl-gcc
|
||||
```bash
|
||||
wget -c http://www.musl-libc.org/releases/musl-1.2.2.tar.gz
|
||||
tar -xvf musl-1.2.2.tar.gz
|
||||
cd musl-1.2.2
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
### 使用 musl-gcc 编译 mindoc
|
||||
```bash
|
||||
go mod tidy -v
|
||||
export GOARCH=amd64
|
||||
export GOOS=linux
|
||||
# 设置使用musl-gcc
|
||||
export CC=/usr/local/musl/bin/musl-gcc
|
||||
# 设置版本
|
||||
export TRAVIS_TAG=temp-musl-v`date +%y%m%d`
|
||||
go build -o mindoc_linux_musl_amd64 --ldflags="-linkmode external -extldflags '-static' -w -X 'github.com/mindoc-org/mindoc/conf.VERSION=$TRAVIS_TAG' -X 'github.com/mindoc-org/mindoc/conf.BUILD_TIME=`date`' -X 'github.com/mindoc-org/mindoc/conf.GO_VERSION=`go version`'"
|
||||
# 验证
|
||||
./mindoc_linux_amd64 version
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
|
||||
|
|
|
@ -263,6 +263,12 @@ func RegisterFunction() {
|
|||
logs.Error("注册函数 urlfor 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
//读取配置值(未作任何转换)
|
||||
err = web.AddFuncMap("conf", conf.CONF)
|
||||
if err != nil {
|
||||
logs.Error("注册函数 conf 出错 ->", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
err = web.AddFuncMap("date_format", func(t time.Time, format string) string {
|
||||
return t.Local().Format(format)
|
||||
})
|
||||
|
|
|
@ -8,6 +8,7 @@ sessionon = true
|
|||
sessionname = mindoc_id
|
||||
copyrequestbody = true
|
||||
enablexsrf = "${MINDOC_ENABLE_XSRF||false}"
|
||||
enable_iframe = "${MINDOC_ENABLE_IFRAME||false}"
|
||||
|
||||
#系统完整URL(http://doc.iminho.me),如果该项不设置,会从请求头中获取地址。
|
||||
baseurl="${MINDOC_BASE_URL}"
|
||||
|
|
|
@ -152,6 +152,11 @@ func GetEnableExport() bool {
|
|||
return web.AppConfig.DefaultBool("enable_export", true)
|
||||
}
|
||||
|
||||
//是否启用iframe
|
||||
func GetEnableIframe() bool {
|
||||
return web.AppConfig.DefaultBool("enable_iframe", false)
|
||||
}
|
||||
|
||||
//同一项目导出线程的并发数
|
||||
func GetExportProcessNum() int {
|
||||
exportProcessNum := web.AppConfig.DefaultInt("export_process_num", 1)
|
||||
|
@ -208,6 +213,15 @@ func IsAllowUploadFileExt(ext string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
//读取配置文件值
|
||||
func CONF(key string, value ...string) string {
|
||||
defaultValue := ""
|
||||
if len(value) > 0 {
|
||||
defaultValue = value[0]
|
||||
}
|
||||
return web.AppConfig.DefaultString(key, defaultValue)
|
||||
}
|
||||
|
||||
//重写生成URL的方法,加上完整的域名
|
||||
func URLFor(endpoint string, values ...interface{}) string {
|
||||
baseUrl := web.AppConfig.DefaultString("baseurl", "")
|
||||
|
|
|
@ -1,11 +1,82 @@
|
|||
package routers
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/beego/beego/v2/server/web/context"
|
||||
"github.com/mindoc-org/mindoc/conf"
|
||||
"github.com/mindoc-org/mindoc/controllers"
|
||||
)
|
||||
|
||||
func rt(req *http.Request) (*http.Response, error) {
|
||||
log.Printf("request received. url=%s", req.URL)
|
||||
// req.Header.Set("Host", "httpbin.org") // <--- I set it here as well
|
||||
defer log.Printf("request complete. url=%s", req.URL)
|
||||
|
||||
return http.DefaultTransport.RoundTrip(req)
|
||||
}
|
||||
|
||||
// roundTripper makes func signature a http.RoundTripper
|
||||
type roundTripper func(*http.Request) (*http.Response, error)
|
||||
|
||||
func (f roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { return f(req) }
|
||||
|
||||
type CorsTransport struct {
|
||||
http.RoundTripper
|
||||
}
|
||||
|
||||
func (t *CorsTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||
// refer:
|
||||
// - https://stackoverflow.com/questions/31535569/golang-how-to-read-response-body-of-reverseproxy/31536962#31536962
|
||||
// - https://gist.github.com/simon-cj/b4da0b2bca793ec3b8a5abe04c8fca41
|
||||
resp, err = t.RoundTripper.RoundTrip(req)
|
||||
logs.Debug(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Header.Del("Access-Control-Request-Method")
|
||||
resp.Header.Set("Access-Control-Allow-Origin", "*")
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
web.Any("/cors-anywhere", func(ctx *context.Context) {
|
||||
u, _ := url.PathUnescape(ctx.Input.Query("url"))
|
||||
logs.Error("ReverseProxy: ", u)
|
||||
if len(u) > 0 && strings.HasPrefix(u, "http") {
|
||||
if strings.TrimRight(conf.BaseUrl, "/") == ctx.Input.Site() {
|
||||
ctx.Redirect(302, u)
|
||||
} else {
|
||||
target, _ := url.Parse(u)
|
||||
logs.Debug("target: ", target)
|
||||
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Transport: roundTripper(rt),
|
||||
Director: func(req *http.Request) {
|
||||
req.Header = ctx.Request.Header
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Path = target.Path
|
||||
req.Header.Set("Host", target.Host)
|
||||
},
|
||||
}
|
||||
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
proxy.ServeHTTP(ctx.ResponseWriter, ctx.Request)
|
||||
}
|
||||
} else {
|
||||
ctx.ResponseWriter.WriteHeader(http.StatusBadRequest)
|
||||
ctx.Output.Body([]byte("400 Bad Request"))
|
||||
}
|
||||
})
|
||||
|
||||
web.Router("/", &controllers.HomeController{}, "*:Index")
|
||||
|
||||
web.Router("/login", &controllers.AccountController{}, "*:Login")
|
||||
|
|
|
@ -96,6 +96,7 @@ body{
|
|||
bottom: 0;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #DDDDDD;
|
||||
z-index: 999;
|
||||
}
|
||||
.manual-editor-container .manual-editormd{
|
||||
position: absolute;
|
||||
|
|
|
@ -3,6 +3,10 @@ $(function () {
|
|||
js : window.katex.js,
|
||||
css : window.katex.css
|
||||
};
|
||||
var htmlDecodeList = ["style","script","title","onmouseover","onmouseout","style"];
|
||||
if (!window.IS_ENABLE_IFRAME) {
|
||||
htmlDecodeList.unshift("iframe");
|
||||
}
|
||||
window.editor = editormd("docEditor", {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
@ -18,8 +22,8 @@ $(function () {
|
|||
taskList: true,
|
||||
flowChart: true,
|
||||
mermaid: true,
|
||||
htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
|
||||
lineNumbers: false,
|
||||
htmlDecode: htmlDecodeList.join(','),
|
||||
lineNumbers: true,
|
||||
sequenceDiagram: true,
|
||||
highlightStyle: window.highlightStyle ? window.highlightStyle : "github",
|
||||
tocStartLevel: 1,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!function(P,H,k){"use strict";if(1==P.importNode.length&&!H.get("ungap-li")){var D="extends";try{var e={extends:"li"},t=HTMLLIElement,n=function(){return Reflect.construct(t,[],n)};if(n.prototype=k.create(t.prototype),H.define("ungap-li",n,e),!/is="ungap-li"/.test((new n).outerHTML))throw e}catch(e){!function(){var l="attributeChangedCallback",n="connectedCallback",r="disconnectedCallback",e=Element.prototype,i=k.assign,t=k.create,o=k.defineProperties,a=k.getOwnPropertyDescriptor,s=k.setPrototypeOf,u=H.define,c=H.get,f=H.upgrade,p=H.whenDefined,v=t(null),d=new WeakMap,g={childList:!0,subtree:!0};Reflect.ownKeys(self).filter(function(e){return"string"==typeof e&&/^HTML(?!Element)/.test(e)}).forEach(function(e){function t(){}var n=self[e];s(t,n),(t.prototype=n.prototype).constructor=t,(n={})[e]={value:t},o(self,n)}),new MutationObserver(m).observe(P,g),O(Document.prototype,"importNode"),O(Node.prototype,"cloneNode"),o(H,{define:{value:function(e,t,n){if(e=e.toLowerCase(),n&&D in n){v[e]=i({},n,{Class:t});for(var e=n[D]+'[is="'+e+'"]',r=P.querySelectorAll(e),o=0,a=r.length;o<a;o++)A(r[o])}else u.apply(H,arguments)}},get:{value:function(e){return e in v?v[e].Class:c.call(H,e)}},upgrade:{value:function(e){var t=L(e);!t||e instanceof t.Class?f.call(H,e):N(e,t)}},whenDefined:{value:function(e){return e in v?Promise.resolve():p.call(H,e)}}});var h=P.createElement;o(P,{createElement:{value:function(e,t){e=h.call(P,e);return t&&"is"in t&&(e.setAttribute("is",t.is),H.upgrade(e)),e}}});var b=a(e,"attachShadow").value,y=a(e,"innerHTML");function m(e){for(var t=0,n=e.length;t<n;t++){for(var r=e[t],o=r.addedNodes,a=r.removedNodes,i=0,l=o.length;i<l;i++)A(o[i]);for(i=0,l=a.length;i<l;i++)C(a[i])}}function w(e){for(var t=0,n=e.length;t<n;t++){var r=e[t],o=r.attributeName,a=r.oldValue,i=r.target,r=i.getAttribute(o);l in i&&(a!=r||null!=r)&&i[l](o,a,i.getAttribute(o),null)}}function C(e){var t;1===e.nodeType&&((t=L(e))&&e instanceof t.Class&&r in e&&d.get(e)!==r&&(d.set(e,r),Promise.resolve(e).then(T)),E(e,C))}function L(e){e=e.getAttribute("is");return e&&(e=e.toLowerCase())in v?v[e]:null}function M(e){e[n]()}function T(e){e[r]()}function N(e,t){var t=t.Class,n=t.observedAttributes||[];if(s(e,t.prototype),n.length){new MutationObserver(w).observe(e,{attributes:!0,attributeFilter:n,attributeOldValue:!0});for(var r=[],o=0,a=n.length;o<a;o++)r.push({attributeName:n[o],oldValue:null,target:e});w(r)}}function A(e){var t;1===e.nodeType&&((t=L(e))&&(e instanceof t.Class||N(e,t),n in e&&e.isConnected&&d.get(e)!==n&&(d.set(e,n),Promise.resolve(e).then(M))),E(e,A))}function E(e,t){for(var n=e.content,r=(n&&11==n.nodeType?n:e).querySelectorAll("[is]"),o=0,a=r.length;o<a;o++)t(r[o])}function O(e,t){var n=e[t],r={};r[t]={value:function(){var e=n.apply(this,arguments);switch(e.nodeType){case 1:case 11:E(e,A)}return e}},o(e,r)}o(e,{attachShadow:{value:function(){var e=b.apply(this,arguments);return new MutationObserver(m).observe(e,g),e}},innerHTML:{get:y.get,set:function(e){y.set.call(this,e),/\bis=("|')?[a-z0-9_-]+\1/i.test(e)&&E(this,A)}}})}()}}}(document,customElements,Object);
|
|
@ -54,7 +54,10 @@ $(function () {
|
|||
remark: 'Remark',
|
||||
}
|
||||
};
|
||||
|
||||
var htmlDecodeList = ["style","script","title","onmouseover","onmouseout","style"];
|
||||
if (!window.IS_ENABLE_IFRAME) {
|
||||
htmlDecodeList.unshift("iframe");
|
||||
}
|
||||
window.editor = editormd("docEditor", {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
@ -69,8 +72,8 @@ $(function () {
|
|||
fileUploadURL: window.fileUploadURL,
|
||||
taskList: true,
|
||||
flowChart: true,
|
||||
htmlDecode: "style,script,iframe,title,onmouseover,onmouseout,style",
|
||||
lineNumbers: false,
|
||||
htmlDecode: htmlDecodeList.join(','),
|
||||
lineNumbers: true,
|
||||
sequenceDiagram: true,
|
||||
tocStartLevel: 1,
|
||||
tocm: true,
|
||||
|
@ -193,7 +196,7 @@ $(function () {
|
|||
} else {
|
||||
var action = window.editor.toolbarHandlers[name];
|
||||
|
||||
if (action !== "undefined") {
|
||||
if (!!action && action !== "undefined") {
|
||||
$.proxy(action, window.editor)();
|
||||
window.editor.focus();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
customElements.define('x-frame-bypass', class extends HTMLIFrameElement {
|
||||
static get observedAttributes() {
|
||||
return ['src']
|
||||
}
|
||||
constructor () {
|
||||
super()
|
||||
}
|
||||
attributeChangedCallback () {
|
||||
this.load(this.src)
|
||||
}
|
||||
connectedCallback () {
|
||||
this.sandbox = '' + this.sandbox || 'allow-forms allow-modals allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation' // all except allow-top-navigation
|
||||
}
|
||||
load (url, options) {
|
||||
if (!url || !url.startsWith('http'))
|
||||
throw new Error(`X-Frame-Bypass src ${url} does not start with http(s)://`)
|
||||
console.log('X-Frame-Bypass loading:', url)
|
||||
this.srcdoc = `<html>
|
||||
<head>
|
||||
<style>
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: calc(50% - 25px);
|
||||
left: calc(50% - 25px);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: #333;
|
||||
border-radius: 50%;
|
||||
animation: loader 1s infinite ease-in-out;
|
||||
}
|
||||
@keyframes loader {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="loader"></div>
|
||||
</body>
|
||||
</html>`
|
||||
this.fetchProxy(url, options, 0).then(res => res.text()).then(data => {
|
||||
if (data)
|
||||
this.srcdoc = data.replace(/<head([^>]*)>/i, `<head$1>
|
||||
<base href="${url}">
|
||||
<script>
|
||||
// X-Frame-Bypass navigation event handlers
|
||||
document.addEventListener('click', e => {
|
||||
if (frameElement && document.activeElement && document.activeElement.href) {
|
||||
e.preventDefault()
|
||||
frameElement.load(document.activeElement.href)
|
||||
}
|
||||
})
|
||||
document.addEventListener('submit', e => {
|
||||
if (frameElement && document.activeElement && document.activeElement.form && document.activeElement.form.action) {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.form.method === 'post')
|
||||
frameElement.load(document.activeElement.form.action, {method: 'post', body: new FormData(document.activeElement.form)})
|
||||
else
|
||||
frameElement.load(document.activeElement.form.action + '?' + new URLSearchParams(new FormData(document.activeElement.form)))
|
||||
}
|
||||
})
|
||||
</script>`)
|
||||
}).catch(e => console.error('Cannot load X-Frame-Bypass:', e))
|
||||
}
|
||||
fetchProxy (url, options, i) {
|
||||
const proxies = (options || {}).proxies || [
|
||||
window.BASE_URL + 'cors-anywhere?url=',
|
||||
'https://cors-anywhere.herokuapp.com/',
|
||||
'https://yacdn.org/proxy/',
|
||||
'https://api.codetabs.com/v1/proxy/?quest='
|
||||
]
|
||||
return fetch(proxies[i] + url, options).then(res => {
|
||||
if (!res.ok)
|
||||
throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res
|
||||
}).catch(error => {
|
||||
if (i === proxies.length - 1)
|
||||
throw error
|
||||
return this.fetchProxy(url, options, i + 1)
|
||||
})
|
||||
}
|
||||
}, {extends: 'iframe'})
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/mindoc-org/mindoc/conf"
|
||||
)
|
||||
|
||||
func StripTags(s string) string {
|
||||
func StripTags(s string) string {
|
||||
|
||||
//将HTML标签全转换成小写
|
||||
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
|
||||
|
@ -33,8 +33,9 @@ func StripTags(s string) string {
|
|||
|
||||
return src
|
||||
}
|
||||
|
||||
//自动提取文章摘要
|
||||
func AutoSummary(body string,l int) string {
|
||||
func AutoSummary(body string, l int) string {
|
||||
|
||||
//匹配图片,如果图片语法是在代码块中,这里同样会处理
|
||||
re := regexp.MustCompile(`<p>(.*?)</p>`)
|
||||
|
@ -42,11 +43,11 @@ func AutoSummary(body string,l int) string {
|
|||
contents := re.FindAllString(body, -1)
|
||||
|
||||
if len(contents) <= 0 {
|
||||
return ""
|
||||
return ""
|
||||
}
|
||||
content := ""
|
||||
for _,s := range contents {
|
||||
b := strings.Replace(StripTags(s),"\n","", -1)
|
||||
for _, s := range contents {
|
||||
b := strings.Replace(StripTags(s), "\n", "", -1)
|
||||
|
||||
if l <= 0 {
|
||||
break
|
||||
|
@ -70,7 +71,9 @@ func SafetyProcessor(html string) string {
|
|||
docQuery.Find("applet").Remove()
|
||||
docQuery.Find("frame").Remove()
|
||||
docQuery.Find("meta").Remove()
|
||||
docQuery.Find("iframe").Remove()
|
||||
if !conf.GetEnableIframe() {
|
||||
docQuery.Find("iframe").Remove()
|
||||
}
|
||||
docQuery.Find("*").Each(func(i int, selection *goquery.Selection) {
|
||||
|
||||
if href, ok := selection.Attr("href"); ok && strings.HasPrefix(href, "javascript:") {
|
||||
|
@ -117,10 +120,9 @@ func SafetyProcessor(html string) string {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if html, err := docQuery.Html(); err == nil {
|
||||
return strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(html), "<html><head></head><body>"), "</body></html>")
|
||||
return strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(html), "<html><head></head><body>"), "</body></html>")
|
||||
}
|
||||
}
|
||||
return html
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
<link href="{{cdncss "/static/katex/katex.min.css"}}" rel="stylesheet">
|
||||
<link href="{{cdncss "/static/css/print.css" "version"}}" media="print" rel="stylesheet">
|
||||
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
<script type="text/javascript">window.book={"identify":"{{.Model.Identify}}"};</script>
|
||||
<style>
|
||||
.btn-mobile {
|
||||
|
@ -251,6 +255,8 @@
|
|||
<script src="{{cdnjs "/static/js/jquery.highlight.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/kancloud.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/splitbar.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#searchList").on("click","a",function () {
|
||||
|
|
|
@ -92,6 +92,10 @@
|
|||
border: 1px solid #357ebd;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="auth_form">
|
||||
|
@ -109,6 +113,8 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$("#auth_form").ajaxForm({
|
||||
beforeSerialize: function () {
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
color: #44B036 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
window.editor = null;
|
||||
window.imageUploadURL = "{{urlfor "DocumentController.Upload" "identify" .Model.Identify}}";
|
||||
|
@ -207,6 +210,8 @@
|
|||
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/editor.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/html-editor.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
lang = {{i18n $.Lang "common.js_lang"}};
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
<script src="/static/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="/static/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="m-manual manual-reader">
|
||||
|
@ -173,6 +177,8 @@
|
|||
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||
<script src="{{cdnjs "/static/jstree/3.3.4/jstree.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/jquery/plugins/imgbox/jquery.imgbox.pack.js"}}"></script>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$("#sidebar").jstree({
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{{i18n .Lang "doc.edit_doc"}} - Powered by MinDoc</title>
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
window.treeCatalog = null;
|
||||
window.baseUrl = "{{.BaseUrl}}";
|
||||
|
@ -109,6 +113,7 @@
|
|||
</div>
|
||||
|
||||
<div class="editormd-group pull-right">
|
||||
<a target="_blank" href="{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}" data-toggle="tooltip" data-title="{{i18n .Lang "blog.preview"}}"><i class="fa fa-external-link" name="preview-open" aria-hidden="true"></i></a>
|
||||
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.publish"}}"><i class="fa fa-cloud-upload" name="release" aria-hidden="true"></i></a>
|
||||
</div>
|
||||
|
||||
|
@ -451,6 +456,8 @@
|
|||
<script src="{{cdnjs "/static/js/array.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/editor.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/markdown.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
editLangPath = {{cdnjs "/static/editor.md/languages/"}} + lang
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{{i18n .Lang "doc.edit_doc"}} - Powered by MinDoc</title>
|
||||
<script type="text/javascript">
|
||||
window.IS_ENABLE_IFRAME = '{{conf "enable_iframe" }}' === 'true';
|
||||
window.BASE_URL = '{{urlfor "HomeController.Index" }}';
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
window.editor = null;
|
||||
window.imageUploadURL = "{{urlfor "DocumentController.Upload" "identify" .Model.Identify}}";
|
||||
|
@ -384,6 +388,8 @@
|
|||
<script src="{{cdnjs "/static/js/array.js" "version"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/editor.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/quill.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/custom-elements-builtin-0.6.5.min.js"}}" type="text/javascript"></script>
|
||||
<script src="{{cdnjs "/static/js/x-frame-bypass-1.0.2.js"}}" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
lang = {{i18n $.Lang "common.js_lang"}};
|
||||
|
|
Loading…
Reference in New Issue