Compare commits

...

10 Commits

Author SHA1 Message Date
ge
171ec8fe4b rm Makefile 2025-05-29 22:47:13 +03:00
ge
b7d5f4fcb1 all: stop using src/ dir, make tests reproducible, fix CI 2025-04-22 20:14:55 +03:00
ge
e79f83f800 make path required 2025-04-13 07:13:37 +03:00
8416067007 ci: fix tests one more time 2025-04-13 06:13:38 +03:00
1723bf75b8 ci: fix tests again 2025-04-13 06:12:07 +03:00
8d68479194 ci: fix tests 2025-04-13 06:08:51 +03:00
ge
4ae38ec2c9 ci: add CI 2025-04-13 05:54:27 +03:00
ge
60dfc5f02d Add bare_map, make_const_pub, new test 2025-04-13 05:44:35 +03:00
ge
2568538cb3 cmd: update help text 2025-01-20 22:42:04 +03:00
ge
3096165165 fix test 2025-01-20 22:41:39 +03:00
11 changed files with 164 additions and 58 deletions

48
.github/workflows/docs.yaml vendored Normal file
View File

@ -0,0 +1,48 @@
name: Docs
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup V
run: |
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
unzip -q /tmp/v.zip -d /tmp
echo /tmp/v >> "$GITHUB_PATH"
- name: Build docs
run: |
v doc -f html -m .
pushd _docs
ln -vs embedfs.html index.html
ls -alFh
popd
- name: Upload static files as artifact
id: deployment
uses: actions/upload-pages-artifact@v3
with:
path: _docs/
deploy:
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
permissions:
contents: read
pages: write
id-token: write

24
.github/workflows/test.yaml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Tests
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup V
run: |
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
unzip -q /tmp/v.zip -d /tmp
echo /tmp/v >> "$GITHUB_PATH"
- name: Run tests
run: |
v -stats test .

View File

@ -1,20 +0,0 @@
SRC_DIR ?= src
DOC_DIR ?= doc
TESTS_DIR ?= .
all: test
test:
v test $(TESTS_DIR)
doc:
v doc -f html -m ./$(SRC_DIR) -o $(DOC_DIR)
serve: clean doc
v -e "import net.http.file; file.serve(folder: '$(DOC_DIR)')"
clean:
rm -r $(DOC_DIR) || true
cli:
v cmd/mkembedfs -o mkembedfs

View File

