How do you insert HTML into a text node in AngleSharp? - anglesharp

I'm parsing a document with AngleSharp. I have a text node (NodeName: "#text") and I want to insert some HTML in it. I can certainly reset NodeValue to whatever I want, but it's still a text node, so all the brackets are escaped.
How do I take the string value of a text node, inject some HTML into it, then have a parsed DOM representation that that HTML take the place of the original text node?

I guess what you want is to replace a single text node by multiple nodes.
For instance <div>foo</div>, i.e.,
+ root
+ textnode
becomes
+ root
+ textnode (1)
+ element
+ textnode (2)
which could <div>f<b>o</b>o</div>. The simplest way I can think of is just replacing the node.
var source = #"<div>foo</div>";
var parser = new HtmlParser();
var document = parser.Parse(source);
var div = document.QuerySelector("div");
div.InnerHtml = div.InnerHtml.Replace("foo", "f<b>o</b>o");
Now you can argue that just replacing the text may not be what you want. You maybe have already elements that you want to insert. Therefore a better (yet more complex) way would be to split the text node and insert the remaining contents.
var source = #"<div>foo</div>";
var parser = new HtmlParser();
var document = parser.Parse(source);
var div = document.QuerySelector("div");
var text = div.TextContent;
div.RemoveChild(div.FirstChild); // assuming there is only one child
var bold = document.CreateElement("b");
bold.TextContent = text.Substring(1, 1); //o
div.Append(
document.CreateTextNode(text.Substring(0, 1)), //f
bold,
document.CreateTextNode(text.Substring(2, 1)));//o
Depending in your use-case there may be a more simple solution.

Related

How can i write a conditional statement with Text as its values?

