embed readme
This commit is contained in:
11
build.ps1
11
build.ps1
@@ -112,9 +112,14 @@ if ($Standalone) {
|
||||
|
||||
$exeName = "hpl-toolbox-$version.exe"
|
||||
$exeOut = Join-Path $distDir $exeName
|
||||
go build -ldflags="-s -w -H windowsgui -X main.AppVersion=$version" -trimpath -o $exeOut .
|
||||
if ($LASTEXITCODE -ne 0) { Write-Error "go build failed"; exit 1 }
|
||||
Copy-Item -Path (Join-Path $repoRoot "README.md") -Destination (Join-Path $distDir "README.md") -Force
|
||||
$embeddedReadme = Join-Path (Get-Location) "README.md"
|
||||
Copy-Item -Path (Join-Path $repoRoot "README.md") -Destination $embeddedReadme -Force
|
||||
try {
|
||||
go build -tags release -ldflags="-s -w -H windowsgui -X main.AppVersion=$version" -trimpath -o $exeOut .
|
||||
if ($LASTEXITCODE -ne 0) { Write-Error "go build failed"; exit 1 }
|
||||
} finally {
|
||||
Remove-Item -Path $embeddedReadme -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$summary += [pscustomobject]@{
|
||||
Artifact = $exeName
|
||||
|
||||
64
dist/README.md
vendored
64
dist/README.md
vendored
@@ -1,64 +0,0 @@
|
||||
# HPL Toolbox
|
||||
|
||||
Bundled VS Code extension and standalone tools for playable ad workflows.
|
||||
|
||||
# Changelog
|
||||
|
||||
**v0.1.2**
|
||||
```
|
||||
Added
|
||||
- Added local hosting for HTML files.
|
||||
- Added the standalone app.
|
||||
```
|
||||
|
||||
**v0.1.3**
|
||||
```
|
||||
Added
|
||||
- Added QR regeneration for AppLovin previews that fail to render.
|
||||
- Added Save QR and Save All QRs actions.
|
||||
|
||||
Changed
|
||||
- Updated AppLovin Demo Upload.
|
||||
- Improved the file selection workflow.
|
||||
```
|
||||
|
||||
**v0.1.5**
|
||||
```
|
||||
Added
|
||||
- Added multi-file selection for PLEC Upload.
|
||||
- Added automatic iteration name detection.
|
||||
|
||||
Changed
|
||||
- Improved PLEC Upload file selection.
|
||||
- Moved standalone temporary files into the user temp folder.
|
||||
```
|
||||
|
||||
**v0.1.6**
|
||||
```
|
||||
Added
|
||||
- Added beta tools for further testing:
|
||||
- Playworks Converter for converting Playworks UnityAds HTML into other network variants.
|
||||
- MRAID Checker for scanning HTML files against MRAID requirements and best practices.
|
||||
|
||||
Changed
|
||||
- Simplified the UI.
|
||||
```
|
||||
|
||||
**v0.1.7**
|
||||
```
|
||||
Added
|
||||
- Added standalone drag-and-drop file/folder selection for HTML inputs across supported tools.
|
||||
- Added status throbber/progress updates for batch scans, uploads, sharing, and conversions.
|
||||
- Added streamed standalone progress updates so long-running actions update the status bar before completion.
|
||||
|
||||
Changed
|
||||
- MRAID Checker is no longer marked as beta in extension or standalone.
|
||||
- Playworks Converter source selection now matches the other file-selection UIs more closely.
|
||||
- Playworks Converter default output folder now resolves to the input file location's Output folder.
|
||||
- Progress text now follows the format: [throbber] Verb count file.
|
||||
|
||||
Fixed
|
||||
- Fixed standalone drag-and-drop handling for multiple files and multiple folders.
|
||||
- Fixed cleanup behavior for temporary dropped files when clearing or removing rows.
|
||||
- Fixed standalone PLEC Upload Open button using an incorrect/mangled URL by switching to the Windows URL protocol handler.
|
||||
```
|
||||
BIN
dist/hpl-toolbox-0.1.7.exe
vendored
BIN
dist/hpl-toolbox-0.1.7.exe
vendored
Binary file not shown.
BIN
dist/hpl-toolbox-0.1.7.vsix
vendored
BIN
dist/hpl-toolbox-0.1.7.vsix
vendored
Binary file not shown.
@@ -50,6 +50,14 @@ function getHtml(content: string): string {
|
||||
font-size: 15px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
h3 {
|
||||
margin: 14px 0 6px;
|
||||
font-size: 13px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
ul {
|
||||
margin: 6px 0 12px;
|
||||
padding-left: 20px;
|
||||
@@ -62,6 +70,30 @@ function getHtml(content: string): string {
|
||||
margin: 8px 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
code {
|
||||
font-family: var(--vscode-editor-font-family, monospace);
|
||||
font-size: 0.95em;
|
||||
background: var(--vscode-textCodeBlock-background);
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.changelog-block {
|
||||
margin: 8px 0 18px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 4px;
|
||||
background: var(--vscode-textCodeBlock-background);
|
||||
}
|
||||
.change-section {
|
||||
margin: 8px 0 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.changelog-block ul {
|
||||
margin: 4px 0 10px;
|
||||
}
|
||||
.changelog-block li.nested {
|
||||
margin-left: 18px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -74,6 +106,73 @@ function renderMarkdown(markdown: string): string {
|
||||
const lines = markdown.replace(/\r\n/g, '\n').split('\n');
|
||||
const html: string[] = [];
|
||||
let inList = false;
|
||||
let inCodeBlock = false;
|
||||
let codeLines: string[] = [];
|
||||
|
||||
const closeList = () => {
|
||||
if (inList) {
|
||||
html.push('</ul>');
|
||||
inList = false;
|
||||
}
|
||||
};
|
||||
|
||||
for (const rawLine of lines) {
|
||||
if (rawLine.trim() === '```') {
|
||||
closeList();
|
||||
if (inCodeBlock) {
|
||||
html.push(renderChangelogBlock(codeLines));
|
||||
codeLines = [];
|
||||
inCodeBlock = false;
|
||||
} else {
|
||||
inCodeBlock = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (inCodeBlock) {
|
||||
codeLines.push(rawLine);
|
||||
continue;
|
||||
}
|
||||
|
||||
const line = rawLine.trim();
|
||||
if (!line) {
|
||||
closeList();
|
||||
continue;
|
||||
}
|
||||
const heading = line.match(/^(#{1,3})\s+(.+)$/);
|
||||
if (heading) {
|
||||
closeList();
|
||||
const level = Math.min(heading[1].length, 2);
|
||||
html.push(`<h${level}>${renderInlineMarkdown(heading[2])}</h${level}>`);
|
||||
continue;
|
||||
}
|
||||
const boldHeading = line.match(/^\*\*(.+)\*\*$/);
|
||||
if (boldHeading) {
|
||||
closeList();
|
||||
html.push(`<h2>${escapeHtml(boldHeading[1])}</h2>`);
|
||||
continue;
|
||||
}
|
||||
const listItem = line.match(/^-\s+(.+)$/);
|
||||
if (listItem) {
|
||||
if (!inList) {
|
||||
html.push('<ul>');
|
||||
inList = true;
|
||||
}
|
||||
html.push(`<li>${renderInlineMarkdown(listItem[1])}</li>`);
|
||||
continue;
|
||||
}
|
||||
closeList();
|
||||
html.push(`<p>${renderInlineMarkdown(line)}</p>`);
|
||||
}
|
||||
if (inCodeBlock) {
|
||||
html.push(renderChangelogBlock(codeLines));
|
||||
}
|
||||
closeList();
|
||||
return html.join('\n');
|
||||
}
|
||||
|
||||
function renderChangelogBlock(lines: string[]): string {
|
||||
const html: string[] = ['<div class="changelog-block">'];
|
||||
let inList = false;
|
||||
|
||||
const closeList = () => {
|
||||
if (inList) {
|
||||
@@ -88,29 +187,30 @@ function renderMarkdown(markdown: string): string {
|
||||
closeList();
|
||||
continue;
|
||||
}
|
||||
const heading = line.match(/^(#{1,3})\s+(.+)$/);
|
||||
if (heading) {
|
||||
closeList();
|
||||
const level = Math.min(heading[1].length, 2);
|
||||
html.push(`<h${level}>${escapeHtml(heading[2])}</h${level}>`);
|
||||
continue;
|
||||
}
|
||||
const listItem = line.match(/^-\s+(.+)$/);
|
||||
if (listItem) {
|
||||
if (!inList) {
|
||||
html.push('<ul>');
|
||||
inList = true;
|
||||
}
|
||||
html.push(`<li>${escapeHtml(listItem[1])}</li>`);
|
||||
const nested = rawLine.match(/^\s{8,}-\s+/) ? ' class="nested"' : '';
|
||||
html.push(`<li${nested}>${renderInlineMarkdown(listItem[1])}</li>`);
|
||||
continue;
|
||||
}
|
||||
closeList();
|
||||
html.push(`<p>${escapeHtml(line)}</p>`);
|
||||
html.push(`<div class="change-section">${renderInlineMarkdown(line)}</div>`);
|
||||
}
|
||||
closeList();
|
||||
html.push('</div>');
|
||||
return html.join('\n');
|
||||
}
|
||||
|
||||
function renderInlineMarkdown(value: string): string {
|
||||
return escapeHtml(value)
|
||||
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/`([^`]+)`/g, '<code>$1</code>');
|
||||
}
|
||||
|
||||
function escapeHtml(value: string): string {
|
||||
return value.replace(/[&<>"']/g, ch => ({
|
||||
'&': '&',
|
||||
|
||||
@@ -24,9 +24,15 @@ func ChangelogPage(w http.ResponseWriter, r *http.Request) {
|
||||
.changelog-panel { max-width: 840px; }
|
||||
.changelog-content h1 { margin: 0 0 14px; font-size: 20px; line-height: 1.25; }
|
||||
.changelog-content h2 { margin: 18px 0 8px; padding-top: 12px; border-top: 1px solid #333; font-size: 15px; line-height: 1.3; }
|
||||
.changelog-content h3 { margin: 14px 0 6px; font-size: 13px; line-height: 1.3; }
|
||||
.changelog-content ul { margin: 6px 0 12px; padding-left: 20px; }
|
||||
.changelog-content li { margin: 4px 0; line-height: 1.45; }
|
||||
.changelog-content li.nested { margin-left: 18px; }
|
||||
.changelog-content p { margin: 8px 0; line-height: 1.5; }
|
||||
.changelog-content code { font-family: Consolas, monospace; font-size: 0.95em; background: rgba(128,128,128,0.12); padding: 1px 4px; border-radius: 3px; }
|
||||
.changelog-block { margin: 8px 0 18px; padding: 10px 12px; border: 1px solid #333; border-radius: 4px; background: rgba(128,128,128,0.08); }
|
||||
.change-section { margin: 8px 0 4px; font-weight: 600; }
|
||||
.changelog-block ul { margin: 4px 0 10px; }
|
||||
</style>`
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
@@ -34,6 +40,9 @@ func ChangelogPage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func readChangelog() string {
|
||||
if embeddedReadme != "" {
|
||||
return embeddedReadme
|
||||
}
|
||||
for _, start := range changelogSearchRoots() {
|
||||
for _, candidate := range changelogCandidates(start) {
|
||||
data, err := os.ReadFile(candidate)
|
||||
@@ -72,6 +81,8 @@ func renderChangelogMarkdown(markdown string) string {
|
||||
lines := strings.Split(strings.ReplaceAll(markdown, "\r\n", "\n"), "\n")
|
||||
var out strings.Builder
|
||||
inList := false
|
||||
inCodeBlock := false
|
||||
codeLines := []string{}
|
||||
closeList := func() {
|
||||
if inList {
|
||||
out.WriteString("</ul>")
|
||||
@@ -80,6 +91,22 @@ func renderChangelogMarkdown(markdown string) string {
|
||||
}
|
||||
|
||||
for _, rawLine := range lines {
|
||||
if strings.TrimSpace(rawLine) == "```" {
|
||||
closeList()
|
||||
if inCodeBlock {
|
||||
out.WriteString(renderChangelogBlock(codeLines))
|
||||
codeLines = []string{}
|
||||
inCodeBlock = false
|
||||
} else {
|
||||
inCodeBlock = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
if inCodeBlock {
|
||||
codeLines = append(codeLines, rawLine)
|
||||
continue
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(rawLine)
|
||||
if line == "" {
|
||||
closeList()
|
||||
@@ -87,17 +114,22 @@ func renderChangelogMarkdown(markdown string) string {
|
||||
}
|
||||
if strings.HasPrefix(line, "### ") {
|
||||
closeList()
|
||||
out.WriteString("<h2>" + html.EscapeString(strings.TrimSpace(line[4:])) + "</h2>")
|
||||
out.WriteString("<h2>" + renderInlineMarkdown(strings.TrimSpace(line[4:])) + "</h2>")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "## ") {
|
||||
closeList()
|
||||
out.WriteString("<h2>" + html.EscapeString(strings.TrimSpace(line[3:])) + "</h2>")
|
||||
out.WriteString("<h2>" + renderInlineMarkdown(strings.TrimSpace(line[3:])) + "</h2>")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "# ") {
|
||||
closeList()
|
||||
out.WriteString("<h1>" + html.EscapeString(strings.TrimSpace(line[2:])) + "</h1>")
|
||||
out.WriteString("<h1>" + renderInlineMarkdown(strings.TrimSpace(line[2:])) + "</h1>")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "**") && strings.HasSuffix(line, "**") && len(line) > 4 {
|
||||
closeList()
|
||||
out.WriteString("<h2>" + html.EscapeString(strings.TrimSuffix(strings.TrimPrefix(line, "**"), "**")) + "</h2>")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "- ") {
|
||||
@@ -105,12 +137,93 @@ func renderChangelogMarkdown(markdown string) string {
|
||||
out.WriteString("<ul>")
|
||||
inList = true
|
||||
}
|
||||
out.WriteString("<li>" + html.EscapeString(strings.TrimSpace(line[2:])) + "</li>")
|
||||
out.WriteString("<li>" + renderInlineMarkdown(strings.TrimSpace(line[2:])) + "</li>")
|
||||
continue
|
||||
}
|
||||
closeList()
|
||||
out.WriteString("<p>" + html.EscapeString(line) + "</p>")
|
||||
out.WriteString("<p>" + renderInlineMarkdown(line) + "</p>")
|
||||
}
|
||||
if inCodeBlock {
|
||||
out.WriteString(renderChangelogBlock(codeLines))
|
||||
}
|
||||
closeList()
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func renderChangelogBlock(lines []string) string {
|
||||
var out strings.Builder
|
||||
inList := false
|
||||
closeList := func() {
|
||||
if inList {
|
||||
out.WriteString("</ul>")
|
||||
inList = false
|
||||
}
|
||||
}
|
||||
|
||||
out.WriteString(`<div class="changelog-block">`)
|
||||
for _, rawLine := range lines {
|
||||
line := strings.TrimSpace(rawLine)
|
||||
if line == "" {
|
||||
closeList()
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "- ") {
|
||||
if !inList {
|
||||
out.WriteString("<ul>")
|
||||
inList = true
|
||||
}
|
||||
className := ""
|
||||
if leadingSpaceCount(rawLine) >= 8 {
|
||||
className = ` class="nested"`
|
||||
}
|
||||
out.WriteString("<li" + className + ">" + renderInlineMarkdown(strings.TrimSpace(line[2:])) + "</li>")
|
||||
continue
|
||||
}
|
||||
closeList()
|
||||
out.WriteString(`<div class="change-section">` + renderInlineMarkdown(line) + `</div>`)
|
||||
}
|
||||
closeList()
|
||||
out.WriteString("</div>")
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func renderInlineMarkdown(value string) string {
|
||||
escaped := html.EscapeString(value)
|
||||
escaped = replaceDelimited(escaped, "**", "strong")
|
||||
escaped = replaceDelimited(escaped, "`", "code")
|
||||
return escaped
|
||||
}
|
||||
|
||||
func replaceDelimited(value, marker, tag string) string {
|
||||
var out strings.Builder
|
||||
for {
|
||||
start := strings.Index(value, marker)
|
||||
if start < 0 {
|
||||
out.WriteString(value)
|
||||
break
|
||||
}
|
||||
end := strings.Index(value[start+len(marker):], marker)
|
||||
if end < 0 {
|
||||
out.WriteString(value)
|
||||
break
|
||||
}
|
||||
end += start + len(marker)
|
||||
out.WriteString(value[:start])
|
||||
out.WriteString("<" + tag + ">")
|
||||
out.WriteString(value[start+len(marker) : end])
|
||||
out.WriteString("</" + tag + ">")
|
||||
value = value[end+len(marker):]
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func leadingSpaceCount(value string) int {
|
||||
count := 0
|
||||
for _, ch := range value {
|
||||
if ch != ' ' {
|
||||
break
|
||||
}
|
||||
count++
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
5
standalone/readme_embed_dev.go
Normal file
5
standalone/readme_embed_dev.go
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build !release
|
||||
|
||||
package main
|
||||
|
||||
const embeddedReadme = ""
|
||||
8
standalone/readme_embed_release.go
Normal file
8
standalone/readme_embed_release.go
Normal file
@@ -0,0 +1,8 @@
|
||||
//go:build release
|
||||
|
||||
package main
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed README.md
|
||||
var embeddedReadme string
|
||||
Reference in New Issue
Block a user