Correct HTML for multi-paragraph quotes - html

I have text written like so:
"Something something," he said. "Lorem ipsum dolor sit amet, ne natum
elitr his, usu ex dictas everti, utamur reformidans ad vis. Eam
dissentiet deterruisset an, vis cu nullam lobortis. Doming inimicus eu
nec, laudem audire ceteros cu vis, et per eligendi splendide. Ne
legere tacimates instructior qui. Te vis dicat iudico integre, ex est
prima constituam consequuntur. Vix sanctus voluptaria ei, usu ornatus
iracundia ne, nam nulla iudico no. Duo ei labores nusquam.
"In harum docendi fuisset vis. Meis constituam ea quo. Ei vim prima
liber officiis. Ad modo tota augue est, fugit soleat blandit eos ex."
The text follows an annoying typographical rule for multi-paragraph quotes: a quote which spans a paragraph doesn't have an end quote at the end of each internal paragraph, but it has an extra one at the start of each internal paragraph. HTML5 doesn't allow <p> elements inside <q>elements, but this situation is worse: the second quote doesn't even include all of the paragraph, so even if it did (or if I used, say, <div class=quote>) I can't see a way to mark this up without mis-aligned elements.
(Of course I could just embed quotation marks rather than use <q>, but I'm looking for thoughts on the best way to do this.)

The previous answer (redefining quotes: '\201c' '\201d' '\2018' '\2019';) works, but it overrides the user's locale and forces American style quotation marks.
Instead, this:
<style>
q.continued::after { font-size: 0; }
</style>
…
<p>
I replied, <q class="continued">Blah blah blah.</q>
</p>
<p>
<q class="continued">And not only that!</q>
</p>
<p>
<q>So there!</q>, and left the room.
</p>
Produces:
I replied, ”Blah blah blah.
”And not only that
”So there!”, and left the room.
Which should work correctly with any locale's quotation characters.
Note that display:none would be better, but it doesn't work.
The browser (Chrome at least) notices that the closing quote is missing and switches to the alternate quote mark for the following paragraphs.

The cleanest way to do this is indeed with quotation marks; they are just as semantically appropriate as using the <q> element. From the spec:
The use of q elements to mark up quotations is entirely optional; using explicit quotation punctuation without q elements is just as correct.
Code Example:
In the following example, quotation marks are used instead of the q element:
<p>His best argument was ❝I disagree❞, which
I thought was laughable.</p>
Having said that, you can still do this using <div class=quote> to mark the start and end of a multi-paragraph quotation as you've suggested, coupled with the following CSS:
q {
quotes: '\201c' '\201d' '\2018' '\2019';
}
.quote > p:not(:last-of-type) > q:last-child {
quotes: '\201c' '' '\2018' '';
}
<div class=quote>
<p><q>Something something,</q> he said. <q>Lorem ipsum dolor sit amet,
ne natum elitr his, usu ex dictas everti, utamur reformidans ad vis.
Eam dissentiet deterruisset an, vis cu nullam lobortis. Doming
inimicus eu nec, laudem audire ceteros cu vis, et per eligendi
splendide. Ne legere tacimates instructior qui. Te vis dicat iudico
integre, ex est prima constituam consequuntur. Vix sanctus voluptaria
ei, usu ornatus iracundia ne, nam nulla iudico no. Duo ei labores
nusquam.</q></p>
<p><q>In harum docendi fuisset vis. Meis constituam ea quo. Ei vim prima
liber officiis. Ad modo tota augue est, fugit soleat blandit eos ex.</q></p>
</div>
But this requires using <div class=quote> wherever necessary in the first place. Granted, as it's just a div, it doesn't set the text containing the quotation apart from the rest of the prose (in contrast, a blockquote would be entirely inappropriate for this reason), or otherwise change the meaning of the text, but it's still not as clean as you might like. It does however work regardless of whether that second paragraph has been represented in its entirety or if there is more text following the closing quotation mark — or indeed, even if the second paragraph contains both the end of one quotation and the start of another (just move your </div> end tag to where the second quotation ends).
You'll notice in the above snippet that the <q> elements themselves are split by paragraph; this is perfectly normal since <q> is a phrasing element and therefore, as you've stated, cannot span multiple flow elements. But if you really are worried that the split <q> elements will be seen (particularly by AT) as two separate quotations altogether, you can either associate them using a class or a custom data attribute, or just go with quotation marks which are much simpler and will convey the meaning of the text just as effectively.

Related

sendmailR adding extra space in HTML body that ocasionally breaks HTML tags

I automated personalized reports for people on my team and it's working great!
The only problem is that some of the emails occasionally have an extra space in the middle of the HTML body. Occasionally, these extra spaces are positioned such that they break and expose an HTML tag:
For example, "Consul invidunt" would read "Consul invi dunt". Or worse it would read "< p> Consul invidunt" with the paragraph tag exposed due to the extra space.
The only thing that kind of works is creating "space traps". For example, adding <p> </p> right after the paragraph and hoping that the extra paragraph "lands" in the middle of the paragraph that is just a bunch of spaces. It doesn't always work though.
Since the data frames in the middle of the body and the recipient names are variable, this issue only occurs with some recipients. Those recipients with the glitch change depending on what I type in the body, whether I try to "catch" the space with a "space trap", etc.
The weird thing is that if I paste the HTML from bodyhtml[['text']] into an HTML editor, the HTML looks perfect!
I've also checked to see whether this is a problem with Outlook, but the problem persists when sending to gmail.
This is essentially my code:
bodyhtml <- sendmailR::mime_part(paste0(
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>",
"<html xmlns='http://www.w3.org/1999/xhtml'>",
"<head>",
"<meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>",
"<meta name='viewport' content='width=100%, initial-scale=1.0'/>",
"<style>",
"p { font-size: 95% }",
"table {border-collapse: collapse;}",
"th {background-color: #D3D3D3;}",
"tr:nth-child(odd) {background-color: #dfe7f2;}",
"</style>",
"</head>",
"<body>",
"<br>",
"<p>Hi ",recipient_name,",</p>",
"<br>",
"<div>",
"<p>Check out this awesome report as of <i>",report_date,"</i>.</p>",
"<p>Lorem ipsum dolor sit amet, iudico quidam aliquid eos et, eam no vero democritum, ",
"no tempor laoreet indoctum sea. Cu malis persequeris has, duo an viris labitur pertinax, inani ignota molestiae sea eu. ",
"Pri et hinc quodsi. Ut ius dico animal sapientem. Cum ut vitae officiis definitionem. Sed ex atqui delectus, ",
"ea nulla diceret usu, liber eripuit te usu.</p>",
"</div>",
"<div>",
"<br>",
"<br>",
"</div>",
"<div>",
"<p>Consul invidunt expetendis has in, mea nemore habemus at, nibh eligendi tincidunt ex sit.:</p>",
"<ul>",
"<li><b>Primo</b></li>",
"<ul>",
"<li>Aeterno reprimique ea his. Pro ad brute dicat. Id eos habeo dicta tempor, ei perpetua scripserit theophrastus sed.</li>",
"</ul>",
"<li><b>Secundus</b></li>",
"<ul>",
"<li>Aeterno reprimique ea his. Pro ad brute dicat. Id eos habeo dicta tempor, ei perpetua scripserit theophrastus sed.</li>",
"</ul>",
"<li><b>Tertius</b></li>",
"<ul>",
"<li>Aeterno reprimique ea his. Pro ad brute dicat. Id eos habeo dicta tempor, ei perpetua scripserit theophrastus sed.</li>",
"</ul>",
"</ul>",
"</div>",
"<br>",
"<br>",
"<br>",
"<div>",
"<h2 style='color:#3b5998'>Primo</h2>",
"<p><i>(Up to 10 --see attachment for full list).</i></p>",
df_html1,
"<br>",
"<br>",
"<h2 style='color:#3b5998'>Secundus</h2>",
"<p><i>(Up to 10 --see attachment for full list).</i></p>",
df_html2,
"<br>",
"<br>",
"<h2 style='color:#3b5998'>Tertius</h2>",
"<p><i>(Up to 10 --see attachment for full list).</i></p>",
df_html3,
"</div>",
"<br>",
"<br>",
"<p style='color:#3b5998'>For further details, check out the ",
"<a href='https://www.mywebsite.com/dashboard'> dashboard</a>",
"<p style='color:#3b5998'>Questions? Comments? Reply directly to this email!</p>",
"<p style='color:#8b9dc3'>My Team Name</p>",
"<br>",
"<br>",
"</body>",
'</html>'
))
bodyhtml[["headers"]][["Content-Type"]] <- "text/html"
msg <- c(bodyhtml, sendmailR::mime_part("my_file_path.xlsx"))
sendmailR::sendmail(from = "me#email.com",
to = "you#email.com",
subject = "my subject line",
msg = msg)
Anybody have any ideas? Please help!
I replaced the first two lines (DOCTYPE and html tags) and that seems to have done the trick!
"<!DOCTYPE html>",
"<html xmlns='http://www.w3.org/1999/xhtml' lang='en'>",
I found these links to be helpful:
https://www.emailonacid.com/blog/article/email-development/which-code-should-i-include-in-every-email/
https://emails.hteumeuleu.com/which-doctype-should-you-use-in-html-emails-cd323fdb793c

How to extract nested fields from MongoDB?

So my problem is that I have a database structure (designed by someone else and I have to work on it now) as follows:
DBS:
Database 1
Database 2
Database 3
Collection 1
Collection 2
field_1
field_1_1
field_1_1_1
field_1_2
field_2
field_3
Collection 3
Collection 4
Database 4
Now I want to extract the field field_1_1_1 any idea how I can query that?
So far I have tried applying find_one on Database 3.Collection 2.filed_1.field_1_1.field_1_1_1 but obviously it did not work.
So here goes the actual content as requested. This is what 1 item in the collection "tempStorage" under the database "workApp" looks like.
{"_id":{"tag":"i4x","org":"Temp","course":"CXV_08","category":"about","name":"overview","revision":null},
"definition":
{"data":
{"data":
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
uis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
onsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
illum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
roident, sunt in culpa qui officia deserunt mollit anim id est laborum"
}
}
}
Edit: Uploaded the actual fields.
What does work is if I export the entire collection and then parse through it but the data is already .4 GB and I do not think that that can be the only option and that there must exist something better.
Anyone with good experience in MongoDB who can help me out?
Try this:
var data = db.tempStorage.find()
data[0].definition.data.data
Here, db.tempStorage.find() will give you all the results in an Array variable data, which you can iterate by passing an index value and using dot notation to reach out deep into the document as I have done in data[0].definition.data.data.
If you have only 1 document within collection than findOne() can also be used.
var data = db.tempStorage.findOne()
data.definition.data.data
HTH!
Thanks.

How to Achieve Just the Ctrl + A Functionality of Contenteditable Attribute?

I'm trying to display a div with some example code for users. I want them to be able to select inside the div and use Ctrl + A to select all of the example code, but I don't want them to be able to edit the actual text (lest the remove a bit on accident and then it won't work).
I'm achieving this right now through contenteditable set on the div, but how do I get the same functionality of this attribute sans the actual text editing?
EDIT: Looking at the solution linked in #Mr. Llama's comment, I can use this method to achieve the primary functionality I'm looking for. However, if possible I would like to simply allow for the Ctrl + A command my users are familiar with, and still allow for the manual highlighting of snippets of the div's text. Again, all while disallowing the addition or removal of any text.
Seems to work for me when I prevent the onkeydown, oncut and onpaste events.
for (const elm of document.getElementsByClassName('editable-not-editable')) {
elm.setAttribute('contenteditable', true);
elm.spellcheck = false;
elm.oncut = () => false;
elm.onpaste = () => false;
elm.onkeydown = (event) => {
if (event.metaKey || event.ctrlKey) {
return;
}
event.preventDefault();
}
}
<div class="editable-not-editable">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</div>

WPF split HTML string for every TextBlock

Does anyone know how to split the HTML string for every TextBlock? I split them, but something is wrong. The lines count are not the same in every page. How do I solve this issue?
Here's the code:
XAML:
<Window x:Class="Ebook.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WPFMitsuControls;assembly=WPFMitsuControls"
Title="eBook" Height="600" Width="800"
Loaded="MainWindow_OnLoaded" Background="Silver">
<DockPanel>
<Viewbox Margin="10">
<Grid>
<controls:Book x:Name="myBook" Width="600" Height="400" Margin="20">
<controls:Book.ItemTemplate>
<DataTemplate>
<Border BorderThickness="4" BorderBrush="Gray" Background="White">
<ContentControl Content="{Binding .}" />
</Border>
</DataTemplate>
</controls:Book.ItemTemplate>
</controls:Book>
<Button Content="<" HorizontalAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" Height="50" Click="AutoPreviousClick" />
<Button Content=">" HorizontalAlignment="Right" VerticalAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" Height="50" Click="AutoNextClick" />
</Grid>
</Viewbox>
</DockPanel>
</Window>
CODE:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Globalization;
using System.IO;
namespace Ebook
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
string html_str = "<p>The standard <b>Lorem Ipsum</b> passage, used since the 1500s</p>"
+ "<p>'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'</p>"
+ "<p>Section 1.10.32 of 'de Finibus Bonorum et Malorum', written by Cicero in 45 BC</p>"
+ "<p>'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?'</p>"
+ "<p><u>1914 translation by H. Rackham</u></p>"
+ "<p>'But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?'</p>"
+ "<p>Section 1.10.33 of 'de Finibus Bonorum et Malorum', written by Cicero in 45 BC</p>"
+ "<p>'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.'</p>"
+ "<p><i>1914 translation by H. Rackham</i></p>"
+ "<p>'On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain. These cases are perfectly simple and easy to distinguish. In a free hour, when our power of choice is untrammelled and when nothing prevents our being able to do what we like best, every pleasure is to be welcomed and every pain avoided. But in certain circumstances and owing to the claims of duty or the obligations of business it will frequently occur that pleasures have to be repudiated and annoyances accepted. The wise man therefore always holds in these matters to this principle of selection: he rejects pleasures to secure other greater pleasures, or else he endures pains to avoid worse pains.'</p>";
private void AutoNextClick(object sender, RoutedEventArgs e)
{
myBook.AnimateToNextPage(false, 700);
myBook.Focus();
}
private void AutoPreviousClick(object sender, RoutedEventArgs e)
{
myBook.AnimateToPreviousPage(false, 700);
myBook.Focus();
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
List<string> lines = WrapText(html_str, 200, "Arial", 12);
int rows = 20;
int pages = lines.Count / rows;
string _Page = "";
int j = 0, k = 0;
TextBlock tb1;
for (int i = 0; i < pages; i++)
{
tb1 = new TextBlock();
tb1.TextWrapping = TextWrapping.Wrap;
tb1.Margin = new Thickness(5);
tb1.TextAlignment = TextAlignment.Justify;
_Page = "";
for (j = 0; j < rows; j++)
{
_Page += lines[rows * i + j] + "\n";
k++;
}
//myBook.Items.Add(new TextBlock { Text = _Page, TextWrapping = TextWrapping.Wrap, Margin = new Thickness(5), TextAlignment = TextAlignment.Justify });
tb1.Inlines.AddRange(MarkupProcessor.HTMLToWPF(_Page));
myBook.Items.Add(tb1);
}
}
static List<string> WrapText(string text, double pixels, string fontFamily, float emSize)
{
string[] originalLines = text.Split(new string[] { " " },
StringSplitOptions.None);
List<string> wrappedLines = new List<string>();
StringBuilder actualLine = new StringBuilder();
double actualWidth = 0;
foreach (var item in originalLines)
{
FormattedText formatted = new FormattedText(item,
CultureInfo.CurrentCulture,
System.Windows.FlowDirection.LeftToRight,
new Typeface(fontFamily), emSize, Brushes.Black);
actualLine.Append(item + " ");
actualWidth += formatted.Width;
if (actualWidth > pixels)
{
wrappedLines.Add(actualLine.ToString());
actualLine = new StringBuilder();
actualWidth = 0;
}
}
if (actualLine.Length > 0)
wrappedLines.Add(actualLine.ToString());
return wrappedLines;
}
}
}
http://i.stack.imgur.com/AEpsm.png
Here's the download link to the project: http://www.megafileupload.com/en/file/532650/WPF-Ebook-zip.html
You can`t control number of lines because of this:
tb1.TextWrapping = TextWrapping.Wrap;
Line count will depend on length of string. Long strings will be wrapped.

How to show dynamic text big enough to auto fit stage size?

I have a dynamic text field on the stage, and i want the font size of the text to auto enarlge as per the stage size (which is 800x600). How can i do this?
If i manually enter big font size, and the text is much larger in lenght then it will clip off. Any ideas on this?
I am using Actionscript 3.
Thanks!
there are a couple of ways to accomplish this. if you want to use the same size font regardless of how much text you produce, you should use wordWrap = true on your text field. if you want to adjust the font depending on the amount of text in the field, it becomes a bit more tricky but not impossible. I would do something like this
var maxFont:int = 72;
var minFont:int = 9;
var currentSize:int;
var maxTxtWidth:int = 550;
var incTxt:String;
var tf:TextField = new TextField;
tf.autoSize = "left";
currentSize = maxFont;
while(tf.width > maxTxtWidth){
tf.htmlText = '<font size="'+currentSize+'">'+incTxt+'</font>';
if(currentSize == minFont){
break;
}
currentSize --;
}
then addchild etc as you normally would. there are other ways to do it, using styles, or textFormat but this is a fast solution, and the first to come to mind. Note that this particular syntax will only work properly for a single line of text. You can tweak it a bit and make it suitable for multiline. if you do use this technique, please clean it up, this is just spit out of my head directly.
ok with the help of the code from #NappingRabbit i concluded my own working code.
My main objective was to auto-resize the font size with respect to the stage size (550x400).
If the text length is few then show it as big as possible. And if the ext length is a lot then lower the font size.
Here's my working code for others who are seeking the same. (Flash CS4 / AS3)
var tf:TextField = new TextField();
var size:int = 72;
var foundLargeText:Boolean = false;
var txt:String = "Starting.... Lorem ipsum dolor sit amet, vim laudem argumentum te. Mel nihil nobis oratio ea. Ex sed dolores deterruisset, qui in eius liber. Ne qui minim iracundia, dictas saperet ut cum, id nobis conceptam persequeris sea. Eum at ferri dolor denique, mel audiam fabulas quaestio at. Illum voluptua facilisis nec eu, nam ea quem putent. Elitr aliquam mea ne. In eam iudico petentium scriptorem. Pro mucius oporteat te, impetus scriptorem sea ne, quo graecis menandri rationibus ex. Quando repudiare adipiscing mel cu, has insolens platonem te, eu quando scripta accusata quo. Idque dictas vis eu, an eripuit delenit conclusionemque pri. Et incorrupte signiferumque has, alia bonorum nec id, sea scripta insolens expetendis ne. This is end...";
tf.autoSize = "right";
tf.wordWrap = true;
tf.width = 540;
tf.htmlText = "<font size='"+size+"'>"+txt+"</font>";
tf.border = true;
while(tf.textHeight>=400){
size--;
foundLargeText = true;
tf.htmlText = "<font size='"+size+"'>"+txt+"</font>";
}
trace("using size: "+size);
if(foundLargeText){
tf.htmlText = "<font size='"+size+"'>"+txt+"</font>";
}
addChild(tf);
Thanks everybody!