embed readme
This commit is contained in:
@@ -112,9 +112,14 @@ if ($Standalone) {
|
|||||||
|
|
||||||
$exeName = "hpl-toolbox-$version.exe"
|
$exeName = "hpl-toolbox-$version.exe"
|
||||||
$exeOut = Join-Path $distDir $exeName
|
$exeOut = Join-Path $distDir $exeName
|
||||||
go build -ldflags="-s -w -H windowsgui -X main.AppVersion=$version" -trimpath -o $exeOut .
|
$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 }
|
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
|
} finally {
|
||||||
|
Remove-Item -Path $embeddedReadme -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
$summary += [pscustomobject]@{
|
$summary += [pscustomobject]@{
|
||||||
Artifact = $exeName
|
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;
|
font-size: 15px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
h3 {
|
||||||
|
margin: 14px 0 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
strong {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
ul {
|
ul {
|
||||||
margin: 6px 0 12px;
|
margin: 6px 0 12px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
@@ -62,6 +70,30 @@ function getHtml(content: string): string {
|
|||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
line-height: 1.5;
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -74,6 +106,73 @@ function renderMarkdown(markdown: string): string {
|
|||||||
const lines = markdown.replace(/\r\n/g, '\n').split('\n');
|
const lines = markdown.replace(/\r\n/g, '\n').split('\n');
|
||||||
const html: string[] = [];
|
const html: string[] = [];
|
||||||
let inList = false;
|
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 = () => {
|
const closeList = () => {
|
||||||
if (inList) {
|
if (inList) {
|
||||||
@@ -88,29 +187,30 @@ function renderMarkdown(markdown: string): string {
|
|||||||
closeList();
|
closeList();
|
||||||
continue;
|
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+(.+)$/);
|
const listItem = line.match(/^-\s+(.+)$/);
|
||||||
if (listItem) {
|
if (listItem) {
|
||||||
if (!inList) {
|
if (!inList) {
|
||||||
html.push('<ul>');
|
html.push('<ul>');
|
||||||
inList = true;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
closeList();
|
closeList();
|
||||||
html.push(`<p>${escapeHtml(line)}</p>`);
|
html.push(`<div class="change-section">${renderInlineMarkdown(line)}</div>`);
|
||||||
}
|
}
|
||||||
closeList();
|
closeList();
|
||||||
|
html.push('</div>');
|
||||||
return html.join('\n');
|
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 {
|
function escapeHtml(value: string): string {
|
||||||
return value.replace(/[&<>"']/g, ch => ({
|
return value.replace(/[&<>"']/g, ch => ({
|
||||||
'&': '&',
|
'&': '&',
|
||||||
|
|||||||
@@ -24,9 +24,15 @@ func ChangelogPage(w http.ResponseWriter, r *http.Request) {
|
|||||||
.changelog-panel { max-width: 840px; }
|
.changelog-panel { max-width: 840px; }
|
||||||
.changelog-content h1 { margin: 0 0 14px; font-size: 20px; line-height: 1.25; }
|
.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 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 ul { margin: 6px 0 12px; padding-left: 20px; }
|
||||||
.changelog-content li { margin: 4px 0; line-height: 1.45; }
|
.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 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>`
|
</style>`
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
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 {
|
func readChangelog() string {
|
||||||
|
if embeddedReadme != "" {
|
||||||
|
return embeddedReadme
|
||||||
|
}
|
||||||
for _, start := range changelogSearchRoots() {
|
for _, start := range changelogSearchRoots() {
|
||||||
for _, candidate := range changelogCandidates(start) {
|
for _, candidate := range changelogCandidates(start) {
|
||||||
data, err := os.ReadFile(candidate)
|
data, err := os.ReadFile(candidate)
|
||||||
@@ -72,6 +81,8 @@ func renderChangelogMarkdown(markdown string) string {
|
|||||||
lines := strings.Split(strings.ReplaceAll(markdown, "\r\n", "\n"), "\n")
|
lines := strings.Split(strings.ReplaceAll(markdown, "\r\n", "\n"), "\n")
|
||||||
var out strings.Builder
|
var out strings.Builder
|
||||||
inList := false
|
inList := false
|
||||||
|
inCodeBlock := false
|
||||||
|
codeLines := []string{}
|
||||||
closeList := func() {
|
closeList := func() {
|
||||||
if inList {
|
if inList {
|
||||||
out.WriteString("</ul>")
|
out.WriteString("</ul>")
|
||||||
@@ -80,6 +91,22 @@ func renderChangelogMarkdown(markdown string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, rawLine := range lines {
|
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)
|
line := strings.TrimSpace(rawLine)
|
||||||
if line == "" {
|
if line == "" {
|
||||||
closeList()
|
closeList()
|
||||||
@@ -87,17 +114,22 @@ func renderChangelogMarkdown(markdown string) string {
|
|||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "### ") {
|
if strings.HasPrefix(line, "### ") {
|
||||||
closeList()
|
closeList()
|
||||||
out.WriteString("<h2>" + html.EscapeString(strings.TrimSpace(line[4:])) + "</h2>")
|
out.WriteString("<h2>" + renderInlineMarkdown(strings.TrimSpace(line[4:])) + "</h2>")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "## ") {
|
if strings.HasPrefix(line, "## ") {
|
||||||
closeList()
|
closeList()
|
||||||
out.WriteString("<h2>" + html.EscapeString(strings.TrimSpace(line[3:])) + "</h2>")
|
out.WriteString("<h2>" + renderInlineMarkdown(strings.TrimSpace(line[3:])) + "</h2>")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "# ") {
|
if strings.HasPrefix(line, "# ") {
|
||||||
closeList()
|
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
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(line, "- ") {
|
if strings.HasPrefix(line, "- ") {
|
||||||
@@ -105,12 +137,93 @@ func renderChangelogMarkdown(markdown string) string {
|
|||||||
out.WriteString("<ul>")
|
out.WriteString("<ul>")
|
||||||
inList = true
|
inList = true
|
||||||
}
|
}
|
||||||
out.WriteString("<li>" + html.EscapeString(strings.TrimSpace(line[2:])) + "</li>")
|
out.WriteString("<li>" + renderInlineMarkdown(strings.TrimSpace(line[2:])) + "</li>")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
closeList()
|
closeList()
|
||||||
out.WriteString("<p>" + html.EscapeString(line) + "</p>")
|
out.WriteString("<p>" + renderInlineMarkdown(line) + "</p>")
|
||||||
|
}
|
||||||
|
if inCodeBlock {
|
||||||
|
out.WriteString(renderChangelogBlock(codeLines))
|
||||||
}
|
}
|
||||||
closeList()
|
closeList()
|
||||||
return out.String()
|
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