Skip to content

Commit 990f85e

Browse files
committed
beta release
1 parent b1b145e commit 990f85e

File tree

10 files changed

+59
-101
lines changed

10 files changed

+59
-101
lines changed

.vscode/launch.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
// "-p..\\AzureDevOps.WikiPDFExport.Test\\Tests\\Azure-Platform-Design",
1919
// "-p..\\AzureDevOps.WikiPDFExport.Test\\Tests\\1k",
2020
// "-s..\\AzureDevOps.WikiPDFExport.Test\\Tests\\Test-Emoticon\\emoji.md",
21-
"-h",
22-
"-b",
21+
"--heading",
22+
"--breakPage",
2323
// "-m",
2424
"--math",
2525
//"--mathjax-path=MathJax.js",
2626
"--debug",
2727
// "--pathToHeading",
28-
"--header-template=<div style='padding-left: 10px; margin: 0; -webkit-print-color-adjust: exact; border-bottom:1px solid grey; color: grey; width: 100%; text-align: left; font-size: 6px;'>AzureDevOps.WikiPDFExport</div>",
29-
"--footer-template=<div style='padding-right: 10px; padding-top:2px; margin: 0; -webkit-print-color-adjust: exact; border-top:1px solid grey; color: grey; width: 100%; text-align: right; font-size: 6px;'>Print: <span class='date'></span> Page: </span><span class='pageNumber'></span>/<span class='totalPages'></span></div>",
28+
// "--header-template=<div style='padding-left: 10px; margin: 0; -webkit-print-color-adjust: exact; border-bottom:1px solid grey; color: grey; width: 100%; text-align: left; font-size: 6px;'>AzureDevOps.WikiPDFExport</div>",
29+
// "--footer-template=<div style='padding-right: 10px; padding-top:2px; margin: 0; -webkit-print-color-adjust: exact; border-top:1px solid grey; color: grey; width: 100%; text-align: right; font-size: 6px;'>Print: <span class='date'></span> Page: </span><span class='pageNumber'></span>/<span class='totalPages'></span></div>",
3030
//"--css=styles.css", //not needed, its the default now.
3131
"--open",
32-
//"--footer-url=C:\\Git\\AzureDevOps.WikiPDFExport\\AzureDevOps.WikiPDFExport\\bin\\Debug\\netcoreapp3.1\\example-footer.html",
33-
//"--header-url=C:\\Git\\AzureDevOps.WikiPDFExport\\AzureDevOps.WikiPDFExport\\bin\\Debug\\netcoreapp3.1\\example-header.html"
32+
"--footer-template-path=..\\example-footer.html",
33+
"--header-template-path=..\\example-header.html",
3434
//"-s..\\AzureDevOps.WikiPDFExport.Test\\Tests\\Real\\AzureDevOps.WikiPDFExport\\TEST%2DPAGE.md"
3535
//"-s..\\AzureDevOps.WikiPDFExport\\TEST%2DPAGE.md",
3636
//"--mermaidjs-path=mermaid.min.js",
@@ -40,7 +40,7 @@
4040
//"--filter=tags:test,tags:license"
4141
"--highlight-code",
4242
"--organization=https://dev.azure.com/mmelcher",
43-
"--pat=wdsenlsthdajotbtmej3t7pcqq2zqudf57at352ely4blsdjesfa" //add a 'a' to the end. valid until August 2022.
43+
"--pat=wdsenlsthdajotbtmej3t7pcqq2zqudf57at352ely4blsdjesf" //add a 'a' to the end. valid until August 2022.
4444
],
4545
"cwd": "${workspaceFolder}/AzureDevOps.WikiPDFExport",
4646
"console": "internalConsole",

AzureDevOps.WikiPDFExport/Program.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ public class Options
5757
[Option("header-template", Required = false, HelpText = "A HTML template for the header. Will be added on every page.")]
5858
public string HeaderTemplate { get; set; }
5959

