initial commit
This commit is contained in:
commit
7cb1f02423
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Binaries
|
||||
cmd/yatwiki-server/yatwiki-server
|
||||
|
||||
# Development db files
|
||||
cmd/yatwiki-server/wiki.db
|
146
DB.go
Normal file
146
DB.go
Normal file
@ -0,0 +1,146 @@
|
||||
package yatwiki3
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type WikiDB struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewWikiDB(dbFilePath string) (*WikiDB, error) {
|
||||
db, err := sql.Open("sqlite3", dbFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wdb := WikiDB{db: db}
|
||||
err = wdb.assertSchema()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("assertSchema: %s", err.Error())
|
||||
}
|
||||
|
||||
return &wdb, nil
|
||||
}
|
||||
|
||||
func (this *WikiDB) assertSchema() error {
|
||||
_, err := this.db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS articles (
|
||||
id INTEGER PRIMARY KEY,
|
||||
article INTEGER,
|
||||
modified INTEGER,
|
||||
body BLOB,
|
||||
author TEXT
|
||||
);`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS titles (
|
||||
id INTEGER PRIMARY KEY,
|
||||
title TEXT
|
||||
);`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.db.Exec(`
|
||||
CREATE INDEX IF NOT EXISTS articles_modified_index ON articles (modified)
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = this.db.Exec(`
|
||||
CREATE INDEX IF NOT EXISTS articles_title_index ON articles (article)
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Article struct {
|
||||
ID int
|
||||
TitleID int
|
||||
Modified int64
|
||||
Body []byte
|
||||
Author string
|
||||
}
|
||||
|
||||
func (this *Article) FillModifiedTimestamp() {
|
||||
this.Modified = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (this *Article) FillAuthor(r *http.Request) {
|
||||
userAgentHash := md5.Sum([]byte(r.UserAgent()))
|
||||
this.Author = r.RemoteAddr + "-" + hex.EncodeToString(userAgentHash[:])[:6]
|
||||
}
|
||||
|
||||
type ArticleWithTitle struct {
|
||||
Article
|
||||
Title string
|
||||
}
|
||||
|
||||
func (this *WikiDB) GetArticleById(articleId int) (*Article, error) {
|
||||
row := this.db.QueryRow(`SELECT articles.* FROM articles WHERE id = ?`, articleId)
|
||||
return this.parseArticle(row)
|
||||
}
|
||||
|
||||
func (this *WikiDB) GetLatestVersion(title string) (*Article, error) {
|
||||
row := this.db.QueryRow(`SELECT articles.* FROM articles WHERE article = (SELECT id FROM titles WHERE title = ?) ORDER BY modified DESC LIMIT 1`, title)
|
||||
return this.parseArticle(row)
|
||||
}
|
||||
|
||||
func (this *WikiDB) ListTitles() ([]string, error) {
|
||||
rows, err := this.db.Query(`SELECT title FROM titles ORDER BY title ASC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
ret := make([]string, 0)
|
||||
for rows.Next() {
|
||||
var title string
|
||||
err = rows.Scan(&title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = append(ret, title)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (this *WikiDB) parseArticle(row *sql.Row) (*Article, error) {
|
||||
a := Article{}
|
||||
err := row.Scan(&a.ID, &a.TitleID, &a.Modified, &a.Body, &a.Author)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
func (this *WikiDB) parseArticleWithTitle(row *sql.Row) (*ArticleWithTitle, error) {
|
||||
a := ArticleWithTitle{}
|
||||
err := row.Scan(&a.ID, &a.TitleID, &a.Modified, &a.Body, &a.Author, &a.Title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &a, nil
|
||||
}
|
||||
|
||||
func (this *WikiDB) Close() {
|
||||
this.db.Close()
|
||||
}
|
31
ServerOptions.go
Normal file
31
ServerOptions.go
Normal file
@ -0,0 +1,31 @@
|
||||
package yatwiki3
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ServerOptions struct {
|
||||
PageTitle string
|
||||
ExpectBaseURL string
|
||||
DefaultPage string
|
||||
Timezone string
|
||||
DateFormat string
|
||||
DBFilePath string
|
||||
AllowDBDownload bool
|
||||
RecentChanges int
|
||||
GzipCompressionLevel int
|
||||
}
|
||||
|
||||
func DefaultOptions() *ServerOptions {
|
||||
return &ServerOptions{
|
||||
PageTitle: "YATWiki",
|
||||
ExpectBaseURL: "/",
|
||||
DefaultPage: "home",
|
||||
Timezone: "UTC",
|
||||
DateFormat: time.RFC822Z,
|
||||
DBFilePath: "wiki.db",
|
||||
AllowDBDownload: true,
|
||||
RecentChanges: 20,
|
||||
GzipCompressionLevel: 9,
|
||||
}
|
||||
}
|
59
WikiServer.go
Normal file
59
WikiServer.go
Normal file
@ -0,0 +1,59 @@
|
||||
package yatwiki3
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type WikiServer struct {
|
||||
db *WikiDB
|
||||
opts *ServerOptions
|
||||
pageTmp *template.Template
|
||||
}
|
||||
|
||||
func NewWikiServer(opts *ServerOptions) (*WikiServer, error) {
|
||||
wdb, err := NewWikiDB(opts.DBFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmpl, err := template.New("yatwiki/page").Parse(pageTemplate)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ws := WikiServer{
|
||||
db: wdb,
|
||||
opts: opts,
|
||||
pageTmp: tmpl,
|
||||
}
|
||||
return &ws, nil
|
||||
}
|
||||
|
||||
func (this *WikiServer) Close() {
|
||||
this.db.Close()
|
||||
}
|
||||
|
||||
func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Server", "Yatwiki3")
|
||||
|
||||
if r.URL.Path == this.opts.ExpectBaseURL+"wiki.css" {
|
||||
w.Header().Set("Content-Type", "text/css")
|
||||
w.Write(tmplWikiCss)
|
||||
return
|
||||
}
|
||||
|
||||
pto := DefaultPageTemplateOptions(this.opts)
|
||||
pto.SessionMessage = `Invalid request.`
|
||||
//pto.CurrentPageIsArticle = true
|
||||
//pto.CurrentPageName = "quotes/\"2017"
|
||||
this.servePageResponse(w, pto)
|
||||
}
|
||||
|
||||
func (this *WikiServer) servePageResponse(w http.ResponseWriter, pto *pageTemplateOptions) {
|
||||
err := this.pageTmp.Execute(w, pto)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
}
|
35
cmd/yatwiki-server/main.go
Normal file
35
cmd/yatwiki-server/main.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"code.ivysaur.me/yatwiki3"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
bindAddr := flag.String("listen", "127.0.0.1:80", "Bind address")
|
||||
dbPath := flag.String("database", "wiki.db", "Database file")
|
||||
flag.Parse()
|
||||
|
||||
opts := yatwiki3.DefaultOptions()
|
||||
opts.DBFilePath = *dbPath
|
||||
|
||||
ws, err := yatwiki3.NewWikiServer(opts)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
err = http.ListenAndServe(*bindAddr, ws)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
113
pageTemplate.go
Normal file
113
pageTemplate.go
Normal file
@ -0,0 +1,113 @@
|
||||
package yatwiki3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
var subresourceNonce = time.Now().Unix()
|
||||
|
||||
type pageTemplateOptions struct {
|
||||
CurrentPageIsArticle bool
|
||||
CurrentPageName string
|
||||
WikiTitle string
|
||||
Content template.HTML
|
||||
BaseURL string
|
||||
LoadCodeResources bool
|
||||
DefaultPage string
|
||||
AllowDownload bool
|
||||
SessionMessage template.HTML
|
||||
}
|
||||
|
||||
func DefaultPageTemplateOptions(opts *ServerOptions) *pageTemplateOptions {
|
||||
return &pageTemplateOptions{
|
||||
WikiTitle: opts.PageTitle,
|
||||
BaseURL: opts.ExpectBaseURL,
|
||||
DefaultPage: opts.DefaultPage,
|
||||
AllowDownload: opts.AllowDBDownload,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *pageTemplateOptions) NewArticleTitle() string {
|
||||
return fmt.Sprintf("untitled-%d", time.Now().Unix())
|
||||
}
|
||||
|
||||
func (this *pageTemplateOptions) SubresourceNonce() int64 {
|
||||
return subresourceNonce
|
||||
}
|
||||
|
||||
const pageTemplate string = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.CurrentPageName}}{{ if len .CurrentPageName }} - {{end}}{{.WikiTitle}}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<link rel="alternate" type="application/rss+xml" href="{{.BaseURL}}rss/changes" title="{{.WikiTitle}} - Recent Changes">
|
||||
<link rel="stylesheet" type="text/css" href="{{.BaseURL}}wiki.css?_={{.SubresourceNonce}}">
|
||||
{{if .LoadCodeResources}}
|
||||
<script type="text/javascript" src="{{.BaseURL}}highlight.js?_={{.SubresourceNonce}}"></script>
|
||||
<script type="text/javascript">hljs.tabReplace = ' ';hljs.initHighlightingOnLoad();</script>
|
||||
{{end}}
|
||||
<script type="text/javascript">
|
||||
var a = document;
|
||||
function tid(id) {
|
||||
t(a.getElementById(id));
|
||||
}
|
||||
function ts(e) {
|
||||
t(e.nextSibling);
|
||||
}
|
||||
function t(e) {
|
||||
e.style.display=(e.style.display=='none') ? 'block' : 'none';
|
||||
}
|
||||
function els(e,s){ // no js exec in innerHTML
|
||||
var p = e.parentNode;
|
||||
p.className = "";
|
||||
p.innerHTML = s;
|
||||
var n = "script";
|
||||
var z = p.childNodes,
|
||||
m = "text/javascript",
|
||||
l = function(s){ return s.toLowerCase(); };
|
||||
for (var i=0, e=0; e = z[i]; i++) {
|
||||
if (e.nodeName && (l(e.nodeName)===n) && (!e.type||l(e.type)===m)) {
|
||||
var t = p.removeChild(e),
|
||||
d = a.getElementsByTagName("head")[0],
|
||||
se = a.createElement(n);
|
||||
se.type = m;
|
||||
se.appendChild(a.createTextNode((t.text||t.textContent||t.innerHTML||"")));
|
||||
d.insertBefore(se,d.firstChild );
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<a href="{{.BaseURL}}view/{{.DefaultPage}}" title="Home"><div class="sprite hm"></div></a>
|
||||
<a href="javascript:;" onclick="tid('spm');tid('tr1');tid('tr2');" title="Menu"><div class="sprite sp"></div></a>
|
||||
<a href="{{.BaseURL}}modify/{{.NewArticleTitle}}" title="New Page"><div class="sprite nw"></div></a>
|
||||
{{if .CurrentPageIsArticle }}
|
||||
<div class="sep"></div>
|
||||
<a href="{{.BaseURL}}history/{{.CurrentPageName}}" title="Page History"><div class="sprite hs"></div></a>
|
||||
<a href="{{.BaseURL}}modify/{{.CurrentPageName}}" title="Modify Page"><div class="sprite ed"></div></a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div id="tr1" style="display:none;"></div>
|
||||
<div id="tr2" style="display:none;"></div>
|
||||
<div class="ddmenu" id="spm" style="display:none;">
|
||||
<a href="{{.BaseURL}}recent"><div class="sprite no"></div> Recent Changes</a>
|
||||
<a href="{{.BaseURL}}random"><div class="sprite rn"></div> Random Page</a>
|
||||
<a href="{{.BaseURL}}index"><div class="sprite no"></div> Article Index</a>
|
||||
{{if .AllowDownload}}
|
||||
<a href="{{.BaseURL}}download-database"><div class="sprite no"></div> Download DB backup</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="content">
|
||||
{{if len .SessionMessage}}
|
||||
<div class="info">{{.SessionMessage}}</div>
|
||||
{{end}}
|
||||
{{.Content}}
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
279
tmpl_WikiCss.go
Normal file
279
tmpl_WikiCss.go
Normal file
@ -0,0 +1,279 @@
|
||||
package yatwiki3
|
||||
|
||||
var tmplWikiCss []byte = []byte(`
|
||||
/* wiki.css */
|
||||
html,body {
|
||||
background:white;color:black;font-size:12px;
|
||||
margin:0;padding:0;border:0;
|
||||
}
|
||||
html,body,input{font-family:Verdana,Arial;}
|
||||
table,tr,td,th {border:0px;}
|
||||
input {font-size:8px;}
|
||||
a {text-decoration:none;color: blue;}
|
||||
a:hover {text-decoration:underline;}
|
||||
img {border:0px;max-width:100%;}
|
||||
ul {margin:0px; padding-left:30px;}
|
||||
h2 {display:inline;}
|
||||
pre {font-family:Consolas,Courier,monospace;font-size:11px;}
|
||||
td {padding:0px 10px;}
|
||||
.content{padding:8px;}
|
||||
.s {text-decoration:line-through;}
|
||||
.spoiler{color:black;background-color:black;}
|
||||
.spoiler:hover{color:white;}
|
||||
|
||||
.imgur {
|
||||
border:1px solid white;
|
||||
width:90px;
|
||||
height:90px;
|
||||
opacity:0.6;
|
||||
-moz-transition:all 0.1s linear;
|
||||
-webkit-transition:all 0.1s linear;
|
||||
}
|
||||
.imgur:hover {opacity: 1.0;}
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
background:#DDD;
|
||||
padding:3px;
|
||||
font-size:0px;
|
||||
box-shadow: 0px 4px 24px #CCC;
|
||||
/*position:absolute;
|
||||
left:0;right:0;*/
|
||||
}
|
||||
.header a {
|
||||
background:#DDD;
|
||||
color:grey;
|
||||
text-decoration: none;
|
||||
margin:0px 2px;
|
||||
border:1px solid #DDD;
|
||||
display:inline-block;
|
||||
height:16px;
|
||||
padding:2px 3px;
|
||||
-moz-transition:all 0.1s linear;
|
||||
-webkit-transition:all 0.1s linear;
|
||||
}
|
||||
.header a:hover {
|
||||
background:white;
|
||||
color:black;
|
||||
border:1px solid black;
|
||||
border-color:grey black black grey;
|
||||
}
|
||||
.info {
|
||||
display:block;
|
||||
border:1px solid darkgrey;
|
||||
padding:2px 4px;
|
||||
margin:10px 5px;
|
||||
color:black;
|
||||
background-color:lightyellow;
|
||||
}
|
||||
|
||||
/* Editor page */
|
||||
fieldset {border:1px solid grey;}
|
||||
fieldset legend {
|
||||
padding:2px 6px 2px 6px;
|
||||
background:#DDD;
|
||||
border:1px solid grey;
|
||||
font-weight:bold;
|
||||
}
|
||||
.editor {
|
||||
padding:0px;
|
||||
margin:0px;
|
||||
vertical-align:top;
|
||||
}
|
||||
#contentctr {
|
||||
border:1px dashed lightgrey;
|
||||
position:absolute;
|
||||
top:120px;right:10px;bottom:10px;left:10px;
|
||||
}
|
||||
.editor textarea {
|
||||
font-family:Consolas,Courier,monospace;font-size:10px;
|
||||
margin:0;padding:0;border:0;
|
||||
|
||||
width:100%;height:100%;
|
||||
min-width:100%;min-height:100%; /* no resize */
|
||||
max-width:100%;max-height:100%;
|
||||
position:absolute; /* IE7 */
|
||||
}
|
||||
.frm {
|
||||
border:1px solid #DDD;
|
||||
background:#EEE;
|
||||
font-size:10px;
|
||||
padding:5px;
|
||||
margin:5px 10px 10px 15px;
|
||||
}
|
||||
|
||||
/* Tables in content */
|
||||
.ti {border-collapse: collapse; border-style:hidden;}
|
||||
.ti td {border-left:1px solid #DDD;border-right:1px solid #DDD;}
|
||||
.ti tr:first-child {font-weight:bold;}
|
||||
.ti tr:first-child td {border-bottom:1px solid #DDD;}
|
||||
.ti tr:hover {background-color:#F8F8F8;}
|
||||
.ti tr:first-child:hover{background-color:white;}
|
||||
|
||||
/* Sprites */
|
||||
.sprite {
|
||||
display:inline-block;
|
||||
width:16px;height:16px;
|
||||
vertical-align:text-bottom;
|
||||
background-repeat:no-repeat;
|
||||
background-image: url(data:image/png;base64,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);
|
||||
}
|
||||
.sprite.hm { background-position:0px 0px;}
|
||||
.sprite.hs { background-position:0px -16px;}
|
||||
.sprite.sp { background-position:0px -32px;}
|
||||
.sprite.nw { background-position:-16px 0px;}
|
||||
.sprite.ed { background-position:-16px -16px;}
|
||||
.sprite.rn { background-position:-16px -32px;}
|
||||
.sprite.no {
|
||||
background:none;
|
||||
}
|
||||
.sep {
|
||||
display:inline-block;
|
||||
*display:inline; /* IE7 */
|
||||
zoom: 1; /* IE7 */
|
||||
height:16px;
|
||||
width:0px;
|
||||
border-left:1px solid darkgrey;
|
||||
border-right:1px solid #DDD;
|
||||
margin:0px 4px;
|
||||
}
|
||||
/* Sections */
|
||||
.section {
|
||||
display:inline-block;
|
||||
background:#F8F8F8;
|
||||
width:auto;
|
||||
padding:3px;
|
||||
border:1px dashed #DDD;
|
||||
}
|
||||
.sectionheader {
|
||||
color:green;
|
||||
font-weight:bold;
|
||||
}
|
||||
/* Dropdown */
|
||||
.ddmenu {
|
||||
display:block;
|
||||
position:absolute;
|
||||
top:28px;
|
||||
left:32px;
|
||||
width:180px;
|
||||
border-top:1px solid #999;
|
||||
box-shadow: 0px 4px 24px #CCC;
|
||||
z-index: 2;
|
||||
}
|
||||
.ddmenu a {
|
||||
color:black;
|
||||
display:inline-block;
|
||||
border:1px solid #999;
|
||||
border-top:0px;
|
||||
width:170px;
|
||||
padding:4px;
|
||||
background:#EEE;
|
||||
}
|
||||
.ddmenu a:hover {
|
||||
text-decoration:none;background:#FFF;
|
||||
-moz-transition:all 0.1s linear;
|
||||
-webkit-transition:all 0.1s linear;
|
||||
}
|
||||
#tr1 {
|
||||
width:0px;height:0px;border-bottom:10px solid #999;
|
||||
border-right:10px solid transparent;border-left:10px solid transparent;
|
||||
position:absolute;top:18px;left:35px;z-index:1;
|
||||
}
|
||||
#tr2 {
|
||||
width:0px;height:0px;border-bottom:10px solid #EEE;
|
||||
border-right:10px solid transparent;border-left:10px solid transparent;
|
||||
position:absolute;top:19px;left:35px;z-index:3;
|
||||
}
|
||||
/* Diffs, rawhtml */
|
||||
del{text-decoration:none;background:red;font-weight:bold;}
|
||||
ins{text-decoration:none;background:lightgreen;font-weight:bold;}
|
||||
.html a {color:red;font-weight:bold;}
|
||||
|
||||
/*
|
||||
|
||||
highlight.css
|
||||
Visual Studio-like style based on original C# coloring by Jason Diamond <jason@diamond.name>
|
||||
|
||||
*/
|
||||
pre code {
|
||||
display: block; padding: 0.5em;
|
||||
}
|
||||
|
||||
pre .comment,
|
||||
pre .annotation,
|
||||
pre .template_comment,
|
||||
pre .diff .header,
|
||||
pre .chunk,
|
||||
pre .apache .cbracket {
|
||||
color: rgb(0, 128, 0);
|
||||
}
|
||||
|
||||
pre .keyword,
|
||||
pre .id,
|
||||
pre .built_in,
|
||||
pre .smalltalk .class,
|
||||
pre .winutils,
|
||||
pre .bash .variable,
|
||||
pre .tex .command,
|
||||
pre .request,
|
||||
pre .status,
|
||||
pre .nginx .title,
|
||||
pre .xml .tag,
|
||||
pre .xml .tag .value {
|
||||
color: rgb(0, 0, 255);
|
||||
}
|
||||
|
||||
pre .string,
|
||||
pre .title,
|
||||
pre .parent,
|
||||
pre .tag .value,
|
||||
pre .rules .value,
|
||||
pre .rules .value .number,
|
||||
pre .ruby .symbol,
|
||||
pre .ruby .symbol .string,
|
||||
pre .aggregate,
|
||||
pre .template_tag,
|
||||
pre .django .variable,
|
||||
pre .addition,
|
||||
pre .flow,
|
||||
pre .stream,
|
||||
pre .apache .tag,
|
||||
pre .date,
|
||||
pre .tex .formula {
|
||||
color: rgb(163, 21, 21);
|
||||
}
|
||||
|
||||
pre .ruby .string,
|
||||
pre .decorator,
|
||||
pre .filter .argument,
|
||||
pre .localvars,
|
||||
pre .array,
|
||||
pre .attr_selector,
|
||||
pre .pseudo,
|
||||
pre .pi,
|
||||
pre .doctype,
|
||||
pre .deletion,
|
||||
pre .envvar,
|
||||
pre .shebang,
|
||||
pre .preprocessor,
|
||||
pre .userType,
|
||||
pre .apache .sqbracket,
|
||||
pre .nginx .built_in,
|
||||
pre .tex .special,
|
||||
pre .prompt {
|
||||
color: rgb(43, 145, 175);
|
||||
}
|
||||
|
||||
pre .phpdoc,
|
||||
pre .javadoc,
|
||||
pre .xmlDocTag {
|
||||
color: rgb(128, 128, 128);
|
||||
}
|
||||
|
||||
pre .vhdl .typename { font-weight: bold; }
|
||||
pre .vhdl .string { color: #666666; }
|
||||
pre .vhdl .literal { color: rgb(163, 21, 21); }
|
||||
pre .vhdl .attribute { color: #00B0E8; }
|
||||
|
||||
pre .xml .attribute { color: rgb(255, 0, 0); }
|
||||
`)
|
Loading…
Reference in New Issue
Block a user