├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── source code └── html-pdf-edge │ ├── html-pdf-edge-demo │ ├── Default.aspx │ ├── Default.aspx.cs │ ├── Default.aspx.designer.cs │ ├── Edge-logo.png │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── SimpleTest.aspx │ ├── SimpleTest.aspx.cs │ ├── SimpleTest.aspx.designer.cs │ ├── Textarea-As-Editor.aspx │ ├── Textarea-As-Editor.aspx.cs │ ├── Textarea-As-Editor.aspx.designer.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── apiGetPDF.aspx │ ├── apiGetPDF.aspx.cs │ ├── apiGetPDF.aspx.designer.cs │ ├── bindCodeEditorShortcutKeys.js │ ├── favicon.ico │ ├── highlight.min.js │ ├── html-pdf-edge-demo.csproj │ ├── loading.gif │ ├── pdf.jpg │ ├── sample_html │ │ ├── basic.html │ │ ├── form1.html │ │ ├── immenseart1.html │ │ ├── invoice1.html │ │ ├── invoice2.html │ │ ├── invoice3.html │ │ ├── invoice4.html │ │ ├── logo_invoice2.png │ │ └── logo_invoice3.png │ └── vs2015.min.css │ ├── html-pdf-edge.sln │ └── html-pdf-edge │ ├── html-pdf-edge.csproj │ └── html-to-pdf-edge.cs └── wiki ├── loading.gif ├── loading.png ├── screenshot1.png ├── screenshot2.png ├── screenshot3.png └── screenshot4.png /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-detectable=false 2 | *.aspx linguist-detectable=false 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Convert HTML to PDF by Using Microsoft Edge 2 | 3 | Live Demo: [http://html-pdf-edge.adriancs.com/](http://html-pdf-edge.adriancs.com/) 4 | 5 | Nuget: [https://www.nuget.org/packages/Html-PDF-Edge](https://www.nuget.org/packages/Html-PDF-Edge) 6 | 7 | PM> NuGet\Install-Package Html-PDF-Edge 8 | 9 | ## Usage 10 | 11 | Install the Nuget Package, or download the source code. Extract and add the C# class file `html-pdf-edge.cs` into your project. 12 | 13 | Available methods: 14 | 15 | - `PDF.GeneratePdf(string urlHtml, string filePathPDF)` 16 | - `PDF.PublishUrl(string url, string filenamePdf, TransmitMethod transmitMethod)` 17 | - `PDF.PublishHtmlInline(string htmlContent)` 18 | - `PDF.PublishHtmlAttachment(string htmlContent, string filenamePdf)` 19 | - `PDF.PublishHtml(string htmlContent, string filenamePdf, TransmitMethod transmitMethod)` 20 | 21 | ---- 22 | ## Example of Usage 23 | 24 | `PDF.GeneratePdf` 25 | ---- 26 | 27 | ```cs 28 | string url = "https://www.adriancs.com/demo/invoice.html"; 29 | string url = "file:///C:/Users/Username/Documents/invoice.html"; 30 | string filePathPDF = @"C:\file.pdf"; 31 | PDF.GeneratePdf(url, filePathPDF); 32 | ``` 33 | 34 | `PDF.PublishUrl` 35 | ---- 36 | 37 | ```cs 38 | public enum TransmitMethod 39 | { 40 | None, // save the pdf and do nothing 41 | Attachment, // transmit the pdf as attachment 42 | Inline, // transmit the pdf and show it in browser 43 | Redirect // redirect the browser to the url of the pdf 44 | } 45 | 46 | PDF.TransmitMethod transmitMethod = PDF.TransmitMethod.Inline; 47 | PDF.PublishUrl(url, "file.pdf", transmitMethod); 48 | ``` 49 | 50 | `PDF.PublishHtmlInline` 51 | ---- 52 | 53 | ```cs 54 | string html = "

Hello

"; 55 | PDF.PublishHtmlInline(html); 56 | ``` 57 | 58 | `PDF.PublishHtmlAttachment` 59 | ---- 60 | 61 | ```cs 62 | string html = "

Hello

"; 63 | PDF.PublishHtmlAttachment(html, "file.pdf"); 64 | ``` 65 | 66 | `PDF.PublishHtml` 67 | ---- 68 | 69 | ```cs 70 | PDF.TransmitMethod transmitMethod = PDF.TransmitMethod.Inline; 71 | PDF.PublishHtml(html, "file.pdf", transmitMethod); 72 | ``` 73 | 74 | ## Important CSS Properties For Generating PDF 75 | There are a few necessary CSS that you have to include in the HTML page in order for this to work properly. 76 | 77 | 1. Set page margin to 0 (zero) 78 | 2. Set paper size 79 | 3. Wrap all content within a "div" with fixed width and margin 80 | 4. Use CSS of page-break-always to split between pages. 81 | 5. All fonts must already installed or hosted in your website 82 | 6. URL links for images, external css stylesheet reference must include the root path. 83 | 84 | **1. Set page margin to 0 (zero)** 85 | ``` 86 | @page { 87 | margin: 0; 88 | } 89 | ``` 90 | The purpose of doing this is to hide the header and footer: 91 | 92 | ![](https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/main/wiki/screenshot4.png) 93 | 94 | **2. Set paper size** 95 | 96 | Example 1: 97 | ``` 98 | @page { 99 | margin: 0; 100 | size: A4 portrait; 101 | } 102 | ``` 103 | Example 2: 104 | ``` 105 | @page { 106 | margin: 0; 107 | size: letter landscape; 108 | } 109 | ``` 110 | Example 3: custom size (inch) *width then height 111 | ``` 112 | @page { 113 | margin: 0; 114 | size: 4in 6in; 115 | } 116 | ``` 117 | Example 4: custom size (cm) *width then height 118 | ``` 119 | @page { 120 | margin: 0; 121 | size: 14cm 14cm; 122 | } 123 | ``` 124 | For more options/info on the CSS of @page, you may refer: 125 | 126 | https://developer.mozilla.org/en-US/docs/Web/CSS/@page/size 127 | 128 | **3. Wrap all content within a DIV with fixed width and margin** 129 | 130 | Example: 131 | ``` 132 |
133 |

Page 1

134 | 135 | 136 |
137 | ``` 138 | Style the "div" with class "page" (act as the main block/wrapper/container). Since the page has zero margin, we need to manually specified the top margin in CSS: 139 | ``` 140 | CSS 141 | .page { 142 | width: 18cm; 143 | margin: auto; 144 | margin-top: 10mm; 145 | } 146 | ``` 147 | The **width** has to be specified. 148 | 149 | The "**margin: auto**" will align the div block at center horizontally. 150 | 151 | "**margin-top: 10mm**", will provide space between the main block and the edge of the paper at top section. 152 | 153 | **4. Use CSS of "page-break-always" to split between pages.** 154 | 155 | To split pages, use a "div" and style with CSS of "page-break-after". 156 | ``` 157 | page-break-after: always 158 | ``` 159 | Example: 160 | ``` 161 |
162 |

Page 1

163 | 164 |
165 | 166 |
167 | 168 |
169 |

Page 2

170 | 171 |
172 | 173 |
174 | 175 |
176 |

Page 3

177 | 178 |
179 | ``` 180 | **5. All fonts must already installed or hosted in your website** 181 | 182 | The font rendering might not be working properly if the fonts are hosted at 3rd party's server, for example: Google Fonts. Try install the fonts into your server Windows OS or host the fonts within your website. 183 | 184 | **6. URL links for images, external css stylesheet reference must include the root path.** 185 | 186 | For example, the following img tag might not be rendered properly. The image has the potential to be missing in the final rendered PDF output. 187 | 188 | ``` 189 | 190 | 191 | ``` 192 | In stead, include the root path like this: 193 | ``` 194 | 195 | 196 | ``` 197 | 198 | ## The sample of full HTML page: 199 | ``` 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | Document 208 | 226 | 227 | 228 | 229 | 230 |
231 |

Page 1

232 | 233 |
234 | 235 |
236 | 237 |
238 |

Page 2

239 | 240 |
241 | 242 |
243 | 244 |
245 |

Page 3

246 | 247 |
248 | 249 | 250 | 251 | 252 | ``` 253 | 254 | ## How Does It Works Under the Hood 255 | 256 | Microsoft Edge is a chromium based web browser which includes a built-in function that can generate PDF from HTML (or convert HTML to PDF). 257 | 258 | Here's the basic command line: 259 | 260 | ``` 261 | msedge --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf="{filePath}" {url} 262 | ``` 263 | 264 | Example of command line with parameters: 265 | 266 | ``` 267 | msedge --headless --disable-gpu --run-all-compositor-stages-before-draw 268 | --print-to-pdf="D:\\www.mysite.com\temp\pdf\2059060194.pdf" 269 | http://localhost:50964/temp/pdf/2059060194.html 270 | ``` 271 | 272 | This project is basically gathered the values and uses a process to execute the command line: 273 | 274 | ```cs 275 | using System.Diagnostics; 276 | 277 | using (var p = new Process()) 278 | { 279 | p.StartInfo.FileName = "msedge"; 280 | p.StartInfo.Arguments = $"--headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf=\"{filePath}\" {url}"; 281 | p.Start(); 282 | p.WaitForExit(); 283 | } 284 | ``` 285 | 286 | Above code will generate the PDF and save it at the location `filePath`, then it can be further transmitted for download. 287 | 288 | Since Google Chrome is also a Chromium based web browser, it can also be run with the same command line. You can check out my another PDF generator which is by using Google Chrome to convert HTML to PDF. 289 | 290 | Here: [https://github.com/adriancs2/HTML-PDF-Chrome](https://github.com/adriancs2/HTML-PDF-Chrome) 291 | 292 | ## Running in Web Hosting Environment 293 | 294 | I have tested this implementation (using Edge) in the following environment: 295 | 296 | - Local IIS hosting 297 | - Web Hosting (smarterasp.net) 298 | - VPS Web Hosting 299 | 300 | All above environment are able to generate PDF without issues. It runs smoothly without the need to configure the permission, Application Pool Identity and Website IIS authentication. 301 | 302 | The following screenshot shows that the execution of MS Edge is allowed with default permission settings: 303 | 304 | ![](https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/main/wiki/screenshot2.png) 305 | 306 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="System.Default" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 |
156 | 157 |

158 | 159 | Convert HTML to PDF by Using Microsoft Edge in ASP.NET 160 |

161 | 162 | Project Site: github.com | 163 | adriancs.com | 164 | CodeProject.com | 165 | Nuget: https://www.nuget.org/packages/html-pdf-edge 166 | 167 |
168 | 169 |
170 | 171 |
172 | Load Sample HTML: 173 | basic 174 | form1 175 | invoice1 176 | invoice2 177 | invoice3 178 | invoice4 179 |
180 | 181 | Special Thanks to: htmlpdfapi.com and Document Templates provided by Microsoft Word 2021 for sample HTML. 182 | 183 |
184 | 185 |
186 | Generate PDF: 187 | Using AJAX 188 | Using Fetch API 189 | 190 | 191 |
192 |
193 | 194 |
195 | 196 | Edit HTML Here: 197 |
198 |
199 | 200 |
201 | 202 |
203 | Shortcut Keys:
204 | [Enter]: Maintain indentation as previous line.
205 | [Tab] / [Shift]+[Tab]: Increase/decrease indentation (multiline supported)
206 | [Shift] + [Del]/[Backspace]: Delete entire row.
207 | [Home]: Move cursor to the front of first non-white space character.
208 |
209 | Read More About Tranform Textarea Into Code Editor With Syntax Highlight Support 210 | 211 |
212 | 213 |
214 |
215 | Generating PDF... 216 |
217 | 218 |
219 | 220 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Web; 6 | using System.Web.UI; 7 | using System.Web.UI.WebControls; 8 | 9 | namespace System 10 | { 11 | public partial class Default : System.Web.UI.Page 12 | { 13 | protected void Page_Load(object sender, EventArgs e) 14 | { 15 | 16 | } 17 | 18 | protected void btPreview_Click(object sender, EventArgs e) 19 | { 20 | Response.Clear(); 21 | Response.Write(textarea1.Text); 22 | Response.End(); 23 | } 24 | 25 | protected void btGeneratePdfAttachment_Click(object sender, EventArgs e) 26 | { 27 | PDF.PublishHtmlAttachment(textarea1.Text, "file.pdf"); 28 | } 29 | 30 | protected void btGeneratePdfInline_Click(object sender, EventArgs e) 31 | { 32 | PDF.PublishHtmlInline(textarea1.Text); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace System 11 | { 12 | 13 | 14 | public partial class Default 15 | { 16 | 17 | /// 18 | /// form1 control. 19 | /// 20 | /// 21 | /// Auto-generated field. 22 | /// To modify move field declaration from designer file to code-behind file. 23 | /// 24 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 25 | 26 | /// 27 | /// btGeneratePdfAttachment control. 28 | /// 29 | /// 30 | /// Auto-generated field. 31 | /// To modify move field declaration from designer file to code-behind file. 32 | /// 33 | protected global::System.Web.UI.WebControls.Button btGeneratePdfAttachment; 34 | 35 | /// 36 | /// btGeneratePdfInline control. 37 | /// 38 | /// 39 | /// Auto-generated field. 40 | /// To modify move field declaration from designer file to code-behind file. 41 | /// 42 | protected global::System.Web.UI.WebControls.Button btGeneratePdfInline; 43 | 44 | /// 45 | /// btPreview control. 46 | /// 47 | /// 48 | /// Auto-generated field. 49 | /// To modify move field declaration from designer file to code-behind file. 50 | /// 51 | protected global::System.Web.UI.WebControls.Button btPreview; 52 | 53 | /// 54 | /// textarea1 control. 55 | /// 56 | /// 57 | /// Auto-generated field. 58 | /// To modify move field declaration from designer file to code-behind file. 59 | /// 60 | protected global::System.Web.UI.WebControls.TextBox textarea1; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Edge-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/Edge-logo.png -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("html_pdf_edge")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("html_pdf_edge")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6f6385bf-ad09-40d7-aabd-304d761ec9fb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace System.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/SimpleTest.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SimpleTest.aspx.cs" Inherits="System.SimpleTest" %> 2 | 3 | 4 | 5 | 6 | 7 | Simple Test 8 | 13 | 14 | 15 |

Simple Test

16 |
17 | 18 | 19 | 20 |

21 | 22 |

23 | 24 |

25 | 26 |

27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/SimpleTest.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | using System.Net.Http; 8 | using System.Threading.Tasks; 9 | 10 | namespace System 11 | { 12 | public partial class SimpleTest : System.Web.UI.Page 13 | { 14 | string url = "https://www.adriancs.com/demo/invoice.html"; 15 | // string url = "file:///C:/Users/Username/Documents/invoice.html"; 16 | 17 | protected void Page_Load(object sender, EventArgs e) 18 | { 19 | 20 | } 21 | 22 | string GetHtml() 23 | { 24 | HttpClient client = new HttpClient(); 25 | HttpResponseMessage response = client.GetAsync(url).Result; 26 | string html = response.Content.ReadAsStringAsync().Result; 27 | return html; 28 | } 29 | 30 | protected void btGeneratePdf_Click(object sender, EventArgs e) 31 | { 32 | string filePathPDF = Server.MapPath("~/file.pdf"); 33 | PDF.GeneratePdf(url, filePathPDF); 34 | 35 | ph1.Controls.Add(new LiteralControl($"Done! File downloaded at: {filePathPDF}")); 36 | } 37 | 38 | protected void btPublishUrl_Click(object sender, EventArgs e) 39 | { 40 | PDF.TransmitMethod transmitMethod = PDF.TransmitMethod.Inline; 41 | PDF.PublishUrl(url, "file.pdf", transmitMethod); 42 | } 43 | 44 | protected void btPublishHtmlInline_Click(object sender, EventArgs e) 45 | { 46 | string html = GetHtml(); 47 | PDF.PublishHtmlInline(html); 48 | } 49 | 50 | protected void btPublishHtmlAttachment_Click(object sender, EventArgs e) 51 | { 52 | string html = GetHtml(); 53 | PDF.PublishHtmlAttachment(html, "file.pdf"); 54 | } 55 | 56 | protected void btPublishHtml_Click(object sender, EventArgs e) 57 | { 58 | string html = GetHtml(); 59 | PDF.TransmitMethod transmitMethod = PDF.TransmitMethod.Inline; 60 | PDF.PublishHtml(html, "file.pdf", transmitMethod); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/SimpleTest.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace System 11 | { 12 | 13 | 14 | public partial class SimpleTest 15 | { 16 | 17 | /// 18 | /// form1 control. 19 | /// 20 | /// 21 | /// Auto-generated field. 22 | /// To modify move field declaration from designer file to code-behind file. 23 | /// 24 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 25 | 26 | /// 27 | /// btGeneratePdf control. 28 | /// 29 | /// 30 | /// Auto-generated field. 31 | /// To modify move field declaration from designer file to code-behind file. 32 | /// 33 | protected global::System.Web.UI.WebControls.Button btGeneratePdf; 34 | 35 | /// 36 | /// ph1 control. 37 | /// 38 | /// 39 | /// Auto-generated field. 40 | /// To modify move field declaration from designer file to code-behind file. 41 | /// 42 | protected global::System.Web.UI.WebControls.PlaceHolder ph1; 43 | 44 | /// 45 | /// btPublishUrl control. 46 | /// 47 | /// 48 | /// Auto-generated field. 49 | /// To modify move field declaration from designer file to code-behind file. 50 | /// 51 | protected global::System.Web.UI.WebControls.Button btPublishUrl; 52 | 53 | /// 54 | /// btPublishHtmlInline control. 55 | /// 56 | /// 57 | /// Auto-generated field. 58 | /// To modify move field declaration from designer file to code-behind file. 59 | /// 60 | protected global::System.Web.UI.WebControls.Button btPublishHtmlInline; 61 | 62 | /// 63 | /// btPublishHtmlAttachment control. 64 | /// 65 | /// 66 | /// Auto-generated field. 67 | /// To modify move field declaration from designer file to code-behind file. 68 | /// 69 | protected global::System.Web.UI.WebControls.Button btPublishHtmlAttachment; 70 | 71 | /// 72 | /// btPublishHtml control. 73 | /// 74 | /// 75 | /// Auto-generated field. 76 | /// To modify move field declaration from designer file to code-behind file. 77 | /// 78 | protected global::System.Web.UI.WebControls.Button btPublishHtml; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Textarea-As-Editor.aspx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | This page of code is moved to:

8 | 9 | 10 | 11 | https://github.com/adriancs2/textarea-syntax-highlight 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Textarea-As-Editor.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace System 9 | { 10 | public partial class WebForm2 : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Textarea-As-Editor.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace System 11 | { 12 | 13 | 14 | public partial class WebForm2 15 | { 16 | 17 | /// 18 | /// form1 control. 19 | /// 20 | /// 21 | /// Auto-generated field. 22 | /// To modify move field declaration from designer file to code-behind file. 23 | /// 24 | protected global::System.Web.UI.HtmlControls.HtmlForm form1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/apiGetPDF.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="apiGetPDF.aspx.cs" Inherits="System.apiGetPDF" %> -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/apiGetPDF.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.UI; 6 | using System.Web.UI.WebControls; 7 | 8 | namespace System 9 | { 10 | public partial class apiGetPDF : System.Web.UI.Page 11 | { 12 | protected void Page_Load(object sender, EventArgs e) 13 | { 14 | string text = Request.Form["text"] + ""; 15 | 16 | if (text.Length == 0) 17 | { 18 | return; 19 | } 20 | 21 | PDF.PublishHtmlInline(text); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/apiGetPDF.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace System 11 | { 12 | 13 | 14 | public partial class apiGetPDF 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/bindCodeEditorShortcutKeys.js: -------------------------------------------------------------------------------- 1 | // applying shortcut keys 2 | function bindCodeEditorShortcutKeys(ta) { 3 | 4 | try { 5 | 6 | ta.addEventListener('keydown', function (e) { 7 | 8 | // [Enter] key pressed detected 9 | if (e.key === 'Enter') { 10 | 11 | // Prevent the default behavior (new line) 12 | e.preventDefault(); 13 | 14 | // Get the cursor position 15 | var cursorPos = this.selectionStart; 16 | 17 | // Get the previous line 18 | var prevLine = this.value.substring(0, cursorPos).split('\n').slice(-1)[0]; 19 | 20 | // Get the indentation of the previous line 21 | var indent = prevLine.match(/^\s*/)[0]; 22 | 23 | // Add a new line with the same indentation 24 | this.setRangeText('\n' + indent, cursorPos, cursorPos, 'end'); 25 | 26 | // remove focus 27 | this.blur(); 28 | 29 | // regain focus (this is force the textarea scroll to caret position in case the caret falls out the textarea visible area) 30 | this.focus(); 31 | 32 | // copy the code from textarea to code block 33 | updateCode(); 34 | return; 35 | } 36 | 37 | // [Tab] pressed, but no [Shift] 38 | if (e.key === "Tab" && !e.shiftKey && 39 | 40 | // and no highlight detected 41 | this.selectionStart == this.selectionEnd) { 42 | 43 | // suspend default behaviour 44 | e.preventDefault(); 45 | 46 | // Get the current cursor position 47 | let cursorPosition = this.selectionStart; 48 | 49 | // Insert 4 white spaces at the cursor position 50 | let newValue = this.value.substring(0, cursorPosition) + " " + 51 | this.value.substring(cursorPosition); 52 | 53 | // Update the textarea value and cursor position 54 | this.value = newValue; 55 | this.selectionStart = cursorPosition + 4; 56 | this.selectionEnd = cursorPosition + 4; 57 | 58 | // copy the code from textarea to code block 59 | updateCode(); 60 | return; 61 | } 62 | 63 | // [Tab] and [Shift] keypress presence 64 | if (e.key === "Tab" && e.shiftKey && 65 | 66 | // no highlight detected 67 | this.selectionStart == this.selectionEnd) { 68 | 69 | // suspend default behaviour 70 | e.preventDefault(); 71 | 72 | // Get the current cursor position 73 | let cursorPosition = this.selectionStart; 74 | 75 | // Check the previous characters for spaces 76 | let leadingSpaces = 0; 77 | for (let i = 0; i < 4; i++) { 78 | if (this.value[cursorPosition - i - 1] === " ") { 79 | leadingSpaces++; 80 | } else { 81 | break; 82 | } 83 | } 84 | 85 | if (leadingSpaces > 0) { 86 | // Remove the spaces 87 | let newValue = this.value.substring(0, cursorPosition - leadingSpaces) + 88 | this.value.substring(cursorPosition); 89 | 90 | // Update the textarea value and cursor position 91 | this.value = newValue; 92 | this.selectionStart = cursorPosition - leadingSpaces; 93 | this.selectionEnd = cursorPosition - leadingSpaces; 94 | } 95 | 96 | // copy the code from textarea to code block 97 | updateCode(); 98 | return; 99 | } 100 | 101 | // [Tab] key pressed and range selection detected 102 | if (e.key == 'Tab' & this.selectionStart != this.selectionEnd) { 103 | e.preventDefault(); 104 | 105 | // split the textarea content into lines 106 | let lines = this.value.split('\n'); 107 | 108 | // find the start/end lines 109 | let startPos = this.value.substring(0, this.selectionStart).split('\n').length - 1; 110 | let endPos = this.value.substring(0, this.selectionEnd).split('\n').length - 1; 111 | 112 | // calculating total removed white spaces 113 | // these values will be used for adjusting new cursor position 114 | let spacesRemovedFirstLine = 0; 115 | let spacesRemoved = 0; 116 | 117 | // [Shift] key was pressed (this means we're un-indenting) 118 | if (e.shiftKey) { 119 | 120 | // iterate over all lines 121 | for (let i = startPos; i <= endPos; i++) { 122 | 123 | // /^ = from the start of the line, 124 | // {1,4} = remove in between 1 to 4 white spaces that may existed 125 | lines[i] = lines[i].replace(/^ {1,4}/, function (match) { 126 | 127 | // "match" is a string (white space) extracted 128 | 129 | // obtaining total white spaces removed 130 | 131 | // total white space removed at first line 132 | if (i == startPos) 133 | spacesRemovedFirstLine = match.length; 134 | 135 | // total white space removed overall 136 | spacesRemoved += match.length; 137 | 138 | return ''; 139 | }); 140 | } 141 | } 142 | 143 | // no shift key, so we're indenting 144 | else { 145 | // iterate over all lines 146 | for (let i = startPos; i <= endPos; i++) { 147 | // add a tab to the start of the line 148 | lines[i] = ' ' + lines[i]; // four spaces 149 | } 150 | } 151 | 152 | // remember the cursor position 153 | let start = this.selectionStart; 154 | let end = this.selectionEnd; 155 | 156 | // put the modified lines back into the textarea 157 | this.value = lines.join('\n'); 158 | 159 | // adjust the position of cursor start selection 160 | this.selectionStart = e.shiftKey ? 161 | start - spacesRemovedFirstLine : start + 4; 162 | 163 | // adjust the position of cursor end selection 164 | this.selectionEnd = e.shiftKey ? 165 | end - spacesRemoved : end + 4 * (endPos - startPos + 1); 166 | 167 | // copy the code from textarea to code block 168 | updateCode(); 169 | return; 170 | } 171 | 172 | // [Shift] + [Del]/[Backspace] = Delete entire line(s) 173 | if (e.shiftKey && (e.key === "Delete" || e.key === "Backspace")) { 174 | 175 | e.preventDefault(); 176 | 177 | // find the start/end lines 178 | let startPos = this.value.substring(0, this.selectionStart).split('\n').length - 1; 179 | let endPos = this.value.substring(0, this.selectionEnd).split('\n').length - 1; 180 | 181 | // get the line and the position in that line where the cursor is 182 | // pop() = take out the last line (which is the cursor selection start located) 183 | let cursorLine = this.value.substring(0, this.selectionStart).split('\n').pop(); 184 | 185 | // get the position of cursor within the last line 186 | let cursorPosInLine = cursorLine.length; 187 | 188 | // calculating total lines to be removed 189 | let totalLinesRemove = endPos - startPos + 1; 190 | 191 | // split the textarea content into lines 192 | let lines = this.value.split('\n'); 193 | 194 | // calculate new cursor position 195 | let newStart = lines.slice(0, startPos).join('\n').length + (startPos > 0 ? 1 : 0); 196 | // add 1 if startPos > 0 to account for '\n' character 197 | 198 | // remove the selected lines 199 | lines.splice(startPos, totalLinesRemove); 200 | 201 | // get the new line where the cursor will be after deleting lines 202 | // if lines[startPos] is not existed, then the new line will be an empty string 203 | let newLine = lines[startPos] || ''; 204 | 205 | // if the new line is shorter than the cursor position, put the cursor at the end of the line 206 | if (newLine.length < cursorPosInLine) { 207 | cursorPosInLine = newLine.length; 208 | } 209 | 210 | // adjuct the cursor's position in the line to the new cursor position 211 | newStart += cursorPosInLine; 212 | 213 | // put the modified lines back into the textarea 214 | this.value = lines.join('\n'); 215 | 216 | // set the new cursor position 217 | // both cursor selection start and end will be at the same position 218 | this.selectionStart = this.selectionEnd = newStart; 219 | 220 | // copy the code from textarea to code block 221 | updateCode(); 222 | return; 223 | } 224 | 225 | // Move cursor to the first non-white space character 226 | if (e.key === "Home") { 227 | 228 | // get the line and the position in that line where the cursor is 229 | // pop() = take out the last line (which is the cursor selection start located) 230 | let line = this.value.substring(0, this.selectionStart).split('\n').pop(); 231 | 232 | // get the position of cursor within the last line 233 | let cursorPosInLine = line.length; 234 | 235 | // Find the start of the current line 236 | let lineStartPos = this.value.substring(0, this.selectionStart).lastIndexOf('\n') + 1; 237 | 238 | // Find the first non-whitespace character on the line 239 | let firstNonWhitespacePos = line.search(/\S/); 240 | 241 | // the cursor's position is already in front of first non-whitespace character, 242 | // or it's position is before first none-whitespace character, 243 | // move the cursor to the start of line 244 | if (firstNonWhitespacePos >= cursorPosInLine) { 245 | // do nothing, perform default behaviour, which is moving the cursor to beginning of the line 246 | return true; 247 | } 248 | // If there's no non-whitespace character, this is an empty or whitespace-only line 249 | else if (firstNonWhitespacePos === -1) { 250 | // do nothing, perform default behaviour, which is moving the cursor to beginning of the line 251 | return true; 252 | } 253 | 254 | // Prevent the default Home key behavior 255 | e.preventDefault(); 256 | 257 | // Move the cursor to the position of the first non-whitespace character 258 | this.selectionStart = this.selectionEnd = lineStartPos + firstNonWhitespacePos; 259 | 260 | return; 261 | } 262 | 263 | }); 264 | } 265 | catch (err) { 266 | alert(err); 267 | } 268 | } -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/favicon.ico -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/html-pdf-edge-demo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {6F6385BF-AD09-40D7-AABD-304D761EC9FB} 10 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 11 | Library 12 | Properties 13 | System 14 | html-pdf-edge-demo 15 | v4.8 16 | true 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | true 28 | full 29 | false 30 | bin\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | 35 | 36 | true 37 | pdbonly 38 | true 39 | bin\ 40 | TRACE 41 | prompt 42 | 4 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | apiGetPDF.aspx 91 | ASPXCodeBehind 92 | 93 | 94 | apiGetPDF.aspx 95 | 96 | 97 | Default.aspx 98 | ASPXCodeBehind 99 | 100 | 101 | Default.aspx 102 | 103 | 104 | 105 | True 106 | True 107 | Settings.settings 108 | 109 | 110 | SimpleTest.aspx 111 | ASPXCodeBehind 112 | 113 | 114 | SimpleTest.aspx 115 | 116 | 117 | Textarea-As-Editor.aspx 118 | ASPXCodeBehind 119 | 120 | 121 | Textarea-As-Editor.aspx 122 | 123 | 124 | 125 | 126 | SettingsSingleFileGenerator 127 | Settings.Designer.cs 128 | 129 | 130 | Web.config 131 | 132 | 133 | Web.config 134 | 135 | 136 | 137 | 138 | {c698502d-45cf-4da6-823a-4650c650286d} 139 | html-pdf-edge 140 | 141 | 142 | 143 | 10.0 144 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | True 154 | True 155 | 50964 156 | / 157 | http://localhost:50964/ 158 | False 159 | False 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | 174 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/loading.gif -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/pdf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/pdf.jpg -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/basic.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 28 | 29 | 30 | 31 | 32 |
33 |

Page 1

34 | 35 |
36 | 37 |
38 | 39 |
40 |

Page 2

41 | 42 |
43 | 44 |
45 | 46 |
47 |

Page 3

48 | 49 |
50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/immenseart1.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Order confirmation 6 | 7 | 8 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 203 | 204 |
131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 200 | 201 |
141 | 142 | 143 | 144 | 196 | 197 | 198 |
145 | 146 | 147 | 148 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 164 | 165 | 166 |
149 | logo 150 |
160 | Hello, Philip Brooks. 161 |
162 | Thank you for shopping from our store and for your order. 163 |
167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 192 | 193 | 194 |
177 | Invoice 178 |
189 | ORDER #800000025
190 | MARCH 4TH 2016 191 |
195 |
199 |
202 |
205 | 206 | 207 | 208 | 209 | 210 | 274 | 275 | 276 |
211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 267 | 268 | 269 | 270 | 271 | 272 |
222 | 223 | 224 | 225 | 228 | 231 | 234 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 |
226 | Item 227 | 229 | SKU 230 | 232 | Quantity 233 | 235 | Subtotal 236 |
246 | Beats Studio Over-Ear Headphones 247 | MH792AM/A1$299.95
Beats RemoteTalk CableMHDV2G/A1$29.95
266 |
273 |
277 | 278 | 279 | 280 | 281 | 282 | 330 | 331 | 332 |
283 | 284 | 285 | 286 | 326 | 327 | 328 |
287 | 288 | 289 | 290 | 291 | 292 | 295 | 298 | 299 | 300 | 303 | 306 | 307 | 308 | 311 | 314 | 315 | 316 | 317 | 320 | 321 | 322 |
293 | Subtotal 294 | 296 | $329.90 297 |
301 | Shipping & Handling 302 | 304 | $15.00 305 |
309 | Grand Total (Incl.Tax) 310 | 312 | $344.90 313 |
TAX 318 | $72.40 319 |
323 | 324 | 325 |
329 |
333 | 334 | 335 | 336 | 337 | 338 | 480 | 481 | 482 |
339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 406 | 407 | 408 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 |
350 | 351 | 352 | 353 | 402 | 403 | 404 |
354 | 355 | 356 | 357 | 358 | 361 | 362 | 363 | 364 | 365 | 366 | 373 | 374 | 375 |
359 | BILLING INFORMATION 360 |
367 | Philip Brooks
368 | Public Wales, Somewhere
369 | New York NY
370 | 4468, United States
371 | T: 202-555-0133 372 |
376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 387 | 388 | 389 | 390 | 391 | 392 | 398 | 399 | 400 |
385 | PAYMENT METHOD 386 |
393 | Credit Card
394 | Credit Card Type: Visa
395 | Worldpay Transaction ID: 4185939336
396 | Right of Withdrawal 397 |
401 |
405 |
409 | 410 | 411 | 412 | 466 | 467 | 468 |
413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 425 | 426 | 427 | 428 | 429 | 430 | 437 | 438 | 439 |
423 | SHIPPING INFORMATION 424 |
431 | Sup Inc
432 | Another Place, Somewhere
433 | New York NY
434 | 4468, United States
435 | T: 202-555-0171 436 |
440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 454 | 455 | 456 | 457 | 458 | 459 | 462 | 463 | 464 |
452 | SHIPPING METHOD 453 |
460 | UPS: U.S. Shipping Services 461 |
465 |
469 |
479 |
483 | 484 | 485 | 486 | 487 | 508 | 509 | 510 | 511 | 512 |
488 | 489 | 490 | 501 | 502 | 503 | 504 | 505 | 506 |
491 | 492 | 493 | 494 | 497 | 498 | 499 |
495 | Have a nice day. 496 |
500 |
507 |
513 | 514 | 515 | 516 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/invoice1.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Example 3 7 | 218 | 219 | 220 | 221 |
222 |
223 |

DATE
August 17, 2015
INVOICE 3-2-1 DUE DATE
September 17, 2015

224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
277 |
278 |
279 |
PROJECT Website development
280 |
CLIENT John Doe
281 |
ADDRESS 796 Silver Harbour, TX 79273, US
282 | 283 |
284 |
285 |
Company Name COMPANY
286 |
455 Foggy Heights, AZ 85004, US ADDRESS
287 |
(602) 519-0450 PHONE
288 | 289 |
290 |
291 |
292 |
NOTICE:
293 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
294 |
295 |
296 |
297 | Invoice was created on a computer and is valid without the signature and seal. 298 |
299 |
300 | 301 |
302 | 303 |
304 |
305 |

DATE
August 17, 2015
INVOICE 3-2-1 DUE DATE
September 17, 2015

306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
359 |
360 |
361 |
PROJECT Website development
362 |
CLIENT John Doe
363 |
ADDRESS 796 Silver Harbour, TX 79273, US
364 | 365 |
366 |
367 |
Company Name COMPANY
368 |
455 Foggy Heights, AZ 85004, US ADDRESS
369 |
(602) 519-0450 PHONE
370 | 371 |
372 |
373 |
374 |
NOTICE:
375 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
376 |
377 |
378 |
379 | Invoice was created on a computer and is valid without the signature and seal. 380 |
381 |
382 | 383 |
384 | 385 |
386 |
387 |

DATE
August 17, 2015
INVOICE 3-2-1 DUE DATE
September 17, 2015

388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
441 |
442 |
443 |
PROJECT Website development
444 |
CLIENT John Doe
445 |
ADDRESS 796 Silver Harbour, TX 79273, US
446 | 447 |
448 |
449 |
Company Name COMPANY
450 |
455 Foggy Heights, AZ 85004, US ADDRESS
451 |
(602) 519-0450 PHONE
452 | 453 |
454 |
455 |
456 |
NOTICE:
457 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
458 |
459 |
460 |
461 | Invoice was created on a computer and is valid without the signature and seal. 462 |
463 |
464 | 465 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/invoice2.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Example 2 7 | 212 | 213 | 214 | 215 |
216 |
217 | 220 |
221 |

Company Name

222 |
455 Foggy Heights, AZ 85004, US
223 |
(602) 519-0450
224 | 225 |
226 |
227 |
228 |
229 |
230 |
INVOICE TO:
231 |

John Doe

232 |
796 Silver Harbour, TX 79273, US
233 | 234 |
235 |
236 |

INVOICE 3-2-1

237 |
Date of Invoice: 01/06/2014
238 |
Due Date: 30/06/2014
239 |
240 |
241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 |
#DESCRIPTIONUNIT PRICEQUANTITYTOTAL
01

Website Design

Creating a recognizable design solution based on the company's existing visual identity
$40.0030$1,200.00
02

Website Development

Developing a Content Management System-based Website
$40.0080$3,200.00
03

Search Engines Optimization

Optimize the site for search engines (SEO)
$40.0020$800.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
292 |
Thank you!
293 |
294 |
NOTICE:
295 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
296 |
297 |
298 |
299 | Invoice was created on a computer and is valid without the signature and seal. 300 |
301 |
302 | 303 |
304 | 305 |
306 |
307 | 310 |
311 |

Company Name

312 |
455 Foggy Heights, AZ 85004, US
313 |
(602) 519-0450
314 | 315 |
316 |
317 |
318 |
319 |
320 |
INVOICE TO:
321 |

John Doe

322 |
796 Silver Harbour, TX 79273, US
323 | 324 |
325 |
326 |

INVOICE 3-2-1

327 |
Date of Invoice: 01/06/2014
328 |
Due Date: 30/06/2014
329 |
330 |
331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 |
#DESCRIPTIONUNIT PRICEQUANTITYTOTAL
01

Website Design

Creating a recognizable design solution based on the company's existing visual identity
$40.0030$1,200.00
02

Website Development

Developing a Content Management System-based Website
$40.0080$3,200.00
03

Search Engines Optimization

Optimize the site for search engines (SEO)
$40.0020$800.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
382 |
Thank you!
383 |
384 |
NOTICE:
385 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
386 |
387 |
388 |
389 | Invoice was created on a computer and is valid without the signature and seal. 390 |
391 |
392 | 393 |
394 | 395 |
396 |
397 | 400 |
401 |

Company Name

402 |
455 Foggy Heights, AZ 85004, US
403 |
(602) 519-0450
404 | 405 |
406 |
407 |
408 |
409 |
410 |
INVOICE TO:
411 |

John Doe

412 |
796 Silver Harbour, TX 79273, US
413 | 414 |
415 |
416 |

INVOICE 3-2-1

417 |
Date of Invoice: 01/06/2014
418 |
Due Date: 30/06/2014
419 |
420 |
421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 |
#DESCRIPTIONUNIT PRICEQUANTITYTOTAL
01

Website Design

Creating a recognizable design solution based on the company's existing visual identity
$40.0030$1,200.00
02

Website Development

Developing a Content Management System-based Website
$40.0080$3,200.00
03

Search Engines Optimization

Optimize the site for search engines (SEO)
$40.0020$800.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
472 |
Thank you!
473 |
474 |
NOTICE:
475 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
476 |
477 |
478 |
479 | Invoice was created on a computer and is valid without the signature and seal. 480 |
481 |
482 | 483 | 484 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/invoice3.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Example 1 7 | 155 | 156 | 157 | 158 |
159 |
160 | 163 |

INVOICE 3-2-1

164 |
165 |
Company Name
166 |
455 Foggy Heights,
AZ 85004, US
167 |
(602) 519-0450
168 | 169 |
170 |
171 |
PROJECT Website development
172 |
CLIENT John Doe
173 |
ADDRESS 796 Silver Harbour, TX 79273, US
174 | 175 |
DATE August 17, 2015
176 |
DUE DATE September 17, 2015
177 |
178 |
179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
233 |
234 |
NOTICE:
235 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
236 |
237 |
238 |
239 | Invoice was created on a computer and is valid without the signature and seal. 240 |
241 |
242 | 243 |
244 | 245 |
246 |
247 | 250 |

INVOICE 3-2-1

251 |
252 |
Company Name
253 |
455 Foggy Heights,
AZ 85004, US
254 |
(602) 519-0450
255 | 256 |
257 |
258 |
PROJECT Website development
259 |
CLIENT John Doe
260 |
ADDRESS 796 Silver Harbour, TX 79273, US
261 | 262 |
DATE August 17, 2015
263 |
DUE DATE September 17, 2015
264 |
265 |
266 |
267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
320 |
321 |
NOTICE:
322 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
323 |
324 |
325 |
326 | Invoice was created on a computer and is valid without the signature and seal. 327 |
328 |
329 | 330 |
331 | 332 |
333 |
334 | 337 |

INVOICE 3-2-1

338 |
339 |
Company Name
340 |
455 Foggy Heights,
AZ 85004, US
341 |
(602) 519-0450
342 | 343 |
344 |
345 |
PROJECT Website development
346 |
CLIENT John Doe
347 |
ADDRESS 796 Silver Harbour, TX 79273, US
348 | 349 |
DATE August 17, 2015
350 |
DUE DATE September 17, 2015
351 |
352 |
353 |
354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 |
SERVICEDESCRIPTIONPRICEQTYTOTAL
DesignCreating a recognizable design solution based on the company's existing visual identity$40.0026$1,040.00
DevelopmentDeveloping a Content Management System-based Website$40.0080$3,200.00
SEOOptimize the site for search engines (SEO)$40.0020$800.00
TrainingInitial training sessions for staff responsible for uploading web content$40.004$160.00
SUBTOTAL$5,200.00
TAX 25%$1,300.00
GRAND TOTAL$6,500.00
407 |
408 |
NOTICE:
409 |
A finance charge of 1.5% will be made on unpaid balances after 30 days.
410 |
411 |
412 |
413 | Invoice was created on a computer and is valid without the signature and seal. 414 |
415 |
416 | 417 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/logo_invoice2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/sample_html/logo_invoice2.png -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/sample_html/logo_invoice3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/source code/html-pdf-edge/html-pdf-edge-demo/sample_html/logo_invoice3.png -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge-demo/vs2015.min.css: -------------------------------------------------------------------------------- 1 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#1e1e1e;color:#dcdcdc}.hljs-keyword,.hljs-literal,.hljs-name,.hljs-symbol{color:#569cd6}.hljs-link{color:#569cd6;text-decoration:underline}.hljs-built_in,.hljs-type{color:#4ec9b0}.hljs-class,.hljs-number{color:#b8d7a3}.hljs-meta .hljs-string,.hljs-string{color:#d69d85}.hljs-regexp,.hljs-template-tag{color:#9a5334}.hljs-formula,.hljs-function,.hljs-params,.hljs-subst,.hljs-title{color:#dcdcdc}.hljs-comment,.hljs-quote{color:#57a64a;font-style:italic}.hljs-doctag{color:#608b4e}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-tag{color:#9b9b9b}.hljs-template-variable,.hljs-variable{color:#bd63c5}.hljs-attr,.hljs-attribute{color:#9cdcfe}.hljs-section{color:gold}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-bullet,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-selector-tag{color:#d7ba7d}.hljs-addition{background-color:#144212;display:inline-block;width:100%}.hljs-deletion{background-color:#600;display:inline-block;width:100%} -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33103.184 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "html-pdf-edge", "html-pdf-edge\html-pdf-edge.csproj", "{C698502D-45CF-4DA6-823A-4650C650286D}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "html-pdf-edge-demo", "html-pdf-edge-demo\html-pdf-edge-demo.csproj", "{6F6385BF-AD09-40D7-AABD-304D761EC9FB}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C698502D-45CF-4DA6-823A-4650C650286D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {C698502D-45CF-4DA6-823A-4650C650286D}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {C698502D-45CF-4DA6-823A-4650C650286D}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {C698502D-45CF-4DA6-823A-4650C650286D}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {6F6385BF-AD09-40D7-AABD-304D761EC9FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {6F6385BF-AD09-40D7-AABD-304D761EC9FB}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {6F6385BF-AD09-40D7-AABD-304D761EC9FB}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {6F6385BF-AD09-40D7-AABD-304D761EC9FB}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {B918739C-A572-4E1D-BBC1-0874BA91B9D9} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge/html-pdf-edge.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | html_pdf_edge_class 6 | html-pdf-edge 7 | Convert HTML to PDF with Edge 8 | 2.1 9 | adriancs 10 | adriancs 11 | Convert HTML to PDF with Edge 12 | Convert HTML to PDF by Using Microsoft Edge 13 | adriancs 14 | https://github.com/adriancs2/HTML-PDF-Edge 15 | https://github.com/adriancs2/HTML-PDF-Edge.git 16 | git 17 | pdf;html;edge 18 | Improve naming of methods 19 | 2.1 20 | 2.1 21 | Unlicense 22 | True 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /source code/html-pdf-edge/html-pdf-edge/html-to-pdf-edge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Web; 7 | using static System.PDF; 8 | 9 | namespace System 10 | { 11 | public class PDF 12 | { 13 | public enum TransmitMethod 14 | { 15 | None, 16 | Attachment, 17 | Inline, 18 | Redirect 19 | } 20 | 21 | public const string Version = "2.1"; 22 | 23 | /// 24 | /// Convert a webpage into pdf 25 | /// 26 | /// The webpage 27 | /// The file path of pdf 28 | public static void GeneratePdf(string url, string filePathPDF) 29 | { 30 | string encodedUrl = Uri.EscapeUriString(url); 31 | 32 | string folderPath = Path.GetDirectoryName(filePathPDF); 33 | 34 | if (!Directory.Exists(folderPath)) 35 | { 36 | Directory.CreateDirectory(folderPath); 37 | } 38 | 39 | using (var p = new Process()) 40 | { 41 | p.StartInfo.FileName = "msedge"; 42 | p.StartInfo.Arguments = $@"--headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf=""{filePathPDF}"" {encodedUrl}"; 43 | p.Start(); 44 | p.WaitForExit(); 45 | } 46 | } 47 | 48 | static void Publish(TransmitMethod transmitMethod, string filenamePdf, string filePdfTemp) 49 | { 50 | if (transmitMethod == TransmitMethod.None) 51 | { 52 | 53 | } 54 | else if (transmitMethod == TransmitMethod.Attachment) 55 | { 56 | HttpContext.Current.Response.Clear(); 57 | HttpContext.Current.Response.ContentType = "application/pdf"; 58 | string encodedFilename = HttpUtility.UrlEncode(filenamePdf); 59 | HttpContext.Current.Response.AddHeader("Content-Disposition", $"attachment; filename*=UTF-8''{encodedFilename}"); 60 | HttpContext.Current.Response.AddHeader("Content-Length", new FileInfo(filePdfTemp).Length.ToString()); 61 | byte[] ba = File.ReadAllBytes(filePdfTemp); 62 | try 63 | { 64 | File.Delete(filePdfTemp); 65 | } 66 | catch { } 67 | HttpContext.Current.Response.BinaryWrite(ba); 68 | HttpContext.Current.Response.End(); 69 | } 70 | else if (transmitMethod == TransmitMethod.Inline) 71 | { 72 | HttpContext.Current.Response.Clear(); 73 | HttpContext.Current.Response.ContentType = "application/pdf"; 74 | string encodedFilename = HttpUtility.UrlEncode(filenamePdf); 75 | HttpContext.Current.Response.AddHeader("Content-Disposition", $"inline; filename*=UTF-8''{encodedFilename}"); 76 | HttpContext.Current.Response.AddHeader("Content-Length", new FileInfo(filePdfTemp).Length.ToString()); 77 | byte[] ba = File.ReadAllBytes(filePdfTemp); 78 | try 79 | { 80 | File.Delete(filePdfTemp); 81 | } 82 | catch { } 83 | HttpContext.Current.Response.BinaryWrite(ba); 84 | HttpContext.Current.Response.End(); 85 | } 86 | else if (transmitMethod == TransmitMethod.Redirect) 87 | { 88 | HttpContext.Current.Response.Redirect($"~/temp/pdf/{filenamePdf}", true); 89 | } 90 | } 91 | 92 | static void DeleteOldFiles(string filenameToKeep, string folderTemp) 93 | { 94 | string[] oldFiles = Directory.GetFiles(folderTemp); 95 | 96 | DateTime dateexpiry = DateTime.Now.AddMinutes(-30); 97 | 98 | foreach (var file in oldFiles) 99 | { 100 | FileInfo fi = new FileInfo(file); 101 | if (fi.CreationTime < dateexpiry) 102 | { 103 | if (file.EndsWith($"{filenameToKeep}")) 104 | continue; 105 | 106 | try 107 | { 108 | File.Delete(file); 109 | } 110 | catch { } 111 | } 112 | } 113 | } 114 | 115 | /// 116 | /// Convert a webpage into pdf and transmit it for download 117 | /// 118 | /// The webpage 119 | /// The filename of pdf (without the file path) 120 | /// The transmit method 121 | public static void PublishUrl(string url, string filenamePdf, TransmitMethod transmitMethod) 122 | { 123 | if (!filenamePdf.ToLower().EndsWith(".pdf")) 124 | { 125 | filenamePdf = filenamePdf + ".pdf"; 126 | } 127 | 128 | string folderTemp = HttpContext.Current.Server.MapPath("~/temp/pdf"); 129 | 130 | if (!Directory.Exists(folderTemp)) 131 | { 132 | Directory.CreateDirectory(folderTemp); 133 | } 134 | 135 | string filePdfTemp = HttpContext.Current.Server.MapPath($"~/temp/pdf/{filenamePdf}"); 136 | 137 | GeneratePdf(url, filePdfTemp); 138 | 139 | DeleteOldFiles(filenamePdf, folderTemp); 140 | 141 | Publish(transmitMethod, filenamePdf, filePdfTemp); 142 | } 143 | 144 | /// 145 | /// Convert html to pdf and transmit it for download as inline 146 | /// 147 | /// 148 | public static void PublishHtmlInline(string htmlContent) 149 | { 150 | PublishHtml(htmlContent, "", TransmitMethod.Inline); 151 | } 152 | 153 | /// 154 | /// Convert html to pdf and transmit it for download as attachment. 155 | /// 156 | /// The html text 157 | /// Filename of PDF 158 | public static void PublishHtmlAttachment(string htmlContent, string filenamePdf) 159 | { 160 | PublishHtml(htmlContent, filenamePdf, TransmitMethod.Attachment); 161 | } 162 | 163 | /// 164 | /// Convert html to pdf and transmit it for download 165 | /// 166 | /// The html text 167 | /// Filename of PDF (optional), this parameter can be blank inline download transmission 168 | /// Transmission type 169 | public static void PublishHtml(string htmlContent, string filenamePdf, TransmitMethod transmitMethod) 170 | { 171 | if (filenamePdf == null || filenamePdf.Length == 0) 172 | { 173 | filenamePdf = DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf"; 174 | } 175 | 176 | if (!filenamePdf.ToLower().EndsWith(".pdf")) 177 | { 178 | filenamePdf = filenamePdf + ".pdf"; 179 | } 180 | 181 | filenamePdf = filenamePdf.Replace(" ", "_"); 182 | 183 | filenamePdf = EscapeFileName(filenamePdf); 184 | 185 | string folderTemp = HttpContext.Current.Server.MapPath("~/temp/pdf"); 186 | 187 | if (!Directory.Exists(folderTemp)) 188 | { 189 | Directory.CreateDirectory(folderTemp); 190 | } 191 | 192 | Random rd = new Random(); 193 | 194 | string htmlRandomFilename = rd.Next(100000, int.MaxValue).ToString(); 195 | 196 | string fileHtmlTemp = HttpContext.Current.Server.MapPath($"~/temp/pdf/{htmlRandomFilename}.html"); 197 | string filePdfTemp = HttpContext.Current.Server.MapPath($"~/temp/pdf/{filenamePdf}"); 198 | 199 | File.WriteAllText(fileHtmlTemp, htmlContent); 200 | 201 | Uri r = HttpContext.Current.Request.Url; 202 | 203 | string urlHtml = $"{r.Scheme}://{r.Host}:{r.Port}/temp/pdf/{htmlRandomFilename}.html"; 204 | 205 | GeneratePdf(urlHtml, filePdfTemp); 206 | 207 | try 208 | { 209 | File.Delete(fileHtmlTemp); 210 | } 211 | catch { } 212 | 213 | DeleteOldFiles(filenamePdf, folderTemp); 214 | 215 | Publish(transmitMethod, filenamePdf, filePdfTemp); 216 | } 217 | 218 | static string EscapeFileName(string fileName) 219 | { 220 | string escapedFileName = string.Concat(fileName.Select(c => IsValidFileNameChar(c) ? c.ToString() : "_")); 221 | return escapedFileName; 222 | } 223 | 224 | static bool IsValidFileNameChar(char c) 225 | { 226 | return !Path.GetInvalidFileNameChars().Contains(c); 227 | } 228 | } 229 | } -------------------------------------------------------------------------------- /wiki/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/loading.gif -------------------------------------------------------------------------------- /wiki/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/loading.png -------------------------------------------------------------------------------- /wiki/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/screenshot1.png -------------------------------------------------------------------------------- /wiki/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/screenshot2.png -------------------------------------------------------------------------------- /wiki/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/screenshot3.png -------------------------------------------------------------------------------- /wiki/screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adriancs2/HTML-PDF-Edge/51784aef8a5ad62b97f152147a1fbae1ed05ae6a/wiki/screenshot4.png --------------------------------------------------------------------------------