Firstly, I created some text values
Text gamecon1 = Text('1v1 Box Fight');
Text gamecon1duo = Text('1v1 Duos');
Text gamecon2 = Text('2v2 Box Fight');
Text gamecon2sq = Text('2v2 Squads');
Text gamecon3 = Text('3v3 Box Fight');
Text gamecon4 = Text('4v4 Box Fight');
Then i queried a document field from firestore and wrote a conditional statement
Text((() {
if (tourneyDetails['tourneyprizes'] ==
gamecon1) {
return multiplier = 8;
} else if (tourneyDetails[
'tourneyprizes'] ==
gamecon1duo) {
return multiplier = 5;
String calculator = (int.parse(
tourneyDetails[
'tourneycost']) *
multiplier)
.toString();
String calculatordivide =
(double.parse(calculator) / 100.0)
.toString();
String calculatorpercentage =
(double.parse(calculatordivide) *
20)
.toString();
String calculatorfinal =
(double.parse(calculator) -
double.parse(
calculatorpercentage))
.toString();
return calculatorfinal;
What i am trying to accomplish is, if the document field is equal to one the text values, then it should run the calculation and return the value.
but this doesn't work.
After some troubleshooting, i realised that even when the text value is the same as the document field queried, flutter still doesn't recognise it.
If you need more context feel free to comment. Thanks
Without knowing what the type definition of tourneyDetails is I cannot be sure but I suspect that you are trying to compare a String (in tourneyDetails) with a Text widget. If so, they will never equate. You should be defining your strings as constants eg. const gamecon1 = '1v1 Box Fight'; then the comparison should equate.
Text() is a widget. You want to compare Strings.
if (tourneyDetails['tourneyprizes'] == gamecon1.data)
or
define String gamecon1 = 'gamecon1' and tourneyDetails must also be an array of Strings.

InDesign - Script to find specific words between angle brackets, and copy those to a list

Sorry in advance if I’m not phrasing this question correctly. I know nothing about InDesign scripting, but this would solve a workflow problem I’m having at my company, so I would appreciate any and all help.
I want to find all strings in an InDesign file that are between angle brackets (i.e. <variable>) and export that out into a list. Ideally this list would be a separate document but if it can just be dumped into a text frame or something that’s fine.
Any ideas on how to do this? Thank you in advance for any and all help.
Here is something simple:
app.findGrepPreferences=NothingEnum.NOTHING; //to reset the Grep search
app.findGrepPreferences.findWhat = '<[^<]+?>'; //the word(s) you are searching
var fnd = app.activeDocument.findGrep (); //execute search
var temp_str = ''; //initialize an empty string
for (var i = 0; i < fnd.length; i++) { //loop through results and store the results
temp_str += fnd[i].contents.toString() + '\r'; // add next found item text to string
}
var new_doc = app.documents.add (); //create a new document
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS; //set measurement units to points
var text_frame = new_doc.pages[0].textFrames.add({geometricBounds:[0,0,100,100]});// create a new text frame on the first page
text_frame.contents = temp_str; //output your text to the text frame in the new document
For more data see here.

How to build a simple widget or app in jupyter notebook/lab to interactively extract a substring from text?

I want iterate over a list of string, output the string as plain text in jupyter lab then interactively highlight a substring to get easily the start index of the substring and the length. The goal is to do a quick annotation of text and get the coordinates of the substring.
Is it easy or even possible to do something like this with jupyter notebook (lab)? If then How?
I had a look at ipywidgets but couldn't find something for this use case.
Here's an example with the RangeSlider:
import ipywidgets
input_string = 'averylongstring'
widg = ipywidgets.IntRangeSlider(
value = [0, len(input_string)],
min=0, max=len(input_string)
)
output_widg = ipywidgets.Text()
display(widg)
display(output_widg)
def chomp_string(widg):
start,end = tuple(widg['new'])
output_widg.value = input_string[start: end]
widg.observe(chomp_string, names='value')
You can implement this using jp_proxy_widgets. See the following screenshot:
Note that there are warnings about compatibility for selection protocols -- I only tested this on Chrome on a Mac. Also I don't know why the indices are off by one
(select_callback(startOffset+1, endOffset+1);)
Please see https://github.com/AaronWatters/jp_proxy_widget for more information
Edit: Here is the pastable text as requested:
import jp_proxy_widget
select_widget = jp_proxy_widget.JSProxyWidget()
txt = """
Never gonna give you up.
Never gonna let you down.
Never gonna run around and
desert you.
"""
selected_text = None
def select_callback(startOffset, endOffset):
global selected_text
selected_text = txt[startOffset: endOffset]
print ("Selected", startOffset, endOffset, repr(selected_text))
select_widget.js_init("""
// (Javascript) Add a text area.
element.empty()
$("<h3>please select text:</h3>").appendTo(element);
var textarea = $('<textarea cols="50" rows="5">' + txt + "</textarea>").appendTo(element);
// Attach a select handler that calls back to select_callback.
var select_handler = function(event) {;
var target = event.target;
var startOffset = target.selectionStart;
var endOffset = target.selectionEnd;
select_callback(startOffset+1, endOffset+1);
};
textarea[0].addEventListener('select', select_handler);
""", txt=txt, select_callback=select_callback)
# display the widget
select_widget.debugging_display()

Set inner HTML using QDomDocument

How can I set the inner HTML in a QDomElement?
When I’m using QWebElement I have the method QWebElement::setInnerXml, there is some similar method in QDomElement?
There's no API to "inject" XML snippets as text into a QDomDocument (or QXmlStreamWriter). One has to use the API and create the nodes programmatically.
Assuming you have a string to start with, my current solution is to generate a DOM tree from it, import that tree in a fragment, then copy those in the right place (you must have an import which is why you need an intermediate fragment. Quite unfortunate if you ask me.)
// assuming that 'n' is the node you are replacing or at least inserting after
// 'parent' is the parent of 'n'
// 'result' is the string to replace 'n' or insert after 'n'
QDomDocument doc_text("snap");
doc_text.setContent("<text>" + result + "</text>", true, NULL, NULL, NULL);
QDomDocumentFragment frag(xml.createDocumentFragment());
frag.appendChild(xml.importNode(doc_text.documentElement(), true));
QDomNodeList children(frag.firstChild().childNodes());
const int max(children.size());
QDomNode previous(n);
for(int i(0); i < max; ++i)
{
QDomNode l(children.at(0));
parent.insertAfter(children.at(0), previous);
previous = l;
}
// if you are replacing, then delete node n as well
parent.removeChild(n);
Note that the <text> tag is used so that way result does not need to be a tag, it could just be text and it will still work.
Obviously, if you have a fragment or XML from another document to start with, ignore the code that creates that code in the doc_text object.

Removing last char from textfield without destroying textformat

i have a problem where i want to remove the last character from a textfield (including linebreaks) that has multiple textformats without removing the formats.
so far i have:
textfield.replaceText(textField.length-1,textField.length-1,'');
i guess this doesn't remove linebreaks, and is very slow, seems to destroy my textformats.
or:
textfield.text = textfield.text.slice(0,-1);
this is faster but removes all textformats as well.
It is a bit tedious, but you can use the htmlText-property of TextField, even though you are not formatting your text with StyleSheets: Flash will transform all your formatting information into HTML text internally, so even though you set textField.text, you can still get xml formatted text to work with:
textField.text = "A test.";
trace (textField.htmlText);
will actually return:
<P ALIGN="LEFT"><FONT FACE="Times Roman" SIZE="12" COLOR="#000000" LETTERSPACING="0" KERNING="0">A test.</FONT></P>
Text will always appear within <FONT> tags reflecting the changes you made using setTextFormat(). You can, therefore, iterate over the XML contained in this line, and remove only the last character in the last TextNode:
private function removeLastCharacter (textField:TextField) : void {
var xml:XML = new XML (textField.htmlText);
for ( var i : int = xml.children().length()-1; i >= 0; i-- ){
var node:XML = xml.children()[i];
if ( node.name() == "FONT") {
var tx:String = node.text()[0].toString();
node.setChildren (tx.substr (0, tx.length-1));
break;
}
}
textField.htmlText = xml;
trace (textField.text); // In the above example, output will be: "A test";
}
I hope I understand your problem correctly. If you keep your formatting in htmlText, I have one possible solution:
The idea is to keep the formatted text in an XML format, and modify the XML. XML will keep your formatting intact, you don't have to do string aerobatics to maintain them. The downsides are of course having to keep the formatting XML valid, and the extra variable.
Here's an example:
var tf:TextField = new TextField();
var t:XML = new XML("<html><p>lalala</p><font color='#ff0000'> lol</font></html>");
tf.htmlText = t.toXMLString();
t.font[0] = t.font[0].text().slice(0, -1);
tf.htmlText = t.toXMLString();
addChild(tf);

Resources