@bookshop/hugo-engine 3.3.2 → 3.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nyc_output/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +0 -0
- package/.nyc_output/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json} +0 -0
- package/.nyc_output/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +0 -0
- package/.nyc_output/{6aec5420-0b83-4260-b300-4d595dfd0660.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +0 -0
- package/.nyc_output/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +0 -0
- package/.nyc_output/processinfo/{396c364e-fec4-4f27-9ff2-8b236061ef8f.json → 0f70a16f-6a79-48c7-8b16-3b4665e247b2.json} +1 -1
- package/.nyc_output/processinfo/6285d5fa-be3d-49e4-8f2f-82157d95dcd8.json +1 -0
- package/.nyc_output/processinfo/{4ef43740-059b-4329-96cd-0643fd8fe8d8.json → 8b5e1314-6e86-4197-a3ae-3c40e4c2f39e.json} +1 -1
- package/.nyc_output/processinfo/{656275f4-66d6-4d27-bfab-c2f7a3087670.json → c5490eb0-70c0-468f-a43f-e58c75dd34c8.json} +1 -1
- package/.nyc_output/processinfo/{874bd79b-45da-4726-9afc-1f6cab44be1f.json → ee1a9bec-d318-4aea-af93-7269debcf6df.json} +1 -1
- package/.nyc_output/processinfo/index.json +1 -1
- package/bookshop-hugo-templates/bookshop.html +56 -0
- package/bookshop-hugo-templates/bookshop_bindings.html +29 -0
- package/bookshop-hugo-templates/bookshop_component_browser.html +30 -0
- package/bookshop-hugo-templates/bookshop_partial.html +42 -0
- package/bookshop-hugo-templates/bookshop_scss.html +9 -0
- package/bookshop-hugo-templates/errors/bad_bookshop_tag.html +39 -0
- package/bookshop-hugo-templates/errors/err.html +6 -0
- package/bookshop-hugo-templates/helpers/component.html +25 -0
- package/bookshop-hugo-templates/helpers/component_key.html +11 -0
- package/bookshop-hugo-templates/helpers/partial.html +25 -0
- package/bookshop-hugo-templates/helpers/partial_key.html +9 -0
- package/full-hugo-renderer/build.sh +34 -0
- package/full-hugo-renderer/go.mod +87 -0
- package/{hugo-renderer → full-hugo-renderer}/go.sum +204 -12
- package/full-hugo-renderer/hugo_renderer.wasm +0 -0
- package/full-hugo-renderer/hugo_renderer.wasm.gz +0 -0
- package/full-hugo-renderer/main.go +215 -0
- package/{hugo-renderer → full-hugo-renderer}/wasm_exec.js +6 -2
- package/lib/builder.js +2 -2
- package/lib/engine.js +109 -42
- package/lib/hugoIdentifierParser.js +5 -0
- package/lib/translateTextTemplate.js +3 -0
- package/lib/translateTextTemplate.test.js +22 -16
- package/package.json +4 -4
- package/.nyc_output/processinfo/6aec5420-0b83-4260-b300-4d595dfd0660.json +0 -1
- package/hugo-renderer/build.sh +0 -66
- package/hugo-renderer/deps/bookshop_modified_deps.go +0 -6
- package/hugo-renderer/go.mod +0 -19
- package/hugo-renderer/helpers/bookshop_modified_content.go +0 -98
- package/hugo-renderer/helpers/bookshop_modified_general.go +0 -33
- package/hugo-renderer/helpers/emoji.go +0 -96
- package/hugo-renderer/hugo_renderer.wasm +0 -0
- package/hugo-renderer/hugo_renderer.wasm.gz +0 -0
- package/hugo-renderer/main.go +0 -42
- package/hugo-renderer/tpl/bookshop_engine/bookshop_func_importer.go +0 -35
- package/hugo-renderer/tpl/bookshop_engine/bookshop_render.go +0 -64
- package/hugo-renderer/tpl/bookshop_library/bookshop_components.go +0 -129
- package/hugo-renderer/tpl/bookshop_library/bookshop_data.go +0 -53
- package/hugo-renderer/tpl/cast/cast.go +0 -63
- package/hugo-renderer/tpl/cast/init.go +0 -57
- package/hugo-renderer/tpl/collections/append.go +0 -37
- package/hugo-renderer/tpl/collections/apply.go +0 -131
- package/hugo-renderer/tpl/collections/collections.go +0 -768
- package/hugo-renderer/tpl/collections/complement.go +0 -55
- package/hugo-renderer/tpl/collections/index.go +0 -133
- package/hugo-renderer/tpl/collections/init.go +0 -214
- package/hugo-renderer/tpl/collections/merge.go +0 -126
- package/hugo-renderer/tpl/collections/reflect_helpers.go +0 -216
- package/hugo-renderer/tpl/collections/sort.go +0 -183
- package/hugo-renderer/tpl/collections/symdiff.go +0 -68
- package/hugo-renderer/tpl/collections/where.go +0 -517
- package/hugo-renderer/tpl/compare/compare.go +0 -324
- package/hugo-renderer/tpl/compare/init.go +0 -85
- package/hugo-renderer/tpl/crypto/crypto.go +0 -109
- package/hugo-renderer/tpl/crypto/init.go +0 -65
- package/hugo-renderer/tpl/debug/debug.go +0 -40
- package/hugo-renderer/tpl/debug/init.go +0 -45
- package/hugo-renderer/tpl/encoding/encoding.go +0 -90
- package/hugo-renderer/tpl/encoding/init.go +0 -59
- package/hugo-renderer/tpl/fmt/fmt.go +0 -66
- package/hugo-renderer/tpl/fmt/init.go +0 -77
- package/hugo-renderer/tpl/inflect/inflect.go +0 -79
- package/hugo-renderer/tpl/inflect/init.go +0 -60
- package/hugo-renderer/tpl/internal/bookshop_modified_templatefuncsRegistry.go +0 -88
- package/hugo-renderer/tpl/math/init.go +0 -134
- package/hugo-renderer/tpl/math/math.go +0 -164
- package/hugo-renderer/tpl/math/round.go +0 -61
- package/hugo-renderer/tpl/partials/init.go +0 -55
- package/hugo-renderer/tpl/partials/partials.go +0 -88
- package/hugo-renderer/tpl/path/init.go +0 -60
- package/hugo-renderer/tpl/path/path.go +0 -159
- package/hugo-renderer/tpl/reflect/init.go +0 -51
- package/hugo-renderer/tpl/reflect/reflect.go +0 -36
- package/hugo-renderer/tpl/safe/init.go +0 -80
- package/hugo-renderer/tpl/safe/safe.go +0 -72
- package/hugo-renderer/tpl/site/bookshop_site.go +0 -67
- package/hugo-renderer/tpl/site/init.go +0 -41
- package/hugo-renderer/tpl/strings/init.go +0 -229
- package/hugo-renderer/tpl/strings/regexp.go +0 -125
- package/hugo-renderer/tpl/strings/strings.go +0 -500
- package/hugo-renderer/tpl/strings/truncate.go +0 -157
- package/hugo-renderer/tpl/transform/bookshop_unmarshal.go +0 -39
- package/hugo-renderer/tpl/transform/init.go +0 -113
- package/hugo-renderer/tpl/transform/transform.go +0 -116
- package/hugo-renderer/update-from-hugo.sh +0 -19
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Copyright 2015 The Hugo Authors. All rights reserved.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
|
|
14
|
+
package main
|
|
15
|
+
|
|
16
|
+
import (
|
|
17
|
+
"encoding/json"
|
|
18
|
+
"fmt"
|
|
19
|
+
"io/ioutil"
|
|
20
|
+
"log"
|
|
21
|
+
"path/filepath"
|
|
22
|
+
"syscall/js"
|
|
23
|
+
|
|
24
|
+
"github.com/fsnotify/fsnotify"
|
|
25
|
+
"github.com/gohugoio/hugo/config"
|
|
26
|
+
"github.com/gohugoio/hugo/deps"
|
|
27
|
+
"github.com/gohugoio/hugo/hugofs"
|
|
28
|
+
"github.com/gohugoio/hugo/hugolib"
|
|
29
|
+
"github.com/spf13/afero"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
type bookshopSiteBuilder struct {
|
|
33
|
+
Cfg config.Provider
|
|
34
|
+
Fs *hugofs.Fs
|
|
35
|
+
Sites *hugolib.HugoSites
|
|
36
|
+
changedFiles []string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Load whatever source config file we have previously written to disk
|
|
40
|
+
func (builder *bookshopSiteBuilder) LoadConfig() error {
|
|
41
|
+
cfg, _, err := hugolib.LoadConfig(hugolib.ConfigSourceDescriptor{
|
|
42
|
+
WorkingDir: "",
|
|
43
|
+
Fs: builder.Fs.Source,
|
|
44
|
+
Filename: "config.toml",
|
|
45
|
+
}, func(cfg config.Provider) error {
|
|
46
|
+
return nil
|
|
47
|
+
})
|
|
48
|
+
if err != nil {
|
|
49
|
+
return err
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
builder.Cfg = cfg
|
|
53
|
+
|
|
54
|
+
return nil
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Create our Hugo sites
|
|
58
|
+
// TODO: I don't know how the lang aspects of Hugo
|
|
59
|
+
// will interact with Hugo.
|
|
60
|
+
func (builder *bookshopSiteBuilder) CreateSites() error {
|
|
61
|
+
if err := builder.LoadConfig(); err != nil {
|
|
62
|
+
fmt.Println(fmt.Sprintf("failed to load config: %s", err))
|
|
63
|
+
return fmt.Errorf("failed to load config: %w", err)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
builder.Fs.PublishDir = hugofs.NewCreateCountingFs(builder.Fs.PublishDir)
|
|
67
|
+
|
|
68
|
+
sites, err := hugolib.NewHugoSites(deps.DepsCfg{
|
|
69
|
+
Fs: builder.Fs,
|
|
70
|
+
Cfg: builder.Cfg,
|
|
71
|
+
Running: true,
|
|
72
|
+
})
|
|
73
|
+
if err != nil {
|
|
74
|
+
fmt.Println(fmt.Sprintf("failed to create sites: %s", err))
|
|
75
|
+
return fmt.Errorf("failed to create sites: %w", err)
|
|
76
|
+
}
|
|
77
|
+
builder.Sites = sites
|
|
78
|
+
|
|
79
|
+
return nil
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Runs a standard Hugo build into our in-memory "public" directory
|
|
83
|
+
func (builder *bookshopSiteBuilder) build(cfg hugolib.BuildCfg) error {
|
|
84
|
+
if builder.Sites == nil {
|
|
85
|
+
builder.CreateSites()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
err := builder.Sites.Build(cfg, builder.changeEvents()...)
|
|
89
|
+
|
|
90
|
+
if err == nil {
|
|
91
|
+
logErrorCount := builder.Sites.NumLogErrors()
|
|
92
|
+
if logErrorCount > 0 {
|
|
93
|
+
err = fmt.Errorf("logged %d errors", logErrorCount)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if err != nil {
|
|
97
|
+
fmt.Errorf("Build failed: %s", err)
|
|
98
|
+
fmt.Println(fmt.Sprintf("Build failed: %s", err))
|
|
99
|
+
return err
|
|
100
|
+
}
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Writes content to the given file path in the in-memory filesystem
|
|
105
|
+
func (builder *bookshopSiteBuilder) writeFile(filename, content string) {
|
|
106
|
+
if err := afero.WriteFile(builder.Fs.Source, filepath.FromSlash(filename), []byte(content), 0755); err != nil {
|
|
107
|
+
fmt.Println(fmt.Sprintf("Failed to write file: %s", err))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
builder.changedFiles = append(builder.changedFiles, filename)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Reads content from the given file path in the in-memory filesystem
|
|
114
|
+
func (builder *bookshopSiteBuilder) readFile(filename string) string {
|
|
115
|
+
b, err := afero.ReadFile(builder.Fs.Source, filepath.Clean(filename))
|
|
116
|
+
if err != nil {
|
|
117
|
+
fmt.Println(fmt.Sprintf("Failed to read file: %s", err))
|
|
118
|
+
}
|
|
119
|
+
return string(b)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Helper method to list out any files in our virtual fs
|
|
123
|
+
func (builder *bookshopSiteBuilder) debugDir(dir string) {
|
|
124
|
+
files, err := afero.ReadDir(builder.Fs.Source, dir)
|
|
125
|
+
if err == nil {
|
|
126
|
+
for _, file := range files {
|
|
127
|
+
fmt.Println(fmt.Sprintf("%s > %+v", dir, file.Name()))
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
fmt.Println(fmt.Sprintf("Error debugging directory: %+v", err))
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
func (builder *bookshopSiteBuilder) changeEvents() []fsnotify.Event {
|
|
135
|
+
var events []fsnotify.Event
|
|
136
|
+
|
|
137
|
+
for _, v := range builder.changedFiles {
|
|
138
|
+
events = append(events, fsnotify.Event{
|
|
139
|
+
Name: v,
|
|
140
|
+
Op: fsnotify.Write,
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return events
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
var builder bookshopSiteBuilder
|
|
148
|
+
var build_config hugolib.BuildCfg
|
|
149
|
+
|
|
150
|
+
func main() {
|
|
151
|
+
fs_config := config.NewWithTestDefaults()
|
|
152
|
+
fs := hugofs.NewMem(fs_config)
|
|
153
|
+
builder = bookshopSiteBuilder{Fs: fs}
|
|
154
|
+
build_config = hugolib.BuildCfg{
|
|
155
|
+
NoBuildLock: true,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
log.SetOutput(ioutil.Discard)
|
|
159
|
+
|
|
160
|
+
c := make(chan struct{}, 0)
|
|
161
|
+
js.Global().Set("initHugoConfig", js.FuncOf(initHugoConfig))
|
|
162
|
+
js.Global().Set("writeHugoFiles", js.FuncOf(writeHugoFiles))
|
|
163
|
+
js.Global().Set("readHugoFiles", js.FuncOf(readHugoFiles))
|
|
164
|
+
js.Global().Set("buildHugo", js.FuncOf(buildHugo))
|
|
165
|
+
<-c
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
func initHugoConfig(this js.Value, args []js.Value) interface{} {
|
|
169
|
+
if err := builder.LoadConfig(); err != nil {
|
|
170
|
+
fmt.Println(fmt.Sprintf("failed to load config: %s", err))
|
|
171
|
+
return fmt.Errorf("failed to load config: %w", err)
|
|
172
|
+
}
|
|
173
|
+
if err := builder.CreateSites(); err != nil {
|
|
174
|
+
fmt.Println(fmt.Sprintf("failed to create sites: %s", err))
|
|
175
|
+
return fmt.Errorf("failed to create sites: %w", err)
|
|
176
|
+
}
|
|
177
|
+
return nil
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
func writeHugoFiles(this js.Value, args []js.Value) interface{} {
|
|
181
|
+
var writeFiles map[string]string
|
|
182
|
+
err := json.Unmarshal([]byte(args[0].String()), &writeFiles)
|
|
183
|
+
if err != nil {
|
|
184
|
+
fmt.Println(fmt.Sprintf("Bad json: %+v", err))
|
|
185
|
+
return nil
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
for file_name, file_contents := range writeFiles {
|
|
189
|
+
builder.writeFile(file_name, file_contents)
|
|
190
|
+
}
|
|
191
|
+
return nil
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func readHugoFiles(this js.Value, args []js.Value) interface{} {
|
|
195
|
+
var readFiles []string
|
|
196
|
+
err := json.Unmarshal([]byte(args[0].String()), &readFiles)
|
|
197
|
+
if err != nil {
|
|
198
|
+
fmt.Println(fmt.Sprintf("Bad json: %+v", err))
|
|
199
|
+
return nil
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fileContents := make(map[string]interface{})
|
|
203
|
+
for _, file_name := range readFiles {
|
|
204
|
+
fileContents[file_name] = builder.readFile(file_name)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return js.ValueOf(fileContents)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
func buildHugo(this js.Value, args []js.Value) interface{} {
|
|
211
|
+
if err := builder.build(build_config); err != nil {
|
|
212
|
+
return fmt.Sprintf("Build error: %+v", err)
|
|
213
|
+
}
|
|
214
|
+
return nil
|
|
215
|
+
}
|
|
@@ -48,7 +48,10 @@
|
|
|
48
48
|
outputBuf += decoder.decode(buf);
|
|
49
49
|
const nl = outputBuf.lastIndexOf("\n");
|
|
50
50
|
if (nl != -1) {
|
|
51
|
-
|
|
51
|
+
// Disable all logs from the WASM side
|
|
52
|
+
if (window.log_hugo_wasm) {
|
|
53
|
+
console.log(outputBuf.substr(0, nl));
|
|
54
|
+
}
|
|
52
55
|
outputBuf = outputBuf.substr(nl + 1);
|
|
53
56
|
}
|
|
54
57
|
return buf.length;
|
|
@@ -499,7 +502,8 @@
|
|
|
499
502
|
},
|
|
500
503
|
|
|
501
504
|
"debug": (value) => {
|
|
502
|
-
|
|
505
|
+
// Disable all logs from the WASM side
|
|
506
|
+
// console.log(value);
|
|
503
507
|
},
|
|
504
508
|
}
|
|
505
509
|
};
|
package/lib/builder.js
CHANGED
|
@@ -9,12 +9,12 @@ export const extensions = [".hugo.html"];
|
|
|
9
9
|
export const esbuildConfigFn = (esbuildConfig, options) => {
|
|
10
10
|
esbuildConfig.loader = {
|
|
11
11
|
...esbuildConfig.loader,
|
|
12
|
+
".html": "text",
|
|
12
13
|
".hugo.html": "text",
|
|
13
|
-
".wasm": options?.hosted ? "file" : "binary",
|
|
14
14
|
".wasm.gz": options?.hosted ? "file" : "binary",
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
const wasm_exec_banner = fs.readFileSync(path.join(__dirname, "../hugo-renderer/wasm_exec.js"));
|
|
17
|
+
const wasm_exec_banner = fs.readFileSync(path.join(__dirname, "../full-hugo-renderer/wasm_exec.js"));
|
|
18
18
|
esbuildConfig.banner = {
|
|
19
19
|
...esbuildConfig.banner,
|
|
20
20
|
js: (esbuildConfig.js ?? "") + wasm_exec_banner
|
package/lib/engine.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import compressedHugoWasm from "../hugo-renderer/hugo_renderer.wasm.gz";
|
|
1
|
+
import compressedHugoWasm from "../full-hugo-renderer/hugo_renderer.wasm.gz";
|
|
3
2
|
import { gunzipSync } from 'fflate';
|
|
4
3
|
import translateTextTemplate from './translateTextTemplate.js';
|
|
5
4
|
import { IdentifierParser } from './hugoIdentifierParser.js';
|
|
@@ -33,8 +32,24 @@ export class Engine {
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
async initializeHugo() {
|
|
35
|
+
const templates = {
|
|
36
|
+
"layouts/partials/bookshop.html": (await import("../bookshop-hugo-templates/bookshop.html")).default,
|
|
37
|
+
"layouts/partials/bookshop_scss.html": (await import("../bookshop-hugo-templates/bookshop_scss.html")).default,
|
|
38
|
+
"layouts/partials/bookshop_partial.html": (await import("../bookshop-hugo-templates/bookshop_partial.html")).default,
|
|
39
|
+
"layouts/partials/bookshop_component_browser.html": (await import("../bookshop-hugo-templates/bookshop_component_browser.html")).default,
|
|
40
|
+
"layouts/partials/bookshop_bindings.html": (await import("../bookshop-hugo-templates/bookshop_bindings.html")).default,
|
|
41
|
+
"layouts/partials/_bookshop/helpers/component.html": (await import("../bookshop-hugo-templates/helpers/component.html")).default,
|
|
42
|
+
"layouts/partials/_bookshop/helpers/component_key.html": (await import("../bookshop-hugo-templates/helpers/component_key.html")).default,
|
|
43
|
+
"layouts/partials/_bookshop/helpers/partial.html": (await import("../bookshop-hugo-templates/helpers/partial.html")).default,
|
|
44
|
+
"layouts/partials/_bookshop/helpers/partial_key.html": (await import("../bookshop-hugo-templates/helpers/partial_key.html")).default,
|
|
45
|
+
"layouts/partials/_bookshop/errors/bad_bookshop_tag.html": (await import("../bookshop-hugo-templates/errors/bad_bookshop_tag.html")).default,
|
|
46
|
+
"layouts/partials/_bookshop/errors/err.html": (await import("../bookshop-hugo-templates/errors/err.html")).default,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
templates["config.toml"] = "params.env_bookshop_live = true";
|
|
50
|
+
|
|
36
51
|
// When this script is run locally, the hugo wasm is loaded as binary rather than output as a file.
|
|
37
|
-
if (
|
|
52
|
+
if (compressedHugoWasm?.constructor === Uint8Array) {
|
|
38
53
|
await this.initializeInlineHugo();
|
|
39
54
|
} else {
|
|
40
55
|
await this.initializeLocalCompressedHugo();
|
|
@@ -43,12 +58,11 @@ export class Engine {
|
|
|
43
58
|
// TODO: Tidy
|
|
44
59
|
const mappedFiles = {};
|
|
45
60
|
for (const file of Object.entries(this.files)) {
|
|
46
|
-
mappedFiles[file[0]] = {
|
|
47
|
-
contents: translateTextTemplate(file[1], {})
|
|
48
|
-
}
|
|
61
|
+
mappedFiles[`layouts/partials/bookshop/${file[0]}`] = translateTextTemplate(file[1], {});
|
|
49
62
|
}
|
|
50
63
|
|
|
51
|
-
const
|
|
64
|
+
const componentSuccess = window["writeHugoFiles"](JSON.stringify(mappedFiles));
|
|
65
|
+
const templateSuccess = window["writeHugoFiles"](JSON.stringify(templates));
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
async initializeLocalCompressedHugo() {
|
|
@@ -66,28 +80,25 @@ export class Engine {
|
|
|
66
80
|
const compressedResult = await WebAssembly.instantiate(renderer, go.importObject);
|
|
67
81
|
go.run(compressedResult.instance);
|
|
68
82
|
} catch (e) {
|
|
69
|
-
|
|
83
|
+
console.error("Couldn't load the local compressed Hugo WASM");
|
|
84
|
+
console.error(e);
|
|
70
85
|
}
|
|
71
86
|
}
|
|
72
87
|
|
|
73
|
-
async
|
|
88
|
+
async initializeInlineHugo() {
|
|
74
89
|
const go = new Go();
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const result = await WebAssembly.instantiate(buffer, go.importObject);
|
|
90
|
+
const buffer = compressedHugoWasm.buffer;
|
|
91
|
+
const renderer = gunzipSync(new Uint8Array(buffer));
|
|
92
|
+
const result = await WebAssembly.instantiate(renderer, go.importObject);
|
|
79
93
|
go.run(result.instance);
|
|
80
94
|
}
|
|
81
95
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const buffer = hugoWasm.buffer;
|
|
85
|
-
const result = await WebAssembly.instantiate(buffer, go.importObject);
|
|
86
|
-
go.run(result.instance);
|
|
96
|
+
getSharedKey(name) {
|
|
97
|
+
return `shared/hugo/${name}.hugo.html`;
|
|
87
98
|
}
|
|
88
99
|
|
|
89
100
|
getShared(name) {
|
|
90
|
-
const key =
|
|
101
|
+
const key = this.getSharedKey(name);
|
|
91
102
|
return this.files?.[key];
|
|
92
103
|
}
|
|
93
104
|
|
|
@@ -106,9 +117,14 @@ export class Engine {
|
|
|
106
117
|
return !!this.files?.[key];
|
|
107
118
|
}
|
|
108
119
|
|
|
120
|
+
hasShared(name) {
|
|
121
|
+
const key = this.getSharedKey(name);
|
|
122
|
+
return !!this.files?.[key];
|
|
123
|
+
}
|
|
124
|
+
|
|
109
125
|
resolveComponentType(name) {
|
|
110
|
-
if (this.
|
|
111
|
-
if (this.
|
|
126
|
+
if (this.hasComponent(name)) return 'component';
|
|
127
|
+
if (this.hasShared(name)) return 'shared';
|
|
112
128
|
return false;
|
|
113
129
|
}
|
|
114
130
|
|
|
@@ -119,38 +135,58 @@ export class Engine {
|
|
|
119
135
|
}
|
|
120
136
|
|
|
121
137
|
async storeMeta(meta = {}) {
|
|
122
|
-
while (!window.
|
|
138
|
+
while (!window.writeHugoFiles) {
|
|
123
139
|
await sleep(100);
|
|
124
140
|
};
|
|
125
|
-
window.
|
|
141
|
+
window.writeHugoFiles(JSON.stringify({
|
|
142
|
+
"config.toml": [
|
|
143
|
+
meta.baseurl ? `baseURL = ${meta.baseurl}` : "",
|
|
144
|
+
meta.copyright ? `copyright = ${meta.copyright}` : "",
|
|
145
|
+
meta.title ? `title = ${meta.title}` : "",
|
|
146
|
+
"params.env_bookshop_live = true"
|
|
147
|
+
].join('\n')
|
|
148
|
+
}));
|
|
149
|
+
const err = window.initHugoConfig();
|
|
150
|
+
if (err) {
|
|
151
|
+
console.error(err);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// window.loadHugoBookshopMeta(JSON.stringify(meta));
|
|
126
155
|
}
|
|
127
156
|
|
|
128
157
|
async storeInfo(info = {}) {
|
|
129
|
-
while (!window.
|
|
158
|
+
while (!window.writeHugoFiles) {
|
|
130
159
|
await sleep(100);
|
|
131
160
|
};
|
|
132
|
-
|
|
161
|
+
|
|
162
|
+
const data = info?.data;
|
|
163
|
+
if (!data || typeof data !== "object") return;
|
|
164
|
+
const files = {};
|
|
165
|
+
for (const [file, contents] of Object.entries(data)) {
|
|
166
|
+
files[`data/${file}.json`] = JSON.stringify(contents);
|
|
167
|
+
}
|
|
168
|
+
window.writeHugoFiles(JSON.stringify(files));
|
|
133
169
|
}
|
|
134
170
|
|
|
135
171
|
async render(target, name, props, globals, logger) {
|
|
136
|
-
while (!window.
|
|
172
|
+
while (!window.buildHugo) {
|
|
137
173
|
logger?.log?.(`Waiting for the Hugo WASM to be available...`);
|
|
138
174
|
await sleep(100);
|
|
139
175
|
};
|
|
140
176
|
|
|
141
|
-
let
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
|
|
177
|
+
let writeFiles = {};
|
|
178
|
+
|
|
179
|
+
if (this.hasComponent(name)) {
|
|
180
|
+
writeFiles["layouts/index.html"] = `{{ partial "bookshop" (slice "${name}" .Params.component) }}`
|
|
181
|
+
} else if (this.hasShared(name)) {
|
|
182
|
+
writeFiles["layouts/index.html"] = `{{ partial "bookshop_partial" (slice "${name}" .Params.component) }}`
|
|
183
|
+
} else {
|
|
145
184
|
console.warn(`[hugo-engine] No component found for ${name}`);
|
|
146
185
|
return "";
|
|
147
186
|
}
|
|
148
|
-
logger?.log?.(`Going to render ${name}, with
|
|
149
|
-
logger?.log?.(
|
|
150
|
-
|
|
151
|
-
source = translateTextTemplate(source, {});
|
|
152
|
-
logger?.log?.(`Rewritten the template for ${name} to:`);
|
|
153
|
-
logger?.log?.(source);
|
|
187
|
+
logger?.log?.(`Going to render ${name}, with layout:`);
|
|
188
|
+
logger?.log?.(writeFiles["layouts/index.html"]);
|
|
189
|
+
|
|
154
190
|
if (!globals || typeof globals !== "object") globals = {};
|
|
155
191
|
props = {
|
|
156
192
|
...globals, ...props,
|
|
@@ -159,7 +195,25 @@ export class Engine {
|
|
|
159
195
|
|
|
160
196
|
// If we have assigned a root scope we need to pass that in as the context
|
|
161
197
|
if (props["."]) props = props["."];
|
|
162
|
-
|
|
198
|
+
writeFiles["content/_index.md"] = JSON.stringify({
|
|
199
|
+
component: props
|
|
200
|
+
}, null, 2) + "\n";
|
|
201
|
+
window.writeHugoFiles(JSON.stringify(writeFiles));
|
|
202
|
+
|
|
203
|
+
const buildResult = window.buildHugo();
|
|
204
|
+
if (buildResult) {
|
|
205
|
+
console.error(buildResult);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const output = window.readHugoFiles(JSON.stringify([
|
|
210
|
+
"public/index.html"
|
|
211
|
+
]));
|
|
212
|
+
|
|
213
|
+
target.innerHTML = output["public/index.html"];
|
|
214
|
+
return;
|
|
215
|
+
|
|
216
|
+
const outputs = window.renderHugo(source, JSON.stringify(props));
|
|
163
217
|
if (/BKSHERR/.test(output)) {
|
|
164
218
|
logger?.log?.(`Failed to render ${output}`);
|
|
165
219
|
console.error(output);
|
|
@@ -171,7 +225,7 @@ export class Engine {
|
|
|
171
225
|
}
|
|
172
226
|
|
|
173
227
|
async eval(str, props = [{}]) {
|
|
174
|
-
while (!window.
|
|
228
|
+
while (!window.buildHugo) await sleep(10);
|
|
175
229
|
let props_obj = props.reduce((a, b) => { return { ...a, ...b } });
|
|
176
230
|
|
|
177
231
|
// We're capable of looking up a simple variable
|
|
@@ -190,15 +244,28 @@ export class Engine {
|
|
|
190
244
|
|
|
191
245
|
const assignments = Object.entries(props_obj).filter(([key]) => key.startsWith('$')).map(([key, value]) => {
|
|
192
246
|
if (Array.isArray(value)) {
|
|
193
|
-
return `{{ ${key} := index ( \`{"a": ${JSON.stringify(value)}}\` | transform.
|
|
247
|
+
return `{{ ${key} := index ( \`{"a": ${JSON.stringify(value)}}\` | transform.Unmarshal ) "a" }}`
|
|
194
248
|
} else if (typeof value === 'object') {
|
|
195
|
-
return `{{ ${key} := \`${JSON.stringify(value)}\` | transform.
|
|
249
|
+
return `{{ ${key} := \`${JSON.stringify(value)}\` | transform.Unmarshal }}`
|
|
196
250
|
} else {
|
|
197
251
|
return `{{ ${key} := ${JSON.stringify(value)} }}`
|
|
198
252
|
}
|
|
199
253
|
}).join('');
|
|
200
|
-
const eval_str =
|
|
201
|
-
|
|
254
|
+
const eval_str = `{{ with .Params.props }}${assignments}{{ jsonify (${str}) }}{{ end }}`;
|
|
255
|
+
window.writeHugoFiles(JSON.stringify({
|
|
256
|
+
"layouts/index.html": eval_str,
|
|
257
|
+
"content/_index.md": JSON.stringify({ props: props_obj }, null, 2)
|
|
258
|
+
}));
|
|
259
|
+
|
|
260
|
+
const buildError = window.buildHugo();
|
|
261
|
+
if (buildError) {
|
|
262
|
+
console.warn(buildError);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const output = window.readHugoFiles(JSON.stringify([
|
|
267
|
+
"public/index.html"
|
|
268
|
+
]))["public/index.html"];
|
|
202
269
|
|
|
203
270
|
try {
|
|
204
271
|
return JSON.parse(output);
|
|
@@ -36,6 +36,11 @@ export class IdentifierParser {
|
|
|
36
36
|
return `${variable}.${index}`;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// strip the leading .Params. from basic variable references
|
|
40
|
+
// if (/^\s*\./.test(this.input)) {
|
|
41
|
+
// return this.input.replace(/^\s*\.Params\.([^\.\s])/, '$1');
|
|
42
|
+
// }
|
|
43
|
+
|
|
39
44
|
// strip the leading . from basic variable references
|
|
40
45
|
if (/^\s*\./.test(this.input)) {
|
|
41
46
|
return this.input.replace(/^\s*\.([^\.\s])/, '$1');
|
|
@@ -105,6 +105,9 @@ export default function (text, opts) {
|
|
|
105
105
|
liveMarkup: true,
|
|
106
106
|
...opts
|
|
107
107
|
}
|
|
108
|
+
if (!/bookshop/.test(text)) {
|
|
109
|
+
return text;
|
|
110
|
+
}
|
|
108
111
|
const tokenizer = new Tokenizer(text.toString());
|
|
109
112
|
const tokens = tokenizer.readTopLevelTokens();
|
|
110
113
|
const output = [];
|
|
@@ -28,34 +28,40 @@ test("don't add live markup to bookshop_partial tags", t => {
|
|
|
28
28
|
t.is(translateTextTemplate(input, {}), expected);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
test("add live markup
|
|
31
|
+
test("don't add live markup if no bookshop found", t => {
|
|
32
32
|
let input = `{{ $a := .b }}`;
|
|
33
|
-
let expected = `{{ $a := .b }}
|
|
33
|
+
let expected = `{{ $a := .b }}`;
|
|
34
34
|
t.is(translateTextTemplate(input, {}), expected);
|
|
35
|
+
});
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
test("add live markup to assigns", t => {
|
|
38
|
+
let input = `{{ $a := .b }}bookshop`;
|
|
39
|
+
let expected = `{{ $a := .b }}{{ \`<!--bookshop-live context($a: (.b))-->\` | safeHTML }}bookshop`;
|
|
38
40
|
t.is(translateTextTemplate(input, {}), expected);
|
|
39
41
|
|
|
40
|
-
input = `{{ $a
|
|
41
|
-
expected = `{{ $a
|
|
42
|
+
input = `{{ $a := .b | chomp }}bookshop`;
|
|
43
|
+
expected = `{{ $a := .b | chomp }}{{ \`<!--bookshop-live context($a: (.b | chomp))-->\` | safeHTML }}bookshop`;
|
|
44
|
+
t.is(translateTextTemplate(input, {}), expected);
|
|
45
|
+
|
|
46
|
+
input = `{{ $a = .b }}bookshop`;
|
|
47
|
+
expected = `{{ $a = .b }}{{ \`<!--bookshop-live reassign($a: (.b))-->\` | safeHTML }}bookshop`;
|
|
42
48
|
t.is(translateTextTemplate(input, {}), expected);
|
|
43
49
|
});
|
|
44
50
|
|
|
45
51
|
test("add live markup to withs", t => {
|
|
46
|
-
const input = `{{ with .b }}<p>{{.}}</p>{{ end }}`;
|
|
52
|
+
const input = `{{ with .b }}<p>{{.}}</p>{{ end }}bookshop`;
|
|
47
53
|
const expected = [`{{ with .b }}`,
|
|
48
54
|
`{{ \`<!--bookshop-live stack-->\` | safeHTML }}`,
|
|
49
55
|
`{{ \`<!--bookshop-live context(.: (.b))-->\` | safeHTML }}`,
|
|
50
56
|
`<p>{{.}}</p>`,
|
|
51
57
|
`{{ \`<!--bookshop-live unstack-->\` | safeHTML }}`,
|
|
52
|
-
`{{ end }}`
|
|
58
|
+
`{{ end }}bookshop`
|
|
53
59
|
].join('');
|
|
54
60
|
t.is(translateTextTemplate(input, {}), expected);
|
|
55
61
|
});
|
|
56
62
|
|
|
57
63
|
test("add live markup to loops", t => {
|
|
58
|
-
const input = `{{ range .items }}<p>{{ . }}</p>{{ end }}`;
|
|
64
|
+
const input = `{{ range .items }}<p>{{ . }}</p>{{ end }}bookshop`;
|
|
59
65
|
const expected = [`{{ $bookshop__live__iterator__keys := (slice) }}`,
|
|
60
66
|
`{{ range $i, $e := (.items) }}{{ $bookshop__live__iterator__keys = $bookshop__live__iterator__keys | append $i }}{{ end }}`,
|
|
61
67
|
`{{ $bookshop__live__iterator := 0 }}`,
|
|
@@ -66,26 +72,26 @@ test("add live markup to loops", t => {
|
|
|
66
72
|
`{{ $bookshop__live__iterator = (add $bookshop__live__iterator 1) }}`,
|
|
67
73
|
`<p>{{ . }}</p>`,
|
|
68
74
|
`{{ \`<!--bookshop-live unstack-->\` | safeHTML }}`,
|
|
69
|
-
`{{ end }}`
|
|
75
|
+
`{{ end }}bookshop`
|
|
70
76
|
].join('');
|
|
71
77
|
t.is(translateTextTemplate(input, {}), expected);
|
|
72
78
|
});
|
|
73
79
|
|
|
74
80
|
test("add live markup to loops with iterators", t => {
|
|
75
|
-
const input = `{{range $loop_index, $element := .columns}}<p>{{$element}}</p>{{ end }}`;
|
|
81
|
+
const input = `{{range $loop_index, $element := .columns}}<p>{{$element}}</p>{{ end }}bookshop`;
|
|
76
82
|
const expected = [`{{range $loop_index, $element := .columns}}`,
|
|
77
83
|
`{{ \`<!--bookshop-live stack-->\` | safeHTML }}`,
|
|
78
84
|
`{{ (printf \`<!--bookshop-live context(.: (index (.columns) %v))-->\` (jsonify $loop_index)) | safeHTML }}`,
|
|
79
85
|
`<p>{{$element}}</p>`,
|
|
80
86
|
`{{ \`<!--bookshop-live unstack-->\` | safeHTML }}`,
|
|
81
|
-
`{{ end }}`
|
|
87
|
+
`{{ end }}bookshop`
|
|
82
88
|
].join('');
|
|
83
89
|
t.is(translateTextTemplate(input, {}), expected);
|
|
84
90
|
});
|
|
85
91
|
|
|
86
92
|
test("escape backticks in values", t => {
|
|
87
|
-
let input = `{{ $a := "hi\`:)" }}`;
|
|
88
|
-
let expected = `{{ $a := "hi\`:)" }}{{ replace \`<!--bookshop-live context($a: ("hiBKSH_BACKTICK:)"))-->\` "BKSH_BACKTICK" "\`" | safeHTML }}`;
|
|
93
|
+
let input = `{{ $a := "hi\`:)" }}bookshop`;
|
|
94
|
+
let expected = `{{ $a := "hi\`:)" }}{{ replace \`<!--bookshop-live context($a: ("hiBKSH_BACKTICK:)"))-->\` "BKSH_BACKTICK" "\`" | safeHTML }}bookshop`;
|
|
89
95
|
t.is(translateTextTemplate(input, {}), expected);
|
|
90
96
|
});
|
|
91
97
|
|
|
@@ -105,7 +111,7 @@ test("add live markup to complex end structures", t => {
|
|
|
105
111
|
{{end}}
|
|
106
112
|
{{ end }}
|
|
107
113
|
|
|
108
|
-
{{ end }}`;
|
|
114
|
+
{{ end }}bookshop`;
|
|
109
115
|
const expected = `
|
|
110
116
|
{{ $bookshop__live__iterator__keys := (slice) }}{{ range $i, $e := (.items) }}{{ $bookshop__live__iterator__keys = $bookshop__live__iterator__keys | append $i }}{{ end }}{{ $bookshop__live__iterator := 0 }}{{ range .items }}{{ \`<!--bookshop-live stack-->\` | safeHTML }}{{ $bookshop__live__iterator__key := (index ($bookshop__live__iterator__keys) $bookshop__live__iterator) }}{{ (printf \`<!--bookshop-live context(.: (index (.items) %v))-->\` (jsonify $bookshop__live__iterator__key)) | safeHTML }}{{ $bookshop__live__iterator = (add $bookshop__live__iterator 1) }}
|
|
111
117
|
|
|
@@ -121,7 +127,7 @@ test("add live markup to complex end structures", t => {
|
|
|
121
127
|
{{ \`<!--bookshop-live unstack-->\` | safeHTML }}{{end}}
|
|
122
128
|
{{ end }}
|
|
123
129
|
|
|
124
|
-
{{ \`<!--bookshop-live unstack-->\` | safeHTML }}{{ end }}`;
|
|
130
|
+
{{ \`<!--bookshop-live unstack-->\` | safeHTML }}{{ end }}bookshop`;
|
|
125
131
|
t.is(translateTextTemplate(input, {}), expected);
|
|
126
132
|
});
|
|
127
133
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bookshop/hugo-engine",
|
|
3
3
|
"packageManager": "yarn@3.0.0",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0-alpha.2",
|
|
5
5
|
"description": "Bookshop frontend Hugo renderer",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"*.js",
|
|
15
15
|
"lib/*.js",
|
|
16
16
|
"!**/*.test.js",
|
|
17
|
-
"hugo-renderer/hugo_renderer.wasm",
|
|
18
|
-
"hugo-
|
|
17
|
+
"full-hugo-renderer/hugo_renderer.wasm.gz",
|
|
18
|
+
"bookshop-hugo-templates/**/*"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
21
|
"test": "nyc ava -v"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"nyc": "^15.1.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@bookshop/helpers": "3.
|
|
33
|
+
"@bookshop/helpers": "3.4.0-alpha.2",
|
|
34
34
|
"esbuild": "^0.13.10",
|
|
35
35
|
"fflate": "^0.7.3",
|
|
36
36
|
"liquidjs": "9.28.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"parent":null,"pid":3424,"argv":["/opt/hostedtoolcache/node/16.18.1/x64/bin/node","/home/runner/work/bookshop/bookshop/javascript-modules/node_modules/ava/cli.js","-v"],"execArgv":[],"cwd":"/home/runner/work/bookshop/bookshop/javascript-modules/engines/hugo-engine","time":1669766790333,"ppid":3413,"coverageFilename":"/home/runner/work/bookshop/bookshop/javascript-modules/engines/hugo-engine/.nyc_output/6aec5420-0b83-4260-b300-4d595dfd0660.json","externalId":"","uuid":"6aec5420-0b83-4260-b300-4d595dfd0660","files":[]}
|