Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/hiveview: improve esbuild setup #710

Merged
merged 6 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/hiveview/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</head>

<body>
<script id="app" src="/lib/app.js" type="module" data-main="index"></script>
<script src="/lib/app-index.js" type="module"></script>
<main role="main">
<div id="hive-header">
<a href="/"><img id="hive-logo" height="35" src="/images/hive3.svg"></a>
Expand Down
26 changes: 12 additions & 14 deletions cmd/hiveview/assets/lib/app-index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import 'datatables.net'
import 'datatables.net-bs5'
import 'datatables.net-responsive'
import 'datatables.net-responsive-bs5'
import { $ } from 'jquery'
import { html, format, nav } from './utils.js'

import { html, format } from './utils.js'
import * as routes from './routes.js'
import * as common from './common.js'

$(document).ready(function () {
common.updateHeader();

export default function navigate() {
$('#loading').show();
console.log("Loading file list...");
$.ajax("listing.jsonl", {
cache: false,
success: function(data) {
$('#page-text').show();
showFileListing(data);
Expand All @@ -17,18 +26,7 @@ export default function navigate() {
$('#loading').hide();
},
});
}

function resultStats(fails, success, total) {
f = parseInt(fails), s = parseInt(success);
t = parseInt(total);
f = isNaN(f) ? "?" : f;
s = isNaN(s) ? "?" : s;
t = isNaN(t) ? "?" : t;
return '<b><span class="text-danger">' + f +
'</span>&nbsp;:&nbsp;<span class="text-success">' + s +
'</span> &nbsp;/&nbsp;' + t + '</b>';
}
})

function linkToSuite(suiteID, suiteName, linkText) {
let url = routes.suite(suiteID, suiteName);
Expand Down
11 changes: 9 additions & 2 deletions cmd/hiveview/assets/lib/app-suite.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import 'datatables.net'
import 'datatables.net-bs5'
import 'datatables.net-responsive'
import 'datatables.net-responsive-bs5'
import { $ } from 'jquery'

import { html, nav, format, loader } from './utils.js'
import * as routes from './routes.js'
import * as common from './common.js'

$(document).ready(function () {
common.updateHeader();

export default function navigate() {
let name = nav.load("suitename");
if (name) {
showSuiteName(name);
Expand Down Expand Up @@ -34,7 +41,7 @@ export default function navigate() {
showError("error fetching " + filename + " : " + error);
},
});
}
})

// showSuiteName displays the suite title.
function showSuiteName(name) {
Expand Down
7 changes: 5 additions & 2 deletions cmd/hiveview/assets/lib/app-viewer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { $ } from 'jquery'
import { html, nav, format, loader } from './utils.js'
import * as routes from './routes.js'
import * as common from './common.js'

$(document).ready(function () {
common.updateHeader();

export default function navigate() {
// Check for line number in hash.
var line = null;
if (window.location.hash.substr(1, 1) == "L") {
Expand Down Expand Up @@ -39,7 +42,7 @@ export default function navigate() {

// Show default text because nothing was loaded.
showText(document.getElementById("exampletext").innerHTML);
}
})

// setHL sets the highlight on a line number.
function setHL(num, scroll) {
Expand Down
8 changes: 4 additions & 4 deletions cmd/hiveview/assets/lib/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ main {
}

td.test-name-column {
background: url('/images/details_open.svg') no-repeat left 4px;
background: url('../images/details_open.svg') no-repeat left 4px;
background-size: 32px;
cursor: pointer;
padding-left: 32px !important;
Expand All @@ -61,15 +61,15 @@ td.test-name-column {
}

tr.failed td.test-name-column {
background-image: url('/images/details_open_err.svg');
background-image: url('../images/details_open_err.svg');
}

tr.shown td.test-name-column {
background-image: url('/images/details_close.svg');
background-image: url('../images/details_close.svg');
}

tr.shown.failed td.test-name-column {
background-image: url('/images/details_close_err.svg');
background-image: url('../images/details_close_err.svg');
}

td.ellipsis {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
// Pull in dependencies.
import 'datatables.net'
import 'datatables.net-bs5'
import 'datatables.net-responsive'
import 'datatables.net-responsive-bs5'
import 'bootstrap'
import { $ } from 'jquery'

// Pull in app files.
import * as routes from './routes.js'
import { default as index } from './app-index.js'
import { default as suite } from './app-suite.js'
import { default as viewer } from './app-viewer.js'

$(document).ready(function() {
// Kick off the page main function.
let pages = { index, suite, viewer };
let name = $('script[type=module]').attr('data-main');
pages[name]();

export function updateHeader() {
// Update the header with version info from hive.json.
$.ajax({
type: 'GET',
Expand All @@ -31,7 +17,7 @@ $(document).ready(function() {
console.log("error fetching hive.json:", error);
},
});
})
}

function hiveInfoHTML(data) {
var txt = "";
Expand Down
2 changes: 1 addition & 1 deletion cmd/hiveview/assets/suite.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</head>

<body>
<script src="/lib/app.js" type="module" data-main="suite"></script>
<script src="/lib/app-suite.js" type="module"></script>
<main role="main">
<div id="hive-header">
<a href="/"><img id="hive-logo" height="35" src="/images/hive3.svg"></a>
Expand Down
2 changes: 1 addition & 1 deletion cmd/hiveview/assets/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</head>

<body>
<script src="/lib/app.js" type="module" data-main="viewer"></script>
<script src="/lib/app-viewer.js" type="module"></script>
<main role="main">
<div id="hive-header">
<a href="/"><img id="hive-logo" height="35" src="/images/hive3.svg"></a>
Expand Down
70 changes: 39 additions & 31 deletions cmd/hiveview/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"bytes"
"encoding/json"
"errors"
"io"
"io/fs"
"sort"
Expand All @@ -15,10 +14,14 @@ import (

// hiveviewBundler creates the esbuild bundler and registers JS/CSS targets.
func hiveviewBundler(fsys fs.FS) *bundler {
b := newBundler(fsys)
b.add("lib/app.js")
b.add("lib/app.css")
b.add("lib/viewer.css")
entrypoints := []string{
"lib/app-index.js",
"lib/app-suite.js",
"lib/app-viewer.js",
"lib/app.css",
"lib/viewer.css",
}
b := newBundler(fsys, entrypoints, moduleAliases)
return b
}

Expand Down Expand Up @@ -48,17 +51,16 @@ func importMapScript() string {
// against the bundler, and URLs in the HTML will be replaced by references to
// bundle files.
type deployFS struct {
assets fs.FS
bundler *bundler
useBundle bool
assets fs.FS
bundler *bundler
}

func newDeployFS(assets fs.FS, useBundle bool) *deployFS {
return &deployFS{
assets: assets,
bundler: hiveviewBundler(assets),
useBundle: useBundle,
dfs := &deployFS{assets: assets}
if useBundle {
dfs.bundler = hiveviewBundler(assets)
}
return dfs
}

func isBundlePath(name string) bool {
Expand All @@ -75,8 +77,9 @@ func (dfs *deployFS) Open(name string) (f fs.File, err error) {
switch {
case !strings.Contains(name, "/") && strings.HasSuffix(name, ".html"):
return dfs.openHTML(name)
case isBundlePath(name):
return dfs.bundler.fs().Open(name)
case dfs.bundler != nil && isBundlePath(name):
_, memfs, _ := dfs.bundler.rebuild()
return memfs.Open(name)
default:
return dfs.assets.Open(name)
}
Expand All @@ -92,8 +95,9 @@ func (dfs *deployFS) ReadDir(name string) ([]fs.DirEntry, error) {
switch {
case name == ".":
return dfs.readDirRoot()
case isBundlePath(name):
return fs.ReadDir(dfs.bundler.fs(), name)
case dfs.bundler != nil && isBundlePath(name):
_, memfs, _ := dfs.bundler.rebuild()
return fs.ReadDir(memfs, name)
default:
return fs.ReadDir(dfs.assets, name)
}
Expand All @@ -104,8 +108,12 @@ func (dfs *deployFS) readDirRoot() ([]fs.DirEntry, error) {
if err != nil {
return nil, err
}
bundleEntries, _ := fs.ReadDir(dfs.bundler.fs(), ".")
entries = append(entries, bundleEntries...)
if dfs.bundler != nil {
_, memfs, _ := dfs.bundler.rebuild()
bundleEntries, _ := fs.ReadDir(memfs, ".")
entries = append(entries, bundleEntries...)
}

sort.Slice(entries, func(i, j int) bool {
return entries[i].Name() < entries[j].Name()
})
Expand All @@ -128,35 +136,35 @@ func (dfs *deployFS) openHTML(name string) (fs.File, error) {
output := new(bytes.Buffer)
modTime := inputInfo.ModTime()

if !dfs.useBundle {
if dfs.bundler == nil {
// JS bundle is disabled. To make ES module loading work without the bundle,
// the document needs an importmap.
insertAfterTag(inputFile, output, "head", importMapScript())
modTime = time.Now()
} else {
// Replace script/style references with bundle paths, if possible.
buildmsg, _, _ := dfs.bundler.rebuild()
var errorShown bool
modifyHTML(inputFile, output, func(token *html.Token, errlog io.Writer) {
if len(buildmsg) > 0 && !errorShown {
io.WriteString(errlog, "** ESBUILD ERRORS **\n\n")
renderBuildMsg(buildmsg, errlog)
modTime = time.Now()
errorShown = true
}

ref := scriptOrStyleReference(token)
if ref == nil {
return // not script
}
bundle, buildmsg, err := dfs.bundler.build(ref.Val)
if errors.Is(err, fs.ErrNotExist) {
return
} else if err != nil {
if !errorShown {
io.WriteString(errlog, "** ESBUILD ERRORS **\n\n")
errorShown = true
}
renderBuildMsg(buildmsg, errlog)
modTime = time.Now()
return
bundle := dfs.bundler.bundle(ref.Val)
if bundle == nil || bundle.outputFile == "" {
return // not a bundle target
}
if bundle.buildTime.After(modTime) {
modTime = bundle.buildTime
}
ref.Val = "/bundle/" + bundle.name()
ref.Val = "/bundle/" + bundle.outputFile
})
}

Expand Down
22 changes: 21 additions & 1 deletion cmd/hiveview/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,29 @@ func TestBuildAllBundles(t *testing.T) {
b := hiveviewBundler(assets)

var output strings.Builder
msg, err := b.buildAll()
msg, _, err := b.rebuild()
if err != nil {
renderBuildMsg(msg, &output)
t.Fatal("esbuild errors:\n\n", output.String())
}
}

func TestDeployWithBundle(t *testing.T) {
assets, _ := fs.Sub(embeddedAssets, "assets")

temp := t.TempDir()
dfs := newDeployFS(assets, true)
if err := copyFS(temp, dfs); err != nil {
t.Fatal("copy error:", err)
}
}

func TestDeployWithoutBundle(t *testing.T) {
assets, _ := fs.Sub(embeddedAssets, "assets")

temp := t.TempDir()
dfs := newDeployFS(assets, false)
if err := copyFS(temp, dfs); err != nil {
t.Fatal("copy error:", err)
}
}
Loading