From af8afa7fabd98456969201b346f9e480b8889a02 Mon Sep 17 00:00:00 2001 From: movsb Date: Thu, 21 Nov 2024 20:33:14 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=90=E5=88=B6=E6=96=87=E7=AB=A0=E5=86=85?= =?UTF-8?q?=E7=9A=84=E6=A0=B7=E5=BC=8F=E8=A1=A8=E7=9A=84=E4=BD=9C=E7=94=A8?= =?UTF-8?q?=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 3 + service/modules/renderers/all_test.go | 7 ++ .../modules/renderers/scoped_css/README.md | 27 +++++++ .../modules/renderers/scoped_css/all_test.go | 31 +++++++ .../renderers/scoped_css/scoped_css.go | 80 +++++++++++++++++++ service/post.go | 2 + theme/blog/templates/_tweet.html | 2 +- theme/blog/templates/post.html | 2 +- theme/blog/templates/tweet.html | 2 +- 10 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 service/modules/renderers/scoped_css/README.md create mode 100644 service/modules/renderers/scoped_css/all_test.go create mode 100644 service/modules/renderers/scoped_css/scoped_css.go diff --git a/go.mod b/go.mod index 709ba90d..c7f0733e 100644 --- a/go.mod +++ b/go.mod @@ -65,6 +65,7 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect + github.com/tdewolff/parse/v2 v2.7.19 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/crypto v0.22.0 // indirect diff --git a/go.sum b/go.sum index db175cdd..3fd72fdd 100644 --- a/go.sum +++ b/go.sum @@ -323,6 +323,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/parse/v2 v2.7.19 h1:7Ljh26yj+gdLFEq/7q9LT4SYyKtwQX4ocNrj45UCePg= +github.com/tdewolff/parse/v2 v2.7.19/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= diff --git a/service/modules/renderers/all_test.go b/service/modules/renderers/all_test.go index c095d082..46af2a91 100644 --- a/service/modules/renderers/all_test.go +++ b/service/modules/renderers/all_test.go @@ -18,6 +18,7 @@ import ( gold_utils "github.com/movsb/taoblog/service/modules/renderers/goldutils" "github.com/movsb/taoblog/service/modules/renderers/imaging" "github.com/movsb/taoblog/service/modules/renderers/media_size" + "github.com/movsb/taoblog/service/modules/renderers/scoped_css" "github.com/yuin/goldmark/extension" ) @@ -167,6 +168,12 @@ func TestMarkdownAll(t *testing.T) { Markdown: `a #b c #桃子`, Html: `

a #b c #桃子

`, }, + { + ID: 12.0, + Options: []renderers.Option2{scoped_css.New(`article#123`)}, + Markdown: ``, + Html: ``, + }, } for _, tc := range cases { if tc.ID == 10.0 { diff --git a/service/modules/renderers/scoped_css/README.md b/service/modules/renderers/scoped_css/README.md new file mode 100644 index 00000000..e446223c --- /dev/null +++ b/service/modules/renderers/scoped_css/README.md @@ -0,0 +1,27 @@ +# Scoped CSS + +单篇文章的样式文件应该只应用到文章本身,而不应该影响到其它文章。 +编写样式的时候,不应该手动限制样式为当前文章标签,这样会有较大的心智负担。 + +比较,文章里面可以这样写: + +```html + +``` + +当把多篇文章显示在同一个页面下时,会影响到所有表格,这种行为是不预期的。 +所以应该限定一下范围(scope),比如改写成如下形式: + +```html + +``` + +把其范围限制到只对文章(编号为 123)有效。 diff --git a/service/modules/renderers/scoped_css/all_test.go b/service/modules/renderers/scoped_css/all_test.go new file mode 100644 index 00000000..638876e0 --- /dev/null +++ b/service/modules/renderers/scoped_css/all_test.go @@ -0,0 +1,31 @@ +package scoped_css + +import "testing" + +func TestAddScope(t *testing.T) { + testCases := []struct { + scope string + before string + after string + }{ + { + scope: `article`, + before: ` +table, tr td { + min-width: 100px; +} +`, + after: `article table,article tr td{min-width:100px;}`, + }, + } + for i, tc := range testCases { + output, err := addScope(tc.before, tc.scope) + if err != nil { + t.Errorf(`Error %d: %v`, i, err) + continue + } + if output != tc.after { + t.Errorf("Not Equal: %d:\n%s\n%s", i, output, tc.after) + } + } +} diff --git a/service/modules/renderers/scoped_css/scoped_css.go b/service/modules/renderers/scoped_css/scoped_css.go new file mode 100644 index 00000000..acb4b1e7 --- /dev/null +++ b/service/modules/renderers/scoped_css/scoped_css.go @@ -0,0 +1,80 @@ +package scoped_css + +import ( + "io" + + "github.com/PuerkitoBio/goquery" + "github.com/tdewolff/parse/v2" + "github.com/tdewolff/parse/v2/css" + "golang.org/x/net/html" +) + +func New(scope string) *ScopedCSS { + return &ScopedCSS{ + scope: scope, + } +} + +type ScopedCSS struct { + scope string +} + +func (p *ScopedCSS) TransformHtml(doc *goquery.Document) error { + var err error + doc.Find(`style`).Each(func(i int, s *goquery.Selection) { + if er := p.addScope(s); er != nil { + err = er + } + }) + return err +} + +func (p *ScopedCSS) addScope(s *goquery.Selection) error { + if first := s.Nodes[0].FirstChild; first != nil && first.Type == html.TextNode { + raw := first.Data + scoped, err := addScope(raw, p.scope) + if err != nil { + return err + } + first.Data = scoped + } + return nil +} + +// 可以参考:https://github.com/tdewolff/parse/blob/master/css/parse_test.go +func addScope(raw string, scope string) (string, error) { + p := css.NewParser(parse.NewInputString(raw), false) + output := "" + for { + grammar, _, data := p.Next() + data = parse.Copy(data) + // log.Println(grammar, string(data), p.Values()) + if grammar == css.ErrorGrammar { + if err := p.Err(); err != io.EOF { + return ``, err + } + break + } + if grammar == css.AtRuleGrammar || grammar == css.BeginAtRuleGrammar || grammar == css.QualifiedRuleGrammar || grammar == css.BeginRulesetGrammar || grammar == css.DeclarationGrammar || grammar == css.CustomPropertyGrammar { + if grammar == css.DeclarationGrammar || grammar == css.CustomPropertyGrammar { + data = append(data, ":"...) + } + if grammar == css.QualifiedRuleGrammar || grammar == css.BeginRulesetGrammar { + data = append(data, scope...) + data = append(data, ' ') + } + for _, val := range p.Values() { + data = append(data, val.Data...) + } + if grammar == css.BeginAtRuleGrammar || grammar == css.BeginRulesetGrammar { + data = append(data, "{"...) + } else if grammar == css.AtRuleGrammar || grammar == css.DeclarationGrammar || grammar == css.CustomPropertyGrammar { + data = append(data, ";"...) + } else if grammar == css.QualifiedRuleGrammar { + data = append(data, ","...) + } + } + output += string(data) + } + return output, nil +} diff --git a/service/post.go b/service/post.go index e220db11..ddbbf058 100644 --- a/service/post.go +++ b/service/post.go @@ -32,6 +32,7 @@ import ( "github.com/movsb/taoblog/service/modules/renderers/media_size" "github.com/movsb/taoblog/service/modules/renderers/media_tags" "github.com/movsb/taoblog/service/modules/renderers/rooted_path" + "github.com/movsb/taoblog/service/modules/renderers/scoped_css" task_list "github.com/movsb/taoblog/service/modules/renderers/tasklist" "github.com/movsb/taorm" "github.com/yuin/goldmark/extension" @@ -268,6 +269,7 @@ func (s *Service) renderMarkdown(secure bool, postId, commentId int64, sourceTyp ) } options = append(options, media_tags.New(s.OpenAsset(postId), mediaTagOptions...)) + options = append(options, scoped_css.New(fmt.Sprintf(`article.post-%d .entry .content`, postId))) } if !secure { options = append(options, diff --git a/theme/blog/templates/_tweet.html b/theme/blog/templates/_tweet.html index 39b0aaf8..ad2dfd33 100644 --- a/theme/blog/templates/_tweet.html +++ b/theme/blog/templates/_tweet.html @@ -1,6 +1,6 @@ {{ define "_tweet" }} {{ $p := $.Partial }} -
+
diff --git a/theme/blog/templates/post.html b/theme/blog/templates/post.html index e24aa4c0..804f563a 100644 --- a/theme/blog/templates/post.html +++ b/theme/blog/templates/post.html @@ -8,7 +8,7 @@ {{- $dot:=. -}} {{- render "header" . -}} -
+
{{ with .Post.Post }}

{{.StatusString}}{{ .Title }}

diff --git a/theme/blog/templates/tweet.html b/theme/blog/templates/tweet.html index bb880694..d3141514 100644 --- a/theme/blog/templates/tweet.html +++ b/theme/blog/templates/tweet.html @@ -22,7 +22,7 @@ TaoBlog.posts["{{.Post.Post.Id}}"] = {{ $.Strip .Post.Post }};
-
+
{{ .Post.Post.Content }}