firefly-compiler 0.6.19 → 0.6.20

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.
@@ -0,0 +1,80 @@
1
+ import Builder
2
+ import ModuleCache
3
+
4
+ setGlobalBridge(nodeSystem: NodeSystem) {
5
+ // To avoid having the generated code for buildMain depend on the Firefly compiler,
6
+ // we provide the bridge through a global symbol that is read by BuildSystem.internalBridge.
7
+ nodeSystem.js().globalThis()->"$firefly_bridge" = BuildSystemBridge(
8
+ internalCompile = {internalCompile(nodeSystem, _, _)}
9
+ internalBrowserCallEsBuild = {callEsBuildForBrowser(nodeSystem, _, _, _, _)}
10
+ )!
11
+ }
12
+
13
+ internalCompile(nodeSystem: NodeSystem, mainFiles: List[Path], target: String): Unit {
14
+ Builder.buildViaBuildSystem(
15
+ nodeSystem
16
+ nodeSystem.path(nodeSystem!->"fireflyPath_"?)
17
+ mainFiles
18
+ target
19
+ )
20
+ }
21
+
22
+ callEsBuildForBrowser(
23
+ nodeSystem: NodeSystem
24
+ mainJsFiles: List[String]
25
+ outputPath: String
26
+ minify: Bool
27
+ sourceMap: Bool
28
+ ): Unit {
29
+ let esbuild = Js.import("esbuild")
30
+ Js.await(esbuild->build(Js->(
31
+ entryPoints = mainJsFiles
32
+ bundle = True
33
+ minify = minify
34
+ sourcemap = sourceMap
35
+ platform = "browser"
36
+ target = "es2017"
37
+ outdir = outputPath
38
+ outExtension = Js.object().with(".js", ".bundle.js")
39
+ )))
40
+ }
41
+
42
+ callEsBuildForNode(
43
+ self: NodeSystem
44
+ mainJsFile: String
45
+ outputPath: String
46
+ minify: Bool
47
+ ): Unit {
48
+ let esbuild = Js.import("esbuild")
49
+ Js.await(esbuild->build(Js->(
50
+ entryPoints = [mainJsFile]
51
+ bundle = True
52
+ minify = minify
53
+ sourcemap = True
54
+ platform = "node"
55
+ target = "es2017"
56
+ external = ["esbuild", "uws.js"]
57
+ loader = Js.object().with(".node", "copy")
58
+ outdir = outputPath
59
+ )))
60
+ }
61
+
62
+ callEsBuildContextForNode(
63
+ self: NodeSystem
64
+ mainJsFile: String
65
+ outputPath: String
66
+ minify: Bool
67
+ ): JsValue {
68
+ let esbuild = Js.import("esbuild")
69
+ Js.await(esbuild->context(Js->(
70
+ entryPoints = [mainJsFile]
71
+ bundle = True
72
+ minify = minify
73
+ sourcemap = True
74
+ platform = "node"
75
+ target = "es2017"
76
+ external = ["esbuild", "uws.js"]
77
+ loader = Js.object().with(".node", "copy")
78
+ outfile = outputPath
79
+ )))
80
+ }
@@ -15,7 +15,6 @@ build(
15
15
  emitTarget: EmitTarget
16
16
  mainModules: List[ModuleKey]
17
17
  resolvedDependencies: ResolvedDependencies
18
- compilerModulePath: Option[Path]
19
18
  jsOutputPath: Path
20
19
  printMeasurements: Bool
21
20
  moduleCache: ModuleCache
@@ -24,7 +23,6 @@ build(
24
23
  let compiler = Compiler.new(
25
24
  emitTarget
26
25
  system.mainTask()
27
- compilerModulePath
28
26
  jsOutputPath
29
27
  resolvedDependencies
30
28
  Map.new()
@@ -107,7 +105,6 @@ buildViaBuildSystem(
107
105
  emitTarget = EmitBrowser
108
106
  mainModules = mainModuleKeys
109
107
  resolvedDependencies = resolvedDependencies.ResolvedDependencies(packagePaths = fixedPackagePaths)
110
- compilerModulePath = None
111
108
  jsOutputPath = system.path(".firefly/output").slash(target)
112
109
  printMeasurements = printMeasurements
113
110
  moduleCache = moduleCache
@@ -156,7 +153,6 @@ check(
156
153
  let compiler = Compiler.new(
157
154
  EmitNode
158
155
  system.mainTask()
159
- None
160
156
  package.root.slash(".firefly").slash("temporary")
161
157
  fixedResolvedDependencies
162
158
  virtualFiles
@@ -13,7 +13,6 @@ import LspHook
13
13
  capability Compiler(
14
14
  emitTarget: EmitTarget
15
15
  task: Task
16
- compilerModulePath: Option[Path]
17
16
  jsOutputPath: Path
18
17
  packagePaths: Map[PackagePair, Path]
19
18
  singleFilePackages: Set[PackagePair]
@@ -27,7 +26,6 @@ capability Compiler(
27
26
  new(
28
27
  emitTarget: EmitTarget
29
28
  task: Task
30
- compilerModulePath: Option[Path]
31
29
  jsOutputPath: Path
32
30
  resolvedDependencies: ResolvedDependencies
33
31
  virtualFiles: Map[String, String]
@@ -37,7 +35,6 @@ new(
37
35
  Compiler(
38
36
  emitTarget = emitTarget
39
37
  task = task
40
- compilerModulePath = compilerModulePath
41
38
  jsOutputPath = jsOutputPath
42
39
  packagePaths = resolvedDependencies.packagePaths
43
40
  singleFilePackages = resolvedDependencies.singleFilePackages
@@ -231,7 +228,6 @@ extend self: Compiler {
231
228
  otherModules = allModules
232
229
  emitTarget = self.emitTarget
233
230
  isMainModule = isMainModule
234
- compilerModuleFileUrl = self.compilerModulePath.map {_.relativeUrlTo(jsPath)}
235
231
  moduleKey = moduleKey
236
232
  )
237
233
  emitter.emitModule(module)
@@ -4,7 +4,8 @@ import Dependencies
4
4
  import DependencyLock
5
5
  import Syntax
6
6
  import JsEmitter
7
- import Builder from ff:compiler
7
+ import Bridge
8
+ import Builder
8
9
 
9
10
  capability Runner(
10
11
  lock: Lock
@@ -139,7 +140,7 @@ startApp(
139
140
  )
140
141
  let esBuildPath = runFilePath.parent().grab().slash(runFilePath.base() + ".minified.js")
141
142
  let context = esbuildContext.jsValue.else {
142
- let jsValue = BuildSystem.internalNodeCallEsBuildContext(system, startPath.absolute(), esBuildPath.absolute(), minify = True)
143
+ let jsValue = Bridge.callEsBuildContextForNode(system, startPath.absolute(), esBuildPath.absolute(), minify = True)
143
144
  esbuildContext.jsValue = Some(jsValue)
144
145
  jsValue
145
146
  }
@@ -166,6 +167,17 @@ startApp(
166
167
  runner.state = CompileErrorState(None, error.message())
167
168
  }
168
169
  }
170
+ } elseIf {message->ffDevelopMode === "internalBrowserCallEsBuild"} {
171
+ runner.lock.do {
172
+ if(taskIteration == runner.iteration):
173
+ try {
174
+ Bridge.callEsBuildForBrowser(system, message->mainJsFiles?, message->outputPath?, message->minify?, message->sourceMap?)
175
+ forkedProcess->send(Js->(ffDevelopMode = "internalBrowserCallEsBuild"))
176
+ Unit
177
+ } catchAny {error =>
178
+ runner.state = CompileErrorState(None, error.message())
179
+ }
180
+ }
169
181
  }
170
182
  }))
171
183
  let standardOut = result.standardOut.toString()
@@ -8,7 +8,6 @@ class JsEmitter(
8
8
  jsImporter: JsImporter
9
9
  emitTarget: EmitTarget
10
10
  isMainModule: Bool
11
- compilerModuleFileUrl: Option[String]
12
11
  moduleKey: ModuleKey
13
12
  mutable emittingAsync: Bool
14
13
  mutable tailCallUsed: Bool
@@ -29,7 +28,6 @@ new(
29
28
  otherModules: List[Module]
30
29
  emitTarget: EmitTarget
31
30
  isMainModule: Bool
32
- compilerModuleFileUrl: Option[String]
33
31
  moduleKey: ModuleKey
34
32
  ): JsEmitter {
35
33
  JsEmitter(
@@ -39,7 +37,6 @@ new(
39
37
  jsImporter = JsImporter.new()
40
38
  emitTarget = emitTarget
41
39
  isMainModule = isMainModule
42
- compilerModuleFileUrl = compilerModuleFileUrl
43
40
  moduleKey = moduleKey
44
41
  emittingAsync = False
45
42
  tailCallUsed = False
@@ -121,7 +118,6 @@ extend self: JsEmitter {
121
118
  emitModule(module: Module) {
122
119
  let selfImport = self.emitImport(self.moduleKey)
123
120
  let imports = [
124
- self.compilerModuleFileUrl.map {"import * as $firefly_compiler from '" + _ + "'"}.toList()
125
121
  module.imports.sortBy {_.moduleKey}.map {self.emitImport(_.moduleKey)}
126
122
  ].flatten()
127
123
  let liner = Liner(self, True)
package/compiler/Main.ff CHANGED
@@ -12,6 +12,7 @@ import ModuleCache
12
12
  import LspHook
13
13
  import DependencyLock
14
14
  import DevelopMode
15
+ import Bridge
15
16
 
16
17
  data MainCommand {
17
18
  BootstrapCommand
@@ -108,7 +109,6 @@ main(system: NodeSystem): Unit {
108
109
  ].toMap()
109
110
  singleFilePackages = [].toSet()
110
111
  )
111
- compilerModulePath = None
112
112
  jsOutputPath = workingDirectory.slash("output").slash("js")
113
113
  printMeasurements = True
114
114
  moduleCache = ModuleCache.new(0)
@@ -176,9 +176,6 @@ buildScript(
176
176
  } else {
177
177
  resolvedDependencies.packagePaths.add(PackagePair("ff", "core"), fireflyPath.slash("core"))
178
178
  }
179
- let compilerModulePath = if(emitTarget != EmitBrowser) {
180
- fireflyPath.slash("output").slash("js").slash("ff").slash("compiler/Builder.mjs")
181
- }
182
179
  let targetName = emitTarget.{
183
180
  | EmitNode => "node"
184
181
  | EmitBrowser => "browser"
@@ -192,7 +189,6 @@ buildScript(
192
189
  emitTarget = emitTarget
193
190
  mainModules = [moduleKey]
194
191
  resolvedDependencies = resolvedDependencies.ResolvedDependencies(packagePaths = fixedPackagePaths)
195
- compilerModulePath = compilerModulePath
196
192
  jsOutputPath = system.path(".firefly").path("output").path(targetName)
197
193
  printMeasurements = printMeasurements
198
194
  moduleCache = moduleCache
@@ -286,7 +282,7 @@ bundleForExecutable(system: NodeSystem, packagePair: PackagePair, moduleKey: Mod
286
282
  // The following should be awaited, but esbuild doesn't support top level await - still seems to work though
287
283
  "run.$run$(null, process.argv.slice(2))"
288
284
  )
289
- BuildSystem.internalNodeCallEsBuild(
285
+ Bridge.callEsBuildForNode(
290
286
  system,
291
287
  startPath.absolute(),
292
288
  outputPath.absolute(),
@@ -298,8 +294,8 @@ bundleForBrowser(system: NodeSystem, packagePair: PackagePair, moduleKey: Module
298
294
  let packagePath = moduleKey.packagePair.groupName("/")
299
295
  let outputPath = system.path(".firefly/output/browser/" + packagePath + "/")
300
296
  let runFile = outputPath.slash(moduleKey.importName() + ".run.mjs")
301
- BuildSystem.internalBrowserCallEsBuild(
302
- system!?
297
+ Bridge.callEsBuildForBrowser(
298
+ system
303
299
  [runFile.absolute()]
304
300
  outputPath.absolute()
305
301
  minify = True
@@ -315,6 +311,7 @@ importAndRun(
315
311
  arguments: List[String]
316
312
  buildMode: Bool = False
317
313
  ): Bool {
314
+ Bridge.setGlobalBridge(system)
318
315
  let runFile = locateRunFile(system, target, moduleKey)
319
316
  let runFilePath = if(runFile.contains("://")) {system.pathFromUrl(runFile)} else {system.path(runFile)}
320
317
  if(runFilePath.exists()) {
@@ -1,23 +1,29 @@
1
1
  capability BuildSystem {}
2
2
 
3
+ capability BuildSystemBridge(
4
+ internalCompile: (List[Path], String) => Unit
5
+ internalBrowserCallEsBuild: (List[String], String, Bool, Bool) => Unit
6
+ )
7
+
3
8
  extend self: BuildSystem {
4
9
 
5
10
  compileForBrowser(mainFiles: List[String]): AssetSystem {
11
+ let bridge = internalBridge(self)
6
12
  // TODO: Check that the mainFile is in the current package directory
7
- internalCompile(self, mainFiles.map {internalPath(self, _)}, "browser")
13
+ bridge.internalCompile(mainFiles.map {internalPath(self, _)}, "browser")
8
14
  let streams = internalListDirectory(internalPath(self, ".firefly/output/browser"))
9
15
  let mainPackagePair = internalMainPackagePair(self)
10
16
  AssetSystem(streams.toMap())
11
17
  }
12
18
 
13
19
  bundleForBrowser(mainFiles: List[String], minify: Bool = True, sourceMaps: Bool = False): AssetSystem {
14
- internalCompile(self, mainFiles.map {internalPath(self, _)}, "browser")
20
+ let bridge = internalBridge(self)
21
+ bridge.internalCompile(mainFiles.map {internalPath(self, _)}, "browser")
15
22
  let browserOutputPath = internalPath(self, ".firefly/output/browser")
16
23
  let runPaths = internalListPath(browserOutputPath).filter {_.base().endsWith(".run.mjs")}.toList()
17
24
  if(Js.globalThis()->ffDevelopMode.typeof() == "undefined") {
18
25
  let outputPath = runPaths.grabFirst().parent().grab()
19
- let start = self.mainTask().elapsed()
20
- internalBrowserCallEsBuild(self, runPaths.map {_.absolute()}, outputPath.absolute(), minify, sourceMaps)
26
+ bridge.internalBrowserCallEsBuild(runPaths.map {_.absolute()}, outputPath.absolute(), minify, sourceMaps)
21
27
  let bundlePaths = runPaths.flatMap {p =>
22
28
  let outputPath = p.parent().grab()
23
29
  let bundlePath = outputPath.slash(p.base().removeLast(".mjs").grab() + ".bundle.js")
@@ -39,7 +45,7 @@ extend self: BuildSystem {
39
45
  function bundle() {
40
46
  lock.do {
41
47
  if(!built.contains(p.absolute())) {
42
- internalBrowserCallEsBuild(self, [p.absolute()], outputPath.absolute(), minify, sourceMaps)
48
+ bridge.internalBrowserCallEsBuild([p.absolute()], outputPath.absolute(), minify, sourceMaps)
43
49
  built = built.add(p.absolute())
44
50
  }
45
51
  bundlePath.readStream()
@@ -85,66 +91,6 @@ extend self: BuildSystem {
85
91
 
86
92
  }
87
93
 
88
- internalBrowserCallEsBuild(
89
- self: BuildSystem
90
- mainJsFiles: List[String]
91
- outputPath: String
92
- minify: Bool
93
- sourceMap: Bool
94
- ): Unit {
95
- let esbuild = Js.import("esbuild")
96
- Js.await(esbuild->build(Js->(
97
- entryPoints = mainJsFiles
98
- bundle = True
99
- minify = minify
100
- sourcemap = sourceMap
101
- platform = "browser"
102
- target = "es2017"
103
- outdir = outputPath
104
- outExtension = Js.object().with(".js", ".bundle.js")
105
- )))
106
- }
107
-
108
- internalNodeCallEsBuild(
109
- self: NodeSystem
110
- mainJsFile: String
111
- outputPath: String
112
- minify: Bool
113
- ): Unit {
114
- let esbuild = Js.import("esbuild")
115
- Js.await(esbuild->build(Js->(
116
- entryPoints = [mainJsFile]
117
- bundle = True
118
- minify = minify
119
- sourcemap = True
120
- platform = "node"
121
- target = "es2017"
122
- external = ["esbuild", "uws.js"]
123
- loader = Js.object().with(".node", "copy")
124
- outdir = outputPath
125
- )))
126
- }
127
-
128
- internalNodeCallEsBuildContext(
129
- self: NodeSystem
130
- mainJsFile: String
131
- outputPath: String
132
- minify: Bool
133
- ): JsValue {
134
- let esbuild = Js.import("esbuild")
135
- Js.await(esbuild->context(Js->(
136
- entryPoints = [mainJsFile]
137
- bundle = True
138
- minify = minify
139
- sourcemap = True
140
- platform = "node"
141
- target = "es2017"
142
- external = ["esbuild", "uws.js"]
143
- loader = Js.object().with(".node", "copy")
144
- outfile = outputPath
145
- )))
146
- }
147
-
148
94
  internalListDirectory(path: Path): List[Pair[String, () => Stream[Buffer]]] {
149
95
  function go(currentPath: Path): Stream[Path] {
150
96
  currentPath.entries().flatMap {file =>
@@ -175,33 +121,6 @@ internalPath(buildSystem: BuildSystem, absoluteOrRelative: String): Path {
175
121
  Path(nodePath->resolve(absoluteOrRelative)?)
176
122
  }
177
123
 
178
- internalCompile(buildSystem: BuildSystem, mainFiles: List[Path], target: String): Unit {
179
- if(Js.globalThis()->ffDevelopMode.typeof() != "undefined") {
180
- Js->process->send(Js->(
181
- ffDevelopMode = "internalCompile"
182
- mainFiles = mainFiles.map {_.absolute()}
183
- target = target
184
- ))
185
- Js.awaitCancellablePromise {resolve, reject, cleanup =>
186
- Js->process->on("message", Js->{message =>
187
- if(message->ffDevelopMode === "internalCompile") {
188
- resolve(Unit) // Handle errors?
189
- }
190
- })
191
- }
192
- } else:
193
- // Ported from the old FFI. It's quite fragile w.r.t. changes in code generation.
194
- Js.await(Js.rawIdentifier("$firefly_compiler")->"buildViaBuildSystem_$"(
195
- buildSystem!
196
- internalPath(buildSystem, buildSystem!->"fireflyPath_"?)!
197
- mainFiles!
198
- target
199
- Js.undefined()
200
- Js.undefined()
201
- Js.currentTask()!
202
- ))
203
- }
204
-
205
124
  internalMainPackagePair(buildSystem: BuildSystem): Pair[String, String] {
206
125
  Pair(buildSystem!->"mainPackagePair_"->"group_"?, buildSystem!->"mainPackagePair_"->"name_"?)
207
126
  }
@@ -227,3 +146,40 @@ internalReadAssets(system: NodeSystem): AssetSystem {
227
146
  let streams = internalListDirectory(path)
228
147
  AssetSystem(streams.toMap())
229
148
  }
149
+
150
+ internalBridge(self: BuildSystem): BuildSystemBridge {
151
+ let bridge = Js->"$firefly_bridge"
152
+ if(!bridge.nullish()) {bridge?} else {
153
+ function delegate(job: String, message: JsValue): Unit {
154
+ Js->process->send(message.with("ffDevelopMode", job))
155
+ Js.awaitCancellablePromise {resolve, reject, cleanup =>
156
+ let callback = Js->{message =>
157
+ if(message->ffDevelopMode === job) {
158
+ resolve(Unit) // Handle errors?
159
+ }
160
+ }
161
+ cleanup {_ => Js->process->off("message", callback)}
162
+ Js->process->on("message", callback)
163
+ }
164
+ }
165
+ BuildSystemBridge(
166
+ internalCompile = {mainFiles, target =>
167
+ let message = Js->(
168
+ mainFiles = mainFiles.map {_.absolute()}
169
+ target = target
170
+ )
171
+ delegate("internalCompile", message)
172
+ }
173
+ internalBrowserCallEsBuild = {mainJsFiles, outputPath, minify, sourceMap =>
174
+ let message = Js->(
175
+ mainJsFiles = mainJsFiles
176
+ outputPath = outputPath
177
+ minify = minify
178
+ sourceMap = sourceMap
179
+ )
180
+ delegate("internalBrowserCallEsBuild", message)
181
+ }
182
+ )
183
+ }
184
+ }
185
+
@@ -4,35 +4,77 @@ import Lux from ff:lux
4
4
  import Menu
5
5
 
6
6
  serveHtml(
7
+ system: NodeSystem
7
8
  moduleName: String
8
9
  title: String
9
10
  pageData: Buffer
10
- contentHtml: String
11
- styleTags: String
12
11
  request: WebRequest[WebResponse]
12
+ body: Lux => Unit
13
13
  ): Unit {
14
+ let html = Lux.renderToString {lux, insertStyleTags =>
15
+ lux.add("html") {
16
+ lux.set("lang", "en")
17
+ lux.set("style", "background-color: #ffffff; color: #333333; width: 100%; height: 100%; color-scheme: light;")
18
+ lux.add("head") {
19
+ lux.add("title") {lux.text(title)}
20
+ lux.add("meta") {
21
+ lux.set("name", "viewport")
22
+ lux.set("content", "width=device-width, initial-scale=1.0")
23
+ }
24
+ lux.add("meta") {
25
+ lux.set("name", "theme-color")
26
+ lux.set("content", "#ecc45e")
27
+ }
28
+ lux.add("link") {
29
+ lux.set("rel", "modulepreload")
30
+ lux.set("href", "/js/ff/fireflysite/" + moduleName + ".run.mjs")
31
+ }
32
+ lux.add("link") {
33
+ lux.set("rel", "preload")
34
+ lux.set("href", "/assets/font/firefly-mono.woff2")
35
+ lux.set("as", "font")
36
+ lux.set("crossorigin", "anonymous")
37
+ }
38
+ lux.add("link") {
39
+ lux.set("rel", "preload")
40
+ lux.set("href", "/assets/font/firefly-sans.woff2")
41
+ lux.set("as", "font")
42
+ lux.set("crossorigin", "anonymous")
43
+ }
44
+ lux.add("link") {
45
+ lux.set("rel", "preload")
46
+ lux.set("href", "/assets/image/firefly-logo-yellow.webp")
47
+ lux.set("as", "image")
48
+ }
49
+ lux.add("style") {lux.text("@font-face { font-family: 'Firefly Mono'; font-display: fallback; src: url('/assets/font/firefly-mono.woff2'); }")}
50
+ lux.add("style") {lux.text("@font-face { font-family: 'Firefly Sans'; font-display: fallback; src: url('/assets/font/firefly-sans.woff2'); }")}
51
+ insertStyleTags()
52
+ lux.add("script") {
53
+ lux.set("type", "module")
54
+ lux.set("src", "/js/ff/fireflysite/" + moduleName + ".run.mjs")
55
+ }
56
+ lux.add("script") {
57
+ lux.set("type", "text/plain")
58
+ lux.set("id", "data")
59
+ lux.text(pageData.toLetter16())
60
+ }
61
+ lux.add("script") {
62
+ lux.set("type", "speculationrules")
63
+ lux.text(speculationRules)
64
+ }
65
+ }
66
+ lux.add("body") {
67
+ lux.set("style", "margin: 0; padding: 0; width: 100%; height: 100%; touch-action: manipulation;")
68
+ lux.add("div") {
69
+ lux.set("id", "main")
70
+ body(lux)
71
+ }
72
+ }
73
+ }
74
+ }
14
75
  request.writeHeader("Content-Type", "text/html; charset=UTF-8")
15
76
  request.writeText("<!doctype html>")
16
- request.writeText("<html lang='en' style='background-color: #ffffff; color: #333333; width: 100%; height: 100%; color-scheme: light;'>")
17
- request.writeText("<head>")
18
- request.writeText("<title>" + title + "</title>")
19
- request.writeText("<meta name='viewport' content='width=device-width, initial-scale=1.0'>")
20
- request.writeText("<meta name='theme-color' content='#ecc45e'>")
21
- request.writeText("<link rel='modulepreload' href='/js/ff/fireflysite/" + moduleName + ".run.mjs'>")
22
- request.writeText("<link rel='preload' href='/assets/font/firefly-mono.woff2' as='font' crossorigin='anonymous'>")
23
- request.writeText("<link rel='preload' href='/assets/font/firefly-sans.woff2' as='font' crossorigin='anonymous'>")
24
- request.writeText("<link rel='preload' href='/assets/image/firefly-logo-yellow.webp' as='image'>")
25
- request.writeText("<style>@font-face { font-family: 'Firefly Mono'; font-display: fallback; src: url('/assets/font/firefly-mono.woff2'); }</style>")
26
- request.writeText("<style>@font-face { font-family: 'Firefly Sans'; font-display: fallback; src: url('/assets/font/firefly-sans.woff2'); }</style>")
27
- request.writeText(styleTags)
28
- request.writeText("<script type='module' src='/js/ff/fireflysite/" + moduleName + ".run.mjs'></script>")
29
- request.writeText("<script type='text/plain' id='data'>" + pageData.toLetter16() + "</script>")
30
- request.writeText(speculationRules)
31
- request.writeText("</head>")
32
- request.writeText("<body style='margin: 0; padding: 0; width: 100%; height: 100%; touch-action: manipulation;'>")
33
- request.writeText("<div id='main'>" + contentHtml + "</div>")
34
- request.writeText("</body>")
35
- request.writeText("</html>")
77
+ request.writeText(html.first)
36
78
  }
37
79
 
38
80
  serve404(
@@ -55,8 +97,7 @@ renderAndServe[T: Serializable](
55
97
  render: Lux => Unit
56
98
  ) {
57
99
  let serialized = Serializable.serialize(pageData)
58
- let htmlAndCss = Lux.renderToString(system, render)
59
- serveHtml(moduleName, title, serialized, htmlAndCss.first, htmlAndCss.second, request)
100
+ serveHtml(system, moduleName, title, serialized, request, render)
60
101
  }
61
102
 
62
103
  renderToMain[T: Serializable](system: BrowserSystem, render: (Lux, T) => Unit) {
@@ -67,13 +108,11 @@ renderToMain[T: Serializable](system: BrowserSystem, render: (Lux, T) => Unit) {
67
108
  }
68
109
  }
69
110
 
70
- speculationRules: String = """<script type="speculationrules">
71
- {
111
+ speculationRules: String = """{
72
112
  "prerender": [{
73
113
  "where": {
74
114
  "href_matches": "/*"
75
115
  },
76
116
  "eagerness": "moderate"
77
117
  }]
78
- }
79
- </script>"""
118
+ }"""