forked from Botanical/BotanJS
Removed old impl
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package closure
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewCompileCache(workers int) *CompileCache {
|
||||
c := &CompileCache{
|
||||
client: NewClientFromEnv(),
|
||||
states: make(map[string]CompileState),
|
||||
results: make(map[string][]byte),
|
||||
errors: make(map[string]error),
|
||||
jobs: make(chan CompileJob, 128),
|
||||
}
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
go c.worker()
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CompileCache) Get(hash string) ([]byte, bool) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
if c.states[hash] != CompileReady {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return c.results[hash], true
|
||||
}
|
||||
|
||||
func (c *CompileCache) Enqueue(job CompileJob) {
|
||||
c.mu.Lock()
|
||||
|
||||
switch c.states[job.Hash] {
|
||||
case CompilePending, CompileReady:
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
c.states[job.Hash] = CompilePending
|
||||
c.mu.Unlock()
|
||||
|
||||
select {
|
||||
case c.jobs <- job:
|
||||
default:
|
||||
// Queue full. Don't block request path.
|
||||
c.mu.Lock()
|
||||
c.states[job.Hash] = CompileMissing
|
||||
c.errors[job.Hash] = errors.New("compile queue full")
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CompileCache) worker() {
|
||||
for job := range c.jobs {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
|
||||
req := CompileRequest{
|
||||
ExternSources: job.ExternSources,
|
||||
JSSources: job.JSSources,
|
||||
Defines: job.Defines,
|
||||
}
|
||||
|
||||
c.client.DebugPrintCurl(ctx, req)
|
||||
|
||||
out, err := c.client.Compile(ctx, req)
|
||||
cancel()
|
||||
|
||||
c.mu.Lock()
|
||||
if err != nil {
|
||||
c.states[job.Hash] = CompileFailed
|
||||
c.errors[job.Hash] = err
|
||||
} else {
|
||||
c.states[job.Hash] = CompileReady
|
||||
c.results[job.Hash] = out
|
||||
delete(c.errors, job.Hash)
|
||||
}
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package closure
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
endpoint string
|
||||
http *http.Client
|
||||
}
|
||||
|
||||
func NewClientFromEnv() *Client {
|
||||
endpoint := os.Getenv("CLOSURE_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = "http://closure-svc:8080/compile"
|
||||
}
|
||||
|
||||
return &Client{
|
||||
endpoint: endpoint,
|
||||
http: &http.Client{
|
||||
Timeout: 70 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Compile(ctx context.Context, reqBody CompileRequest) ([]byte, error) {
|
||||
body, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
c.endpoint,
|
||||
bytes.NewReader(body),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode/100 != 2 {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
||||
return nil, fmt.Errorf("closure failed: %s: %s", resp.Status, body)
|
||||
}
|
||||
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Client) DebugPrintCurl(ctx context.Context, reqBody CompileRequest) {
|
||||
if os.Getenv("CLOSURE_DEBUG_CURL") == "" {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := json.MarshalIndent(reqBody, "", " ")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "closure debug: marshal payload failed: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
tmpDir := os.Getenv("CLOSURE_DEBUG_DIR")
|
||||
if tmpDir == "" {
|
||||
tmpDir = os.TempDir()
|
||||
}
|
||||
|
||||
path := filepath.Join(
|
||||
tmpDir,
|
||||
fmt.Sprintf("closure-request-%d.json", time.Now().UnixNano()),
|
||||
)
|
||||
|
||||
if err := os.WriteFile(path, body, 0o600); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "closure debug: write payload failed: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintf(
|
||||
os.Stderr,
|
||||
"closure debug curl:\n curl -v -X POST %s -H 'Content-Type: application/json' --data-binary @%s\n",
|
||||
shellQuote(c.endpoint),
|
||||
shellQuote(path),
|
||||
)
|
||||
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
fmt.Fprintf(os.Stderr, "closure debug deadline: %s\n", deadline.Format(time.RFC3339Nano))
|
||||
}
|
||||
}
|
||||
|
||||
func shellQuote(s string) string {
|
||||
return strconv.Quote(s)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package closure
|
||||
|
||||
import "sync"
|
||||
|
||||
type CompileState int
|
||||
|
||||
const (
|
||||
CompileMissing CompileState = iota
|
||||
CompilePending
|
||||
CompileReady
|
||||
CompileFailed
|
||||
)
|
||||
|
||||
type CompileRequest struct {
|
||||
ExternSources []SourceInput `json:"externSources,omitempty"`
|
||||
JSSources []SourceInput `json:"jsSources"`
|
||||
Defines map[string]any `json:"defines,omitempty"`
|
||||
}
|
||||
|
||||
type SourceInput struct {
|
||||
Name string `json:"name"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
type CompileJob struct {
|
||||
Hash string
|
||||
Mode string
|
||||
|
||||
ExternSources []SourceInput
|
||||
JSSources []SourceInput
|
||||
Defines map[string]any
|
||||
}
|
||||
|
||||
type CompileCache struct {
|
||||
client *Client
|
||||
mu sync.Mutex
|
||||
states map[string]CompileState
|
||||
results map[string][]byte
|
||||
errors map[string]error
|
||||
jobs chan CompileJob
|
||||
}
|
||||
@@ -2,5 +2,5 @@ package generated
|
||||
|
||||
const (
|
||||
IMAGE_TAG = "dev"
|
||||
Timestamp = "20260610.201739"
|
||||
Timestamp = "20260611.192429"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by botan-gen; DO NOT EDIT.
|
||||
// Code generated by classmap-gen; DO NOT EDIT.
|
||||
package generated
|
||||
|
||||
import "github.com/tgckpg/botanres-go/internal/classmap"
|
||||
import "github.com/tgckpg/resolver-go/internal/classmap"
|
||||
|
||||
var ClassMap = &classmap.Map{
|
||||
Symbols: map[string]classmap.Symbol{
|
||||
@@ -84,9 +84,9 @@ var ClassMap = &classmap.Map{
|
||||
"Astro.Common.Element": {Name: "Astro.Common.Element", Kind: "class", Parent: "Astro.Common", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.Common.Element.Footer": {Name: "Astro.Common.Element.Footer", Kind: "class", Parent: "Astro.Common.Element", Imports: []string(nil), Resource: classmap.Resource{Src: "Astro/Common/Element/Footer.js", JSHash: "80f69d85c399bdc04d3b2055d1ebbe9ee77a852a", CSSHash: "c26f4238a6a4f2fc0bcbd9ac86141d12522552a4"}},
|
||||
"Astro.Mechanism": {Name: "Astro.Mechanism", Kind: "class", Parent: "Astro", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.Mechanism.CharacterCloud": {Name: "Astro.Mechanism.CharacterCloud", Kind: "class", Parent: "Astro.Mechanism", Imports: []string{"Dandelion"}, Resource: classmap.Resource{Src: "Astro/Mechanism/CharacterCloud.js", JSHash: "540a2085798928418a54e10d56bc037863ee57a9", CSSHash: "7cae98eaf8e3d5d1cd7fadaa6806ce3d65d74d92"}},
|
||||
"Astro.Mechanism.CharacterCloud": {Name: "Astro.Mechanism.CharacterCloud", Kind: "class", Parent: "Astro.Mechanism", Imports: []string{"Dandelion"}, Resource: classmap.Resource{Src: "Astro/Mechanism/CharacterCloud.js", JSHash: "281b59ca621d35d254abbddc1f088870ed61cb28", CSSHash: "7cae98eaf8e3d5d1cd7fadaa6806ce3d65d74d92"}},
|
||||
"Astro.Mechanism.CharacterCloud.create": {Name: "Astro.Mechanism.CharacterCloud.create", Kind: "method", Parent: "Astro.Mechanism.CharacterCloud", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.Mechanism.Parallax": {Name: "Astro.Mechanism.Parallax", Kind: "class", Parent: "Astro.Mechanism", Imports: []string{"System.Cycle", "Dandelion", "Dandelion.IDOMObject"}, Resource: classmap.Resource{Src: "Astro/Mechanism/Parallax.js", JSHash: "ba7b1816fc5d32edfaf5b93b9d35c7b2c297f011", CSSHash: "f8c02f4ec1be082e02c51f0b5ea39cbdd5b0e49f"}},
|
||||
"Astro.Mechanism.Parallax": {Name: "Astro.Mechanism.Parallax", Kind: "class", Parent: "Astro.Mechanism", Imports: []string{"System.Cycle", "Dandelion", "Dandelion.IDOMObject"}, Resource: classmap.Resource{Src: "Astro/Mechanism/Parallax.js", JSHash: "6ac80e95f9e8ba391668e1988fe3586987ea79d0", CSSHash: "f8c02f4ec1be082e02c51f0b5ea39cbdd5b0e49f"}},
|
||||
"Astro.Mechanism.Parallax.attach": {Name: "Astro.Mechanism.Parallax.attach", Kind: "method", Parent: "Astro.Mechanism.Parallax", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.Mechanism.Parallax.cssSlide": {Name: "Astro.Mechanism.Parallax.cssSlide", Kind: "method", Parent: "Astro.Mechanism.Parallax", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.Mechanism.Parallax.verticalSlideTo": {Name: "Astro.Mechanism.Parallax.verticalSlideTo", Kind: "method", Parent: "Astro.Mechanism.Parallax", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
@@ -117,7 +117,7 @@ var ClassMap = &classmap.Map{
|
||||
"Astro.utils.Date.prettyDay": {Name: "Astro.utils.Date.prettyDay", Kind: "method", Parent: "Astro.utils.Date", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Astro.utils.Date.smstamp": {Name: "Astro.utils.Date.smstamp", Kind: "method", Parent: "Astro.utils.Date", Imports: []string(nil), Resource: classmap.Resource{Src: "", JSHash: "", CSSHash: ""}},
|
||||
"Components": {Name: "Components", Kind: "class", Parent: "", Imports: []string(nil), Resource: classmap.Resource{Src: "Components/_this.js", JSHash: "f4cb7babe62a5cdae34d2c4ebcb55071e81da4ff", CSSHash: "1"}},
|
||||
"Components.Console": {Name: "Components.Console", Kind: "class", Parent: "Components", Imports: []string{"System.utils.Perf", "System.Cycle", "System.Cycle.TICK", "System.Global", "System.Log", "System.Debug", "Dandelion", "Dandelion.IDOMElement", "Components.DockPanel"}, Resource: classmap.Resource{Src: "Components/Console.js", JSHash: "115be15db72bd22f8222510e7bf4ce0c741028fb", CSSHash: "452f4a36e8fd7321c7d177a311047c8b71165e48"}},
|
||||
"Components.Console": {Name: "Components.Console", Kind: "class", Parent: "Components", Imports: []string{"System.utils.Perf", "System.Cycle", "System.Cycle.TICK", "System.Global", "System.Log", "System.Debug", "Dandelion", "Dandelion.IDOMElement", "Components.DockPanel"}, Resource: classmap.Resource{Src: "Components/Console.js", JSHash: "9e4ba7f921f39c85f264e416669134120d4668ea", CSSHash: "452f4a36e8fd7321c7d177a311047c8b71165e48"}},
|
||||
"Components.DockPanel": {Name: "Components.DockPanel", Kind: "class", Parent: "Components", Imports: []string{"System.Cycle", "System.utils.DataKey", "Dandelion", "Dandelion.IDOMElement"}, Resource: classmap.Resource{Src: "Components/DockPanel.js", JSHash: "c74b3081efdcbfa13300e9a49529f5664734b24e", CSSHash: "af0d91982c764ee62c46b243be68c08f2808e82b"}},
|
||||
"Components.MessageBox": {Name: "Components.MessageBox", Kind: "class", Parent: "Components", Imports: []string{"System.Cycle.Trigger", "Dandelion", "Dandelion.IDOMObject", "System.utils.EventKey", "Dandelion.CSSAnimations"}, Resource: classmap.Resource{Src: "Components/MessageBox.js", JSHash: "db0b55a5e0b1a92b9781c2b0b13817355b8e3cdf", CSSHash: "5571fa4c2e1324dcf1f2e18df8b6105cf37dfc53"}},
|
||||
"Components.Mouse": {Name: "Components.Mouse", Kind: "class", Parent: "Components", Imports: []string(nil), Resource: classmap.Resource{Src: "Components/Mouse/_this.js", JSHash: "9ec5ced53a20ea1d057e2142668e27e5df7d49f6", CSSHash: "1"}},
|
||||
@@ -379,8 +379,8 @@ var ClassMap = &classmap.Map{
|
||||
"Astro/Blog/SharedStyle.js": {Src: "Astro/Blog/SharedStyle.js", JSHash: "e946130da823a5b2d089b5b416c13b628eb1637d", CSSHash: "f8ff15304a5e38e199b713bac48e282d2bf10f45"},
|
||||
"Astro/Bootstrap.js": {Src: "Astro/Bootstrap.js", JSHash: "51bfb270eadd20b4b71372ae2d20dcf3d20575db", CSSHash: "e650f4de36f799af80ca0633d66351fb9333d620"},
|
||||
"Astro/Common/Element/Footer.js": {Src: "Astro/Common/Element/Footer.js", JSHash: "80f69d85c399bdc04d3b2055d1ebbe9ee77a852a", CSSHash: "c26f4238a6a4f2fc0bcbd9ac86141d12522552a4"},
|
||||
"Astro/Mechanism/CharacterCloud.js": {Src: "Astro/Mechanism/CharacterCloud.js", JSHash: "540a2085798928418a54e10d56bc037863ee57a9", CSSHash: "7cae98eaf8e3d5d1cd7fadaa6806ce3d65d74d92"},
|
||||
"Astro/Mechanism/Parallax.js": {Src: "Astro/Mechanism/Parallax.js", JSHash: "ba7b1816fc5d32edfaf5b93b9d35c7b2c297f011", CSSHash: "f8c02f4ec1be082e02c51f0b5ea39cbdd5b0e49f"},
|
||||
"Astro/Mechanism/CharacterCloud.js": {Src: "Astro/Mechanism/CharacterCloud.js", JSHash: "281b59ca621d35d254abbddc1f088870ed61cb28", CSSHash: "7cae98eaf8e3d5d1cd7fadaa6806ce3d65d74d92"},
|
||||
"Astro/Mechanism/Parallax.js": {Src: "Astro/Mechanism/Parallax.js", JSHash: "6ac80e95f9e8ba391668e1988fe3586987ea79d0", CSSHash: "f8c02f4ec1be082e02c51f0b5ea39cbdd5b0e49f"},
|
||||
"Astro/Penguin/Layout/MainFrame.js": {Src: "Astro/Penguin/Layout/MainFrame.js", JSHash: "b2f58fc9394745c1e47dfb95c4043f59f76acc1a", CSSHash: "e87b69ab9e725e4801065850790670d76f0a6d18"},
|
||||
"Astro/Penguin/Page/Docs.js": {Src: "Astro/Penguin/Page/Docs.js", JSHash: "02217e7fa4ebffe90b32002ef07da500ac02bf52", CSSHash: "5230a026499b9ab0f4f530f4975a9df89170c83b"},
|
||||
"Astro/Penguin/Page/_this.js": {Src: "Astro/Penguin/Page/_this.js", JSHash: "66e415e546eb6ca0b84cedfd4d3b6de67c2164f3", CSSHash: "e8afcaa8c75b241cd933cfc99a648adc42f815d7"},
|
||||
@@ -393,7 +393,7 @@ var ClassMap = &classmap.Map{
|
||||
"Astro/Starfall/_this.js": {Src: "Astro/Starfall/_this.js", JSHash: "77ca61d1ba806c3440cec5e26a100581259e1784", CSSHash: "1"},
|
||||
"Astro/utils/Date.js": {Src: "Astro/utils/Date.js", JSHash: "45221fe447d15fd943310fe9d3d3308f884b6aec", CSSHash: "1"},
|
||||
"Astro/utils/_this.js": {Src: "Astro/utils/_this.js", JSHash: "21e99449ec5c1a4b6d25164db9434132aeea5ad3", CSSHash: "1"},
|
||||
"Components/Console.js": {Src: "Components/Console.js", JSHash: "115be15db72bd22f8222510e7bf4ce0c741028fb", CSSHash: "452f4a36e8fd7321c7d177a311047c8b71165e48"},
|
||||
"Components/Console.js": {Src: "Components/Console.js", JSHash: "9e4ba7f921f39c85f264e416669134120d4668ea", CSSHash: "452f4a36e8fd7321c7d177a311047c8b71165e48"},
|
||||
"Components/DockPanel.js": {Src: "Components/DockPanel.js", JSHash: "c74b3081efdcbfa13300e9a49529f5664734b24e", CSSHash: "af0d91982c764ee62c46b243be68c08f2808e82b"},
|
||||
"Components/MessageBox.js": {Src: "Components/MessageBox.js", JSHash: "db0b55a5e0b1a92b9781c2b0b13817355b8e3cdf", CSSHash: "5571fa4c2e1324dcf1f2e18df8b6105cf37dfc53"},
|
||||
"Components/Mouse/Clipboard.js": {Src: "Components/Mouse/Clipboard.js", JSHash: "574a1ef17878beb21395a2eecfa75d046ff694e0", CSSHash: "1b7f85206ce1560ed23d3b270e093022e25d2e61"},
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Code generated by externs-gen; DO NOT EDIT.
|
||||
package generated
|
||||
|
||||
var Externs = []string{
|
||||
"externs/Astro.Blog.AstroEdit.Article.js",
|
||||
"externs/Astro.Blog.AstroEdit.IPlugin.js",
|
||||
"externs/Astro.Blog.AstroEdit.SmartInput.Definition.js",
|
||||
"externs/Astro.Blog.AstroEdit.SmartInput.ICandidateAction.js",
|
||||
"externs/Astro.Blog.AstroEdit.SmartInput.js",
|
||||
"externs/Astro.Blog.AstroEdit.Visualizer.Snippet.Model.js",
|
||||
"externs/Astro.Blog.AstroEdit.Visualizer.Snippet.js",
|
||||
"externs/Astro.Blog.AstroEdit.Visualizer.js",
|
||||
"externs/Astro.Blog.AstroEdit.js",
|
||||
"externs/Astro.Blog.Components.Bubble.js",
|
||||
"externs/Astro.Blog.Components.Calendar.js",
|
||||
"externs/Astro.Blog.Components.SiteFile.js",
|
||||
"externs/Astro.Blog.Components.js",
|
||||
"externs/Astro.Blog.Config.js",
|
||||
"externs/Astro.Blog.Events.Responsive.js",
|
||||
"externs/Astro.Blog.Events.js",
|
||||
"externs/Astro.Blog.js",
|
||||
"externs/Astro.Bootstrap.js",
|
||||
"externs/Astro.Mechanism.CharacterCloud.js",
|
||||
"externs/Astro.Mechanism.Parallax.js",
|
||||
"externs/Astro.Mechanism.js",
|
||||
"externs/Astro.js",
|
||||
"externs/Astro.utils.Date.js",
|
||||
"externs/Astro.utils.js",
|
||||
"externs/BotanEvent.js",
|
||||
"externs/BotanJS.js",
|
||||
"externs/Components.MessageBox.js",
|
||||
"externs/Components.Mouse.Clipboard.js",
|
||||
"externs/Components.Mouse.ContextMenu.js",
|
||||
"externs/Components.Mouse.js",
|
||||
"externs/Components.Vim.Actions.js",
|
||||
"externs/Components.Vim.Controls.ActionEvent.js",
|
||||
"externs/Components.Vim.Controls.js",
|
||||
"externs/Components.Vim.Cursor.js",
|
||||
"externs/Components.Vim.DateTime.js",
|
||||
"externs/Components.Vim.IAction.js",
|
||||
"externs/Components.Vim.LineBuffer.js",
|
||||
"externs/Components.Vim.LineFeeder.js",
|
||||
"externs/Components.Vim.State.History.js",
|
||||
"externs/Components.Vim.State.Marks.js",
|
||||
"externs/Components.Vim.State.Recorder.js",
|
||||
"externs/Components.Vim.State.Registers.js",
|
||||
"externs/Components.Vim.State.Stack.js",
|
||||
"externs/Components.Vim.State.js",
|
||||
"externs/Components.Vim.StatusBar.js",
|
||||
"externs/Components.Vim.Syntax.Analyzer.js",
|
||||
"externs/Components.Vim.Syntax.TokenMatch.js",
|
||||
"externs/Components.Vim.Syntax.Word.js",
|
||||
"externs/Components.Vim.Syntax.js",
|
||||
"externs/Components.Vim.VimArea.js",
|
||||
"externs/Components.Vim.js",
|
||||
"externs/Components.js",
|
||||
"externs/Dandelion.CSSAnimations.MovieClip.js",
|
||||
"externs/Dandelion.CSSAnimations.js",
|
||||
"externs/Dandelion.IDOMElement.js",
|
||||
"externs/Dandelion.IDOMObject.js",
|
||||
"externs/Dandelion.js",
|
||||
"externs/Libraries.SyntaxHighLighter.Brush.js",
|
||||
"externs/Libraries.SyntaxHighLighter.js",
|
||||
"externs/Libraries.js",
|
||||
"externs/System.Compression.Zlib.js",
|
||||
"externs/System.Compression.js",
|
||||
"externs/System.Cycle.Trigger.js",
|
||||
"externs/System.Cycle.js",
|
||||
"externs/System.Debug.js",
|
||||
"externs/System.Encoding.Base64.js",
|
||||
"externs/System.Encoding.Utf8.js",
|
||||
"externs/System.Encoding.js",
|
||||
"externs/System.Global.js",
|
||||
"externs/System.Log.js",
|
||||
"externs/System.Net.js",
|
||||
"externs/System.Policy.js",
|
||||
"externs/System.Tick.js",
|
||||
"externs/System.js",
|
||||
"externs/System.utils.DataKey.js",
|
||||
"externs/System.utils.EventKey.js",
|
||||
"externs/System.utils.IKey.js",
|
||||
"externs/System.utils.Perf.js",
|
||||
"externs/System.utils.js",
|
||||
"externs/_3rdParty_.Recaptcha.js",
|
||||
"externs/_3rdParty_.js",
|
||||
"externs/_AstConf_.Article.js",
|
||||
"externs/_AstConf_.AstroEdit.js",
|
||||
"externs/_AstConf_.Comment.js",
|
||||
"externs/_AstConf_.Control.js",
|
||||
"externs/_AstConf_.Login.js",
|
||||
"externs/_AstConf_.Notification.js",
|
||||
"externs/_AstConf_.SiteFile.js",
|
||||
"externs/_AstConf_.UserInfo.js",
|
||||
"externs/_AstConf_.js",
|
||||
"externs/_AstJson_.AJaxGetArticle.js",
|
||||
"externs/_AstJson_.AJaxGetDrafts.js",
|
||||
"externs/_AstJson_.AJaxGetFiles.Request.js",
|
||||
"externs/_AstJson_.AJaxGetFiles.js",
|
||||
"externs/_AstJson_.AJaxGetNotis.js",
|
||||
"externs/_AstJson_.SiteFile.js",
|
||||
"externs/_AstJson_.js",
|
||||
"externs/_AstXObject_.AstroEdit.Visualizer.Snippet.Code.js",
|
||||
"externs/_AstXObject_.AstroEdit.Visualizer.Snippet.Spoiler.js",
|
||||
"externs/_AstXObject_.AstroEdit.Visualizer.Snippet.js",
|
||||
"externs/_AstXObject_.AstroEdit.Visualizer.js",
|
||||
"externs/_AstXObject_.AstroEdit.js",
|
||||
"externs/_AstXObject_.js",
|
||||
}
|
||||
@@ -14,8 +14,10 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/tgckpg/botanres-go/internal/classmap"
|
||||
"github.com/tgckpg/resolver-go/internal/classmap"
|
||||
"github.com/tgckpg/resolver-go/internal/closure"
|
||||
)
|
||||
|
||||
type OutputMode string
|
||||
@@ -38,6 +40,9 @@ type Result struct {
|
||||
type Resolver struct {
|
||||
Root string
|
||||
Map *classmap.Map
|
||||
|
||||
externMu sync.RWMutex
|
||||
externCache map[string]closure.SourceInput
|
||||
}
|
||||
|
||||
func New(root string, m *classmap.Map) (*Resolver, error) {
|
||||
@@ -45,7 +50,11 @@ func New(root string, m *classmap.Map) (*Resolver, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Resolver{Root: root, Map: m}, nil
|
||||
return &Resolver{
|
||||
Root: root,
|
||||
Map: m,
|
||||
externCache: make(map[string]closure.SourceInput),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resolver) ResolveRequest(code string, mode OutputMode, excludes []string) (Result, error) {
|
||||
@@ -242,6 +251,55 @@ func (r *Resolver) MergeCSS(files []classmap.Resource) ([]byte, string, error) {
|
||||
return b.Bytes(), hashList(files, "css"), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) GetExterns(files []string) ([]closure.SourceInput, error) {
|
||||
sources := make([]closure.SourceInput, 0, len(files))
|
||||
|
||||
for _, f := range files {
|
||||
src, ok, err := r.getExtern(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
sources = append(sources, src)
|
||||
}
|
||||
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
func (r *Resolver) getExtern(f string) (closure.SourceInput, bool, error) {
|
||||
// Fast path: read cache.
|
||||
r.externMu.RLock()
|
||||
src, ok := r.externCache[f]
|
||||
r.externMu.RUnlock()
|
||||
if ok {
|
||||
return src, true, nil
|
||||
}
|
||||
|
||||
// Slow path: read file.
|
||||
b, err := os.ReadFile(filepath.Join(r.Root, filepath.FromSlash(f)))
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return closure.SourceInput{}, false, nil
|
||||
}
|
||||
return closure.SourceInput{}, false, err
|
||||
}
|
||||
|
||||
src = closure.SourceInput{
|
||||
Name: f,
|
||||
Source: string(b),
|
||||
}
|
||||
|
||||
// Store cache.
|
||||
r.externMu.Lock()
|
||||
r.externCache[f] = src
|
||||
r.externMu.Unlock()
|
||||
|
||||
return src, true, nil
|
||||
}
|
||||
|
||||
func DecodeRequest(code string) ([]string, error) {
|
||||
sep := "/"
|
||||
decoded := code
|
||||
|
||||
Reference in New Issue
Block a user