@ -56,6 +56,38 @@ module main
fn main() {
style := embedfs.files['assets/css/style.css']!
// If `bare_map` parameter is set to `true` use:
// style := embedfs['assets/css/style.css']!
println(style.data.to_string())
}
```
The generated `embedfs` const value example (from `tests/`):
```v okfmt
EmbedFileSystem{
files: {'assets/example.json': EmbedFile{
data: embed_file.EmbedFileData{ len: 22, path: "assets/example.json", apath: "", uncompressed: 846284 }
meta: EmbedFileMetadata{
key: 'assets/example.json'
name: 'example.json'
ext: 'json'
mimetype: 'application/json'
}
}}
}
```
The generated const value if `bare_map` parameter is `true`:
```v okfmt
{'assets/example.json': EmbedFile{
data: embed_file.EmbedFileData{ len: 22, path: "assets/example.json", apath: "", uncompressed: 845da4 }
meta: EmbedFileMetadata{
key: 'assets/example.json'
name: 'example.json'
ext: 'json'
mimetype: 'application/json'
}
}}
```

View File

@ -5,7 +5,7 @@ flags:
-chdir <string> change working directory before codegen
-prefix <string> path prefix for file keys, none by default
-ignore <string> path globs to ignore (allowed multiple times)
-module-name <string> generated module name, main by default
-const-name <string> generated constant name with data, embedfs by default
-module-name <string> generated module name, 'main' by default
-const-name <string> generated constant name with data, 'embedfs' by default
-no-pub do not make symbols in generated module public
-force-mimetype set applicetion/octet-stream mime type for unknown files
-force-mimetype set 'application/octet-stream' mime type for unknown files

View File

@ -38,8 +38,6 @@ fn main() {
println(generator.generate())
}
@[xdoc: 'generate code for embed directories with files into executable.']
@[name: 'embedfs']
struct FlagConfig {
help bool
chdir string

View File

@ -7,7 +7,7 @@ import net.http.mime
pub struct CodeGenerator {
pub:
// Path to file or directory to embed
path string
path string @[required]
// Path prefix if you want to add extra prefix for file paths
prefix string
// Glob patterns to match files the must be ignored when generating the code
@ -20,8 +20,12 @@ pub:
module_name string = 'main'
// Name of constant which will contain embedded files
const_name string = 'embedfs'
// If true make symbols in generated module public
// If true make constant public
make_const_pub bool
// If true make all symbols in generated module public
make_pub bool
// Generate map[string]EmbedFile instead of EmbedFileSystem instance
bare_map bool
}
struct EmbedFileSpec {
@ -34,6 +38,7 @@ struct EmbedFileSpec {
pub fn (g CodeGenerator) generate() string {
visible := if g.make_pub == true { 'pub ' } else { '' }
const_visible := if g.make_pub == true || g.make_const_pub == true { 'pub ' } else { '' }
mut b := strings.new_builder(1024 * 4)
b.writeln('// !WARNING! This file is generated by embedfs module, do not edit it.')
b.writeln('')
@ -57,21 +62,17 @@ pub fn (g CodeGenerator) generate() string {
b.writeln('\tfiles map[string]EmbedFile')
b.writeln('}')
b.writeln('')
b.writeln('${visible}const ${g.const_name} = EmbedFileSystem{')
b.writeln('\tfiles: {')
for filespec in g.get_files() {
b.writeln("\t\t'${filespec.key}': EmbedFile{")
b.writeln("\t\t\tdata: \$embed_file('${filespec.path}')")
b.writeln('\t\t\tmeta: EmbedFileMetadata{')
b.writeln("\t\t\t\tkey: '${filespec.key}'")
b.writeln("\t\t\t\tname: '${filespec.name}'")
b.writeln("\t\t\t\text: '${filespec.ext}'")
b.writeln("\t\t\t\tmimetype: '${filespec.mimetype}'")
b.writeln('\t\t\t}')
b.writeln('\t\t},')
if g.bare_map {
b.writeln('${const_visible}const ${g.const_name} = {')
g.write_embed_file_map_item(mut b)
b.writeln('}')
} else {
b.writeln('${const_visible}const ${g.const_name} = EmbedFileSystem{')
b.writeln('\tfiles: {')
g.write_embed_file_map_item(mut b)
b.writeln('\t}')
b.writeln('}')
}
b.writeln('\t}')
b.writeln('}')
return b.str()
}
@ -105,3 +106,17 @@ fn (g CodeGenerator) get_files() []EmbedFileSpec {
}
return files
}
fn (g CodeGenerator) write_embed_file_map_item(mut b strings.Builder) {
for filespec in g.get_files() {
b.writeln("\t\t'${filespec.key}': EmbedFile{")
b.writeln("\t\t\tdata: \$embed_file('${filespec.path}')")
b.writeln('\t\t\tmeta: EmbedFileMetadata{')
b.writeln("\t\t\t\tkey: '${filespec.key}'")
b.writeln("\t\t\t\tname: '${filespec.name}'")
b.writeln("\t\t\t\text: '${filespec.ext}'")
b.writeln("\t\t\t\tmimetype: '${filespec.mimetype}'")
b.writeln('\t\t\t}')
b.writeln('\t\t},')
}
}

View File

@ -1,7 +1,11 @@
module main
fn main() {
println(embedfs)
json_file := embedfs.files['assets/example.json'] or { EmbedFile{} }
println(json_file.data.to_string().trim_space())
$if bare_map ? {
json_file := embedfs['assets/example.json'] or { EmbedFile{} }
println(json_file.data.to_string().trim_space())
} $else {
json_file := embedfs.files['assets/example.json'] or { EmbedFile{} }
println(json_file.data.to_string().trim_space())
}
}

View File

@ -1,12 +1 @@
EmbedFileSystem{
files: {'assets/example.json': EmbedFile{
data: embed_file.EmbedFileData{ len: 22, path: "assets/example.json", apath: "", uncompressed: 8462c4 }
meta: EmbedFileMetadata{
key: 'assets/example.json'
name: 'example.json'
ext: 'json'
mimetype: 'application/json'
}
}}
}
{"some": "JSON data"}

View File

@ -5,14 +5,30 @@ import v.util.diff
import embedfs
fn test_mymod() {
oldpwd := os.getwd()
expected_out := os.read_file('tests/mymod_test.out')!
os.chdir('tests/mymod')!
gen := embedfs.CodeGenerator{
path: 'assets'
make_pub: false
path: 'assets'
}
os.write_file('assets_generated.v', gen.generate())!
ret := os.execute('${os.quoted_path(@VEXE)} run .')
dump(diff.compare_text(ret.output, expected_out)!)
assert ret.output == expected_out
os.chdir(oldpwd)!
}
fn test_mymod_bare_map() {
oldpwd := os.getwd()
expected_out := os.read_file('tests/mymod_test.out')!
os.chdir('tests/mymod')!
gen := embedfs.CodeGenerator{
path: 'assets'
bare_map: true
}
os.write_file('assets_generated.v', gen.generate())!
ret := os.execute('${os.quoted_path(@VEXE)} -d bare_map run .')
dump(diff.compare_text(ret.output, expected_out)!)
assert ret.output == expected_out
os.chdir(oldpwd)!
}

2
v.mod
View File

@ -1,7 +1,7 @@
Module {
name: 'embedfs'
description: 'Code generator for embedding directories with files into executables'
version: '0.0.1'
version: '0.0.2'
license: 'Unlicense'
dependencies: []
}