60-
[Option("footer-url", Required = false, HelpText = "URL to an html file containing the footer")]
61-
public string FooterUrl { get; set; }
62-
[Option("header-url", Required = false, HelpText = "URL to an html file containing the header, does not work together with header-right, header-left or header-center")]
63-
public string HeaderUrl { get; set; }
60+
[Option("footer-template-path", Required = false, HelpText = "Path to an html file containing the footer")]
61+
public string FooterTemplatePath { get; set; }
62+
[Option("header-template-path", Required = false, HelpText = "Path to an html file containing the header, does not work together with header-right, header-left or header-center")]
63+
public string HeaderTemplatePath { get; set; }
6464

6565
[Option("css", Required = false, HelpText = "Path to a css file that is used for styling the PDF")]
6666
public string CSS { get; set; }

AzureDevOps.WikiPDFExport/WikiPDFExporter.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,32 @@ private async Task<string> ConvertHTMLToPDFAsync(string html)
313313

314314
//todo load header/footer template from file
315315
var pdfoptions = new PdfOptions();
316-
if (!string.IsNullOrEmpty(_options.HeaderTemplate) || !string.IsNullOrEmpty(_options.FooterTemplate))
316+
if (!string.IsNullOrEmpty(_options.HeaderTemplate)
317+
|| !string.IsNullOrEmpty(_options.FooterTemplate)
318+
|| !string.IsNullOrEmpty(_options.HeaderTemplatePath)
319+
|| !string.IsNullOrEmpty(_options.FooterTemplatePath))
317320
{
321+
322+
string footerTemplate = "";
323+
string headerTemplate = "";
324+
if (!string.IsNullOrEmpty(_options.HeaderTemplate))
325+
{
326+
headerTemplate = _options.HeaderTemplate;
327+
}
328+
else if (!string.IsNullOrEmpty(_options.HeaderTemplatePath))
329+
{
330+
headerTemplate = File.ReadAllText(_options.HeaderTemplatePath);
331+
}
332+
333+
if (!string.IsNullOrEmpty(_options.FooterTemplate))
334+
{
335+
footerTemplate = _options.FooterTemplate;
336+
}
337+
else if (!string.IsNullOrEmpty(_options.FooterTemplatePath))
338+
{
339+
footerTemplate = File.ReadAllText(_options.FooterTemplatePath);
340+
}
341+
318342
pdfoptions = new PdfOptions()
319343
{
320344
PreferCSSPageSize = false,
@@ -326,8 +350,8 @@ private async Task<string> ConvertHTMLToPDFAsync(string html)
326350
Left = "100px",
327351
Right = "100px"
328352
},
329-
HeaderTemplate = _options.HeaderTemplate,
330-
FooterTemplate = _options.FooterTemplate,
353+
HeaderTemplate = headerTemplate,
354+
FooterTemplate = footerTemplate,
331355
Format = PuppeteerSharp.Media.PaperFormat.A4
332356
};
333357
}
@@ -628,7 +652,7 @@ public void CorrectLinksAndImages(MarkdownObject document, FileInfo file, Markdo
628652
//convert images to base64 and embed them in the html. Chrome/Puppeter does not show local files because of security reasons.
629653
Byte[] bytes = File.ReadAllBytes(fileInfo.FullName);
630654
String base64 = Convert.ToBase64String(bytes);
631-
655+
632656
link.Url = $"data:image/{fileInfo.Extension};base64,{base64}";
633657
}
634658

AzureDevOps.WikiPDFExport/azuredevops-export-wiki.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929

3030
<ItemGroup>
3131
<PackageReference Include="CommandLineParser" Version="2.8.0" />
32-
<PackageReference Include="Markdig" Version="0.24.0" />
33-
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.17.0" />
32+
<PackageReference Include="Markdig" Version="0.26.0" />
33+
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.18.0" />
3434
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
3535
<PackageReference Include="Microsoft.VisualStudio.Services.Client" Version="16.170.0" />
3636
<PackageReference Include="Microsoft.TeamFoundationServer.Client" Version="16.170.0" />
3737
<PackageReference Include="Microsoft.VisualStudio.Services.InteractiveClient" Version="16.170.0" />
38-
<PackageReference Include="PuppeteerSharp" Version="4.0.0" />
38+
<PackageReference Include="PuppeteerSharp" Version="5.0.0" />
3939
</ItemGroup>
4040
</Project>

AzureDevOps.WikiPDFExport/export.pdf

-282 Bytes
Binary file not shown.

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## 🏎 Quickstart
2-
This tool exports a Azure DevOps wiki as PDF. Therefore, you need to git clone the target wiki to a computer. You can get the clone link of the wiki in the top right of the wiki homepage:
2+
This tool exports an Azure DevOps wiki as PDF. Therefore, you need to git clone the target wiki to a computer. You can get the clone link of the wiki in the top right of the wiki homepage:
33
![Clone a wiki](images/CloneWiki.png)
44

55
To clone this wiki, use the following command:
@@ -32,8 +32,9 @@ The tool currently supports the following:
3232

3333
## 🛰 Requirements
3434

35-
The tool is developed as .NET 5 application, therefore you need to have the runtime installed. Download is available [here](https://dotnet.microsoft.com/download).
36-
Currently it requires a x64 runtime.
35+
The tool is developed as .NET 5 application, therefore you need to have the runtime installed.
36+
Download is available [here](https://dotnet.microsoft.com/download).
37+
It requires a x64 windows runtime.
3738

3839
## 🔽 Download
3940

@@ -56,7 +57,7 @@ Debug mode. Logs tons of stuff and even exports the intermediate html file
5657
Disables the telemetry tracking, see [Telemetry](#telemetry)
5758
### --filter
5859
Filters the pages depending on the page [yaml tags](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#yaml-tags).
59-
### --footer-left, --footer-center, --footer-right, --header-left, --header-center, --header-right,
60+
### --footer-template, --header-template,
6061
Headers and footers can be added to the document by the --header-* and
6162
--footer* template arguments respectfully. In header and footer string supplied
6263
the following variables will be substituted. See [PDF options from puppeteer](https://pptr.dev/#?product=Puppeteer&show=api-pagepdfoptions).
@@ -65,7 +66,7 @@ Headers and footers can be added to the document by the --header-* and
6566
* [topage] Replaced by the number of the last page to be printed
6667
* [totalPages] Replaced by the current date in system local format
6768

68-
### --header-file, --footer-file
69+
### --footer-template-path, --header-template-path
6970
Provide a path to html files that will be added as header and footer. See [example-footer.html](example-footer.html), [example-header.html](example-header.html).
7071

7172
### --disableTelemetry
@@ -119,11 +120,13 @@ Please check if you have page file that are encoded (e.g. Test%20dFiles.md)
119120
### There is an error 'Qt: Could not initialize OLE (error 80010106)'.
120121
Yes, please ignore for now.
121122

123+
### Does it also work for Github?
124+
Yes, but there the .order files are missing to determine the sort order of pages. You would need to create them by yourself, but it is possible.
125+
122126
## ♥ Thanks
123127

124128
In this tool uses open source libraries that do the actual work - I just combined them to get the export as PDF:
125129
1. [CommandLineParser](https://github.com/commandlineparser/commandline) to parse the command line
126130
1. [MarkDig](https://github.com/lunet-io/markdig/) to parse markdown files to HTML.
127-
1. [DinkToPdf](https://github.com/rdvojmoc/DinkToPdf) to export HTML to PDF
128131
1. [dotnet-warp](https://github.com/Hubert-Rybak/dotnet-warp) to release a self-contained exe file
129132
1. [puppeteer-sharp](https://github.com/hardkoded/puppeteer-sharp) to convert mermaid markdown to SVG

azuredevops-export-wiki.exe

-4.05 MB
Binary file not shown.

example-footer.html

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,4 @@
1-
<!DOCTYPE html>
2-
<html lang='en-US'>
3-
4-
<head>
5-
<script>
6-
function subst() {
7-
var vars = {};
8-
var query_strings_from_url = document.location.search.substring(1).split('&');
9-
for (var query_string in query_strings_from_url) {
10-
if (query_strings_from_url.hasOwnProperty(query_string)) {
11-
var temp_var = query_strings_from_url[query_string].split('=', 2);
12-
vars[temp_var[0]] = decodeURI(temp_var[1]);
13-
}
14-
}
15-
var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
16-
for (var css_class in css_selector_classes) {
17-
if (css_selector_classes.hasOwnProperty(css_class)) {
18-
var element = document.getElementsByClassName(css_selector_classes[css_class]);
19-
for (var j = 0; j < element.length; ++j) {
20-
element[j].textContent = vars[css_selector_classes[css_class]];
21-
}
22-
}
23-
}
24-
}
25-
</script>
26-
</head>
27-
28-
<body style="border:0; margin: 0;" onload="subst()">
29-
<div style="border:0; margin: 0;">
30-
<div style="padding: 10px;">
31-
<div style="float:left"><span class="subsection"><!--will be replaced during conversion--></span></div>
32-
<div style="float:right" />Page <span class="page"><!--will be replaced during conversion--></span> of <span class="topage"><!--will be replaced during conversion--></span>
33-
</div>
34-
<div style="clear: both;" />
35-
</div>
36-
</body>
37-
38-
</html>
1+
<div
2+
style='padding-right: 10px; padding-top:2px; margin: 0; -webkit-print-color-adjust: exact; border-top:1px solid grey; color: grey; width: 100%; text-align: right; font-size: 6px;'>
3+
Print: <span class='date'></span> Page: </span><span class='pageNumber'></span>/<span class='totalPages'></span>
4+
</div>

example-header.html

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,3 @@
1-
<!DOCTYPE html>
2-
<html lang='en-US'>
3-
4-
<head>
5-
<script>
6-
function subst() {
7-
var vars = {};
8-
var query_strings_from_url = document.location.search.substring(1).split('&');
9-
for (var query_string in query_strings_from_url) {
10-
if (query_strings_from_url.hasOwnProperty(query_string)) {
11-
var temp_var = query_strings_from_url[query_string].split('=', 2);
12-
vars[temp_var[0]] = decodeURI(temp_var[1]);
13-
}
14-
}
15-
var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
16-
for (var css_class in css_selector_classes) {
17-
if (css_selector_classes.hasOwnProperty(css_class)) {
18-
var element = document.getElementsByClassName(css_selector_classes[css_class]);
19-
for (var j = 0; j < element.length; ++j) {
20-
element[j].textContent = vars[css_selector_classes[css_class]];
21-
}
22-
}
23-
}
24-
}
25-
</script>
26-
</head>
27-
28-
<body style="border:0; margin: 0;" onload="subst()">
29-
<div style="border:0; margin: 0;">
30-
<div style="padding: 10px;">
31-
<div style="float:left; font-size: 10pt"><span class="section"><!--will be replaced with the subsection --></span></div>
32-
<img style="float:right; margin-bottom: 5px;" src="http://placekitten.com/g/50/25" />
33-
</div>
34-
<div style="clear: both;" />
35-
</div>
36-
</body>
37-
38-
</html>
1+
<div
2+
style='padding-left: 10px; margin: 0; -webkit-print-color-adjust: exact; border-bottom:1px solid grey; color: grey; width: 100%; text-align: left; font-size: 6px;'>
3+
AzureDevOps.WikiPDFExport</div>

release-version.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# dotnet tool install --global dotnet-warp
22

3-
$version = "4.0.0-alpha"
3+
$version = "4.0.0-beta"
44
dotnet warp AzureDevOps.WikiPDFExport/azuredevops-export-wiki.csproj -p:Version=$version

0 commit comments

Comments
 (0)