forked from go-shiori/obelisk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
process-css.go
81 lines (65 loc) · 1.64 KB
/
process-css.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package obelisk
import (
"bytes"
"context"
"io"
nurl "net/url"
"strings"
"sync"
"github.com/tdewolff/parse/v2"
"github.com/tdewolff/parse/v2/css"
"golang.org/x/sync/errgroup"
)
func (arc *Archiver) processCSS(ctx context.Context, input io.Reader, baseURL *nurl.URL) (string, error) {
// Prepare buffer to store content from input
buffer := bytes.NewBuffer(nil)
// Scan CSS and find all URLs
urls := make(map[string]struct{})
lexer := css.NewLexer(parse.NewInput(input))
for {
token, bt := lexer.Next()
// Check for error or EOF
if token == css.ErrorToken {
break
}
// If it's URL save it
if token == css.URLToken {
urls[string(bt)] = struct{}{}
}
buffer.Write(bt)
}
// Process each url concurrently
mutex := sync.RWMutex{}
processedURLs := make(map[string]string)
g, ctx := errgroup.WithContext(ctx)
for url := range urls {
url := url
g.Go(func() error {
cssURL := sanitizeStyleURL(url)
cssURL = createAbsoluteURL(cssURL, baseURL)
content, contentType, err := arc.processURL(ctx, cssURL, baseURL.String())
if err != nil && err != errSkippedURL {
return err
}
var result string
if err == errSkippedURL {
result = `url("` + cssURL + `")`
} else {
result = `url("` + arc.transform(cssURL, content, contentType) + `")`
}
mutex.Lock()
processedURLs[url] = result
mutex.Unlock()
return nil
})
}
if err := g.Wait(); err != nil {
return buffer.String(), err
}
// Convert all url into the processed URL
cssRules := buffer.String()
for url, processedURL := range processedURLs {
cssRules = strings.ReplaceAll(cssRules, url, processedURL)
}
return cssRules, nil
}