Files
wails/v2/internal/html/assetbundle.go
Lea Anthony 71bfd29376 Feature/v2 mac (#555)
* Get it compiling

* Stubs in place to compile

* Semi runs

* add darwin platform for server

* Evaluation working correctly. Still WIP

* Ignore favicon for desktop

* lint

* Remove feature flag code

* More feature flag removal

* Support sending messages to the backend

* Callbacks working

* Add Center + refactor prefs

* Fix logger

* Callback hooks for MOAE

* Update packages

* ignore test builds

* Support Un/Fullscreen

* vscode stuff

* Only show window when rendered

* Get it compiling again!

* Support tons of stuff!

* Tidy up

* More refactoring

* WIP [bugged]

* Got get frame working

* fix setsize and setposition

* Add Mac Application Options

* Add HideTitleBar

* Support more mac window options

* Add Toolbar support for Mac

* Support colour

* Support runtime colour change

* Moved options to own package

* Refactored mac titlebar options

* Support hidden titlebar

* Support HiddenInset Titlebar

* Support TitleBar Default

Fixed merging defaults

* Sample titlebars

* Fix minmax app

* Min/Max size supported

* WIP: Support multiple value return

* Support OpenDialog

* Remove old dialog code

* change service bus topics for dialogs

* Revert changes to v1

* Use options struct for dialogs

* Initial support for OpenDialog

* Support selecting files+dirs

* Support multiple files in dialog

* Support all dialog properties

* Add comments

* Filter support

* Support default directory

* Support SaveDialog

* Tidy Up

* WIP: Basics of window drag

* Support window dragging

* Update tests

* Frameless is calculated for Mac

* Tidy up

* Support vibrancy and transparency for webview

Options Colour -> RGBA

* Rename vibrancy to appearance

* Add default appearance

* Refactor part 1

* Refactor Part 2

* Support Translucent Window Background

* Update runtime test

* Add IsDarkMode

Updated runtime test

* Support theme mode change event

* Misc fixes for events

* Support OnMultiple

* Small fixes to frontend events

* Add System calls to runtime

* Add system calls to js runtime

* Support System calls in Go Runtime

* Port Sync Store

* Refactor store. Add get().

* Refactor system. Add IsDarkMode state store

* Use IsDarkMode state store

* Remove generated files

* Support setting app state at startup

* Add Store to go runtime

* Update runtime to v1.0.3

* Remove unused event messages

* Debugging

* initial kitchen sink

* Fix right click crash

* Better drag support

* WIP

* Remove log package

* Add Log to Go runtime

* Add logging to kitchen sink

* Improved CodeBlock. Dark mode to store.

* Start Events. List styling moved to global scope.

* Make logger a public package

* Revert logger package

* Major logging refactor

* Make Ffenestri use logging subsystem.

* Debug refactor

* Add trace to JS runtime

* Migrate runtime to @wails

* Support Trace in kitchensink

* Support trace in go runtime

* Support log level

* Support Print in JS runtime

* Runtime v1.0.1

* Move Info message to Trace

* Support Print logging

* Updated Logger interface

* Fix number of methods in Log

* Support SetLogLevel() at runtime

Refactor of loglevel

* Made go runtime package public.

Using loglevel store to keep loglevel in sync

* Support dynamic loglevel

* Runtime refactor

* Fully refactored logging

* Better looking scrollbar

* Terminal output component

* Link component

* SetLogLevel fully supported

* Runtime defs update.

Slight System refactor

* More Logging updates

* Move preview for SetLogLevel

* Fix log level reactivity.

Misc fixes and tweaks

* logging: slight refactor

* Update logger constants to fix default values

* @wails/runtime v1.0.4

* Fix change in logging levels

* hook in windowWillClose

* refactor clilogger

* WIP Events.On

* Add Events.On

* Improved error handling?

* Disable annoying smart quotes

* update runtime definitions

* Support Emit & Once. Improved On.

* Remove old event methods

* Remove old Event methods

* Update runtime in kitchensink

* Revert Fatal on JS Error

* Tidy up events runtime

* Finish events page

* Update Browser runtime API

* Unify Browser runtime

* JS Runtime v1.0.8

* Fix browser runtime export

* Remove debug line

* Add Browser examples

* Update title

* Improved runtime.System

* Update runtime.System to make all methods

* Expose System methods in Go runtime

* Add System to kitchensink

* Huge improvement to calls: Now handles objects

* Add JS runtime Dialog

* Dialog WIP

* Js package generation (#554)

* WIP

* Generation of index.js

* Add RelativeToCwd

* Add JSDoc comments

* Convert to ES6 syntax

* Fix typo

* Initial generation of typescript declarations

* Typescript improvements

* Improved @returns jsdoc

* Improved declaration files

* Simplified output

* Rename file

* Tidy up

* Revert "Simplified output"

This reverts commit 15cdf7382b.

* Now parsing actual code

* Support Array types

* Reimagined parser

* Wrap parsing in Parser

* Rewritten module generator (TS Only)

* Final touches

* Slight refactor to improve output

* Struct comments. External struct literal binding

* Reworked project parser *working*

* remove debug info

* Refactor of parser

* remove the spew

* Better Ts support

* Better project generation logic

* Support local functions in bind()

* JS Object generation. Linting.

* Support json tags in module generation

* Updated mod files

* Support vscode file generation

* Better global.d.ts

* add ts-check to templates

* Support TS declaration files

* improved 'generate' command for module

Co-authored-by: Travis McLane <tmclane@gmail.com>
2020-11-15 09:27:23 +11:00

201 lines
4.8 KiB
Go

package html
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"path/filepath"
"strings"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/assetdb"
"golang.org/x/net/html"
)
// AssetBundle is a collection of Assets
type AssetBundle struct {
assets []*Asset
basedirectory string
}
// NewAssetBundle creates a new AssetBundle struct containing
// the given html and all the assets referenced by it
func NewAssetBundle(pathToHTML string) (*AssetBundle, error) {
// Create result
result := &AssetBundle{
basedirectory: filepath.Dir(pathToHTML),
}
err := result.loadAssets(pathToHTML)
if err != nil {
return nil, err
}
return result, nil
}
// loadAssets processes the given html file and loads in
// all referenced assets
func (a *AssetBundle) loadAssets(pathToHTML string) error {
// Save HTML
htmlAsset := &Asset{
Type: AssetTypes.HTML,
Path: filepath.Base(pathToHTML),
}
err := htmlAsset.Load(a.basedirectory)
if err != nil {
return err
}
a.assets = append(a.assets, htmlAsset)
return a.processHTML(htmlAsset.AsString())
}
// Credit to: https://drstearns.github.io/tutorials/tokenizing/
func (a *AssetBundle) processHTML(htmldata string) error {
// Tokenize the html
buf := bytes.NewBufferString(htmldata)
tokenizer := html.NewTokenizer(buf)
for {
//get the next token type
tokenType := tokenizer.Next()
//if it's an error token, we either reached
//the end of the file, or the HTML was malformed
if tokenType == html.ErrorToken {
err := tokenizer.Err()
if err == io.EOF {
//end of the file, break out of the loop
break
}
//otherwise, there was an error tokenizing,
//which likely means the HTML was malformed.
//since this is a simple command-line utility,
//we can just use log.Fatalf() to report the error
//and exit the process with a non-zero status code
return tokenizer.Err()
}
//process the token according to the token type...
if tokenType == html.StartTagToken {
//get the token
token := tokenizer.Token()
//if the name of the element is "title"
if "link" == token.Data {
//the next token should be the page title
tokenType = tokenizer.Next()
//just make sure it's actually a text token
asset := &Asset{}
for _, attr := range token.Attr {
// Favicon
if attr.Key == "rel" && attr.Val == "icon" {
asset.Type = AssetTypes.FAVICON
}
if attr.Key == "href" {
asset.Path = attr.Val
}
// stylesheet
if attr.Key == "rel" && attr.Val == "stylesheet" {
asset.Type = AssetTypes.CSS
}
}
err := asset.Load(a.basedirectory)
if err != nil {
return err
}
a.assets = append(a.assets, asset)
}
if "script" == token.Data {
tokenType = tokenizer.Next()
//just make sure it's actually a text token
asset := &Asset{Type: AssetTypes.JS}
for _, attr := range token.Attr {
if attr.Key == "src" {
asset.Path = attr.Val
break
}
}
err := asset.Load(a.basedirectory)
if err != nil {
return err
}
a.assets = append(a.assets, asset)
}
}
}
return nil
}
// WriteToCFile dumps all the assets to C files in the given directory
func (a *AssetBundle) WriteToCFile(targetDir string) (string, error) {
// Write out the assets.c file
var cdata strings.Builder
// Write header
header := `// assets.c
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL.
// This file was auto-generated. DO NOT MODIFY.
`
cdata.WriteString(header)
// Loop over the Assets
var err error
assetVariables := slicer.String()
var variableName string
for index, asset := range a.assets {
// For desktop we ignore the favicon
if asset.Type == AssetTypes.FAVICON {
continue
}
variableName = fmt.Sprintf("%s%d", asset.Type, index)
assetCdata := fmt.Sprintf("const unsigned char %s[]={ %s0x00 };\n", variableName, asset.AsCHexData())
cdata.WriteString(assetCdata)
assetVariables.Add(variableName)
}
if assetVariables.Length() > 0 {
cdata.WriteString(fmt.Sprintf("\nconst unsigned char *assets[] = { %s, 0x00 };", assetVariables.Join(", ")))
} else {
cdata.WriteString("\nconst unsigned char *assets[] = { 0x00 };")
}
// Save file
assetsFile := filepath.Join(targetDir, "assets.c")
err = ioutil.WriteFile(assetsFile, []byte(cdata.String()), 0600)
if err != nil {
return "", err
}
return assetsFile, nil
}
// ConvertToAssetDB returns an assetdb.AssetDB initialized with
// the items in the AssetBundle
func (a *AssetBundle) ConvertToAssetDB() (*assetdb.AssetDB, error) {
assetdb := assetdb.NewAssetDB()
// Loop over the Assets
for _, asset := range a.assets {
assetdb.AddAsset(asset.Path, []byte(asset.Data))
}
return assetdb, nil
}
// Dump will output the assets to the terminal
func (a *AssetBundle) Dump() {
println("Assets:")
for _, asset := range a.assets {
asset.Dump()
}
}