How to embed the right url to custom font in HTML string - c#

How to embed the right url to custom font in my HTML string.
I do the following:
string exeFile = (new System.Uri(Assembly.GetEntryAssembly().CodeBase)).AbsolutePath;
string path4 = Path.Combine(Regex.Escape(exeDir), "\\..\\\\..\\\\CSS\\\\majalla.ttf");
string arabicFont = #"#font-face {
font-family: 'sakkal_majallaregular';
src: url(" + "'" + path4 + "'" + #"), url('majalla-webfont.woff2') format('woff2'), url('majalla-webfont.woff') format('woff');}";
This doesn't work(doesn't take effect). After debugging path4 =
C:\\Users\\AA\\Desktop\\PrintingStatement\\PrintingStatement\\bin\\Debug\\..\\..\\CSS\\majalla.ttf
When I try the constant absolute url like this:
url('C:\\Users\\AA\\Desktop\\PrintingStatement\\PrintingStatement\\CSS\\majalla.ttf')
It works fine. How to convert my url to the previous one in production environment.
MY Updated HTML Method
protected string StyleStatementDoc(SingleStatement statementToPrint)
{
string path1 = "CSS/StatementVerifacation.css";
string path2 = "CSS/Statement.css";
string path3 = "CSS/print.min.css";
string path4 = "CSS/majalla.ttf";
string arabicFont = #"#font-face {
font-family: 'sakkal_majallaregular';
src: url(" + "'" + path4 + "'" + #"), url('majalla-webfont.woff2') format('woff2'), url('majalla-webfont.woff') format('woff');
}";
string htmlData = #"<!DOCTYPE html>
<html>
<head>
<title>Statement</title>
<style>" + arabicFont + #"
body {
font-size: 20px;
background-color: White;
color: Black;
font-family:'sakkal_majallaregular', Arial, Helvetica, sans-serif;
text-align:right;
direction:rtl;
}
p {
line-height: 32px; /* within paragraph */
margin-bottom: 30px; /* between paragraphs */
}
</style>
<link href = '" + path1 + "'" + " rel='stylesheet' />" + #"
<link href = '" + path3 + "'" + " rel='stylesheet' />" + #"
</head>
<body>
<div class='my' id='editor1'>" + statementToPrint.StatementBeforePrint + #"
</div>
</body>
</html>
";
// htmlData = htmlData.Replace(#"<head>", $#"<head><base href=""{new Uri(Application.StartupPath)}/""/>");
return htmlData;
}
System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
protected void Print(string htmlData)
{
webBrowser.SetHtmlContent(htmlData, $#"{new Uri(Application.StartupPath)}/");
webBrowser.Print();
}
My project structure:

To resolve relative addresses you have the following options:
Using a placeholder in html and replace it with bin folder address. (Works for everything but fonts)
Injection <base> tag in head. (Works for everything but fonts)
Implementing IMoniker to set base url for document. (Works for everything as well as fonts) I've implemented an extension method for WebBrowser1.SetHtmlContent(html, url)
Example
Assuming you have an html like this:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<title>Sample</title>
<style>
#font-face {
font-family: "MyFont";
src: url('./Contents/MyFont.ttf') format('truetype');
}
body {
background-image: url('./Contents/Image.jpeg');
font-family: 'MyFont';
font-weight: normal;
font-style: normal;
font-size: 30px;
color: red;
}
</style>
</head>
<body>
Something
</body>
</html>
I assume you have Contents folder containing Image.jpeg and MyFont.ttf files in your project output directory. (If you have them in your project, them in your project, to copy them into output directory into the right folder structure, just in the properties window of those files in solution explorer, set Copy to output directory to Copy Always.)
Solution 1 - use a placeholder in HTML file and replace it with bin path
So instead of ./ use $ROOT$/, for example: background-image:url('$ROOT$/Resources/Sample.jpeg'); Then when setting document text of the browser, replace it with start up path of the application:
this.webBrowser1.DocumentText = yourHtmlContent.Replace("$ROOT$",
new Uri(Application.StartupPath).ToString());
Solution 2 - Injectting html <base> tag
Assuming you don't have any placeholder in the html content. Then it's enough to inject a <base> tag into <head> like this:
var html = System.IO.File.ReadAllText("HTMLPage1.html");
html = html.Replace(#"<head>", $#"<head><base href=""{new Uri(Application.StartupPath)}/""/>");
webBrowser1.DocumentText = html;
It means all the relative addresses will be resolved using <base> href attribute.
Solution 3 - Implemeting IMoniker
You can implement IMoniker interface and using IWebBrowser2 from SHDocVw load the html content and set a base url for that. I used this method for relative address of #font-face as well as relative address for other stuff in html content and it worked well.
You find an Implementation which I shared in this post: Set URL of custom HTML loaded in webbrowser and easily use it like this:
webBrowser1.SetHtmlContent(html,
$#"{new Uri(Application.StartupPath)}/");

Related

ASP.NET MVC FileContentResult inline PDF filename not showing in browser title

.NET Framework 4.7.2 MVC project
I have a controller action that dynamically loads a PDF to return inline to the browser. Everything is working, except the filename is not showing in the browser title bar or the tab. Instead, the browser is showing the value of the "id" parameter, presumably because it follows the last slash.
I need the browser to display the PDF filename, so that users will know what PDF they are viewing. Our users tend to have multiple PDFs open in tabs and switch between them frequently. This is a simplified version of the code:
public FileContentResult ViewPDF(int id)
{
byte[] pdfContents = loadPDF(id);
string filename = getPDFFilename(id);
var cd = new ContentDisposition
{
FileName = filename,
Inline = true
};
Response.AddHeader("Content-Disposition", cd.ToString());
string returnContentType = MimeMapping.GetMimeMapping(filename);
return File(pdfContents, returnContentType);
}
I have also tried a FileStream with no luck and have tried Edge, IE, and Chrome, but they all do the same. In Chrome, when I Save the PDF, it does save with the correct filename but just won't show it in the browser.
This isn't the ideal solution, but I ended up creating a new View page that contains a full-screen <iframe> that loads the PDF inline. This way I could at least display the PDF name in the page title, which appears in the tab.
Similar to this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewData["Title"]</title>
<style type="text/css">
body, html {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
.pdfFrame {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body class="nomargins">
<iframe class="pdfFrame" src="#Url.Action("GetPDF", new { id = ViewBag.pdfID })" frameBorder="0"></iframe>
</body>
</html>

How can I center a image in a HTML created by HtmlAgilityPack

I have a very simple HTML document created with the HtmlAgilityPack, with a embedded image; (base64 format)
Public Report As New HtmlDocument()
Dim html As String = "<!DOCTYPE html>
<html>
<body>
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORAAAAAXNSR0IArs4c6QAAAARn"" alt=""Red dot"" align=""middle""/>
</body>
</html> "
Report.LoadHtml(html)
WebBrowser1.DocumentText = Report.Text
The image displays on the left, I'd like to horizontally center it, how can this be done?
(The actual base64 image is shortened for obvious reasons)
The answer I was looking for was:
With the HtmlAgilityPack you can embed the CCS insite the HTLM like so:
Dim html As String = "<!DOCTYPE html>
<html>
<body>
<head><style>html, body {
height: 100%;
margin:0;
padding:0;
}
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
</style></head>
<div>
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORA"" alt=""Red dot"" class=""center""/>
</div>
</body>
</html> "
Thanks to Mortb for pointing me in the right direction.
give the image style of
img{
display:block;
margin:auto;
}
or you can put the image inside a div tag and give the div this style:
div{
width:; ==> give it any width you want
height:; ==> give it any height want
margin:auto;
}
In HTML images behave like text, so to center an image horizontally all you really need to do is add a div around it which centers all text:
<div style="text-align: center">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORAAAAAXNSR0IArs4c6QAAAARn" alt="Red dot"/>
</div>
No special CSS workarounds needed.

Substring from the beginning of a word

The HTTP GET response for a request is like below
<html>
<head> <script type="text/javascript">----</script> <script type="text/javascript">---</script> <title>Detailed Notes</title>
</head>
<body style="background-color: #FFFFFF; border-width: 0px; font-family: sans-serif; font-size: 13; color: #000000"> <p>this is one note </p> </body> </html>
I am getting this as a string and i have to read the body part out of it.
I tried HtmlAgility pack, but HTML parsing is getting failed due to some specials in the html content (I think something from the commented script causing this issue).
So to read the tag content i am thinking of a SubString operation.
Like SubString from the beginning of <body tag.
How can we do SubString from the beginning of a word from a text?
Using a simple SubString() with IndexOf() + LastIndexOf():
string BodyContent = input.Substring(0, input.LastIndexOf("</body>") - 1).Substring(input.IndexOf("<body"));
BodyContent = BodyContent.Substring(BodyContent.IndexOf(">") + 1).Trim();
This will return:
<p> this is one note </p>
string FullBody = input.Substring(0, input.LastIndexOf("</body>") + 7).Substring(input.IndexOf("<body")).Trim();
This will return:
<body style = background-color: #FFFFFF; border-width: 0px; font-family: sans-serif; font-size: 13; color: #000000' >< p > this is one note </p> </body>
The " will cause a problme so you need to replace every " after you get the request source
WebClient client = new WebClient(); // make an instance of webclient
string source = client.DownloadString("url").Replace("\"",",,"); // get the html source and escape " with any charachter
string code = "<body style=\"background-color: #FFFFFF; border-width: 0px; font-family: sans-serif; font-size: 13; color: #000000\"> <p>this is one note </p> </body>";
MatchCollection m0 = Regex.Matches(code, "(<body)(?<body>.*?)(</body>)", RegexOptions.Singleline); // use RE to get between tags
foreach (Match m in m0) // loop through the results
{
string result = m.Groups["body"].Value.Replace(",,", "\""); // get the result and replace the " back
}

Highlight 2 places in a single map without using search box [duplicate]

This question already has answers here:
Add "Search Area" outline onto google maps result
(5 answers)
Closed 5 years ago.
I want to highlight 2 places in google maps like the image below(could not show two places highlighted, i have just shown the border style that i will implement).
I want to show border of place exactly like the image below.
I want to dynamically mark places based on place name.
For example I don't have lat long values so ,so I have to search by name of
place.
Right now, to do this using the Google Maps Javascript API, you'll need external data to show the borders of each place. Having it internal to the Javascript API is already being requested here in Google's Issue Tracker: https://issuetracker.google.com/issues/35816953
As a workaround though, you can use the Maps Embed API to mimic the behavior you outlined in your post.
Here's a sample:
Be sure to replace YOUR_API_KEY_HERE with your own API key.
var input = document.getElementById('location');
var autocomplete;
function initPlaces() {
autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (!place.geometry) {
alert('Error with your search for ' + place.name);
}
if(place.place_id) {
markLocation(place.place_id);
}
})
}
function markLocation(placeId) {
var url = 'https://www.google.com/maps/embed/v1/place?key=AIzaSyCD0rWgXRVBa7PgaTWXVp_gU51pgHGviYY';
var placeStr = '&q=place_id:';
var iframe = document.getElementById('iframe');
placeStr += placeId;
url += placeStr;
iframe.src = url;
}
var onSubmitHandler = function(e) {
e.preventDefault();
//markLocation();
}
document.getElementById('form').addEventListener('submit', onSubmitHandler);
input {
height: 2rem;
border-radius: 2px;
border-style: none;
border: 1px solid #e2e2e2;
padding-left: 1rem;
}
.places {
height: 100px;
}
#map {
height: 100%;
}
#location {
width: 400px;
}
.map-frame {
width: 100%;
height: 500px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="places">
<form id="form" autocomplete="off">
<input id="location" type="text" placeholder="Enter a location">
</form>
</div>
<div class="map-frame">
<!-- Be sure to replace YOUR_API_KEY_HERE with your actual API key -->
<iframe width="100%" id="iframe" height="100%"frameborder="0" style="border:0"
src="https://www.google.com/maps/embed/v1/place?q=place_id:ChIJ-QB6d6K5lzMRxi-hKfTINm0&key=YOUR_API_KEY_HERE" allowfullscreen></iframe>
</div>
<!-- Be sure to replace YOUR_API_KEY_HERE with your actual API key -->
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_HERE&libraries=places&callback=initPlaces" async defer></script>
</body>
</html>
An external jsbin link here as well if you want to try it out: jsbin
Here's the documentation of the Maps Embed API in case you want to pursue that track: https://developers.google.com/maps/documentation/embed/start
Hope that helps!

WPF Webbrowser create html file from user input

I'm reading a html using the webbrowser component in WPF. I should let the user to give there own text, upload an image and save it as a .html file.
By this way I can get the tag value:
string myTagValue = (FrameWithinGrid.Document as mshtml.HTMLDocument)
.getElementsByTagName("div")
.OfType<mshtml.IHTMLElement>()
.First()
.innerText;
How can i get the value from a text box and save it as a .html file including a new image?
Need your help. Thank you.
This is the html file:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>Welcome to Linguini Party!</title>
<style type="text/css">
* {
margin: 0;
}
html, body {
height: 100%;
font-family: Arial;
background-color: #e1dfe3;
color: #333333;
background-repeat: no-repeat;
}
h1 {
margin-right: 8%;
margin-left: 7%;
font-size: 450%;
text-align: center;
}
h2 {
font-size: 450%;
text-align: center;
color: #8a00ca;
font-style: italic;
}
</style>
</head>
<body id="Imagebg" background="welcome_final1.png">
<div id="container">
<h1 id="text1">Welcome to<br></h1>
<h2 id="text2">Linguini Party!</h2>
</div>
</body>
</html>
One strategy for accomplishing this is to create an html template along the lines of this...
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body id="Imagebg" >
<div id="container">
<h1 id="text1">$$TEXT1$$<br></h1>
<h2 id="text2">$$TEXT2$$</h2>
<img src="$$IMAGELOCATION$$"/>
</div>
</body>
</html>
This template has been instrumented with markers such as $$TEXT1$$. These will be replaced with customized text later.
Include the template as a resource, or as an external file, or wherever. I opt for including it as an embedded resource. Here's the settings...
You don't HAVE to use an embedded resource, you can use the WebBrowser to get the html also. I like using a resource because it avoids exceptions caused by missing or corrupt files.
The next step is easy. Here's a working View Model...
public class ViewModel
{
public string Text1 { get; set; }
public string Text2 { get; set; }
public string ImagePath { get; set; }
public string DestinationName { get; set; }
public void Start()
{
var resourceName = Assembly.GetExecutingAssembly().GetManifestResourceNames().Where(q => q.Contains("Template.html")).FirstOrDefault();
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
string html = reader.ReadToEnd().Replace("$$TEXT1$$", Text1).Replace("$$TEXT2$$", Text2).Replace("$$IMAGELOCATION$$", ImagePath);
File.WriteAllText(DestinationName, html);
}
}
}
}
The View Model gets the various Text1 (etc) properties set by the caller, and then loads the HTML template and replaces the markers with custom content. Then it uses the static method on File to save it.
You can modify this strategy to use any other type of instrumentation as long as it's consistent. For a more scalable, full-blown solution, I suggest HtmlAgility. I have been using it for years.

Categories