I'm using the Atlassian Commonmark API found here to parse Markdown to HTML.
Works beautifully, but tends to add <pand </p>to the beginning and end of every parsed String.
Has anyone used the API extensively in the past and/or has any idea how I could get it to stop doing this?
Other than manually removing the paragraph afterwards, that is, which feels ... unclean somehow.
Edit for clarification: The converted code snippets are intended for use in an HTML table, so I don't need the paragraph bits before and after them.
The Markdown input might be:
####Text for the table here.
The output I'm getting is:
<p><h6>Text for the table here.</h6></p>
What I want is simply for the paragraph snips not to be added:
<h6>Text for the table here.</h6>
Was looking for this as well. I achieved it by creating a simple custom renderer that does not render the top level <p>aragraphs.
It checks if the parent of a paragraph is the Document node and if yes it does only render the children of the paragraph.
It extends the default renderer (CoreHtmlNodeRenderer) to get access to visitChildren() and visit(Paragraph)
in kotlin:
class SkipParentWrapperParagraphsRenderer(val context: HtmlNodeRendererContext)
: CoreHtmlNodeRenderer(context), NodeRenderer {
override fun getNodeTypes(): Set<Class<out Node>> {
return setOf(Paragraph::class.java)
}
override fun render(node: Node) {
if (node.parent is Document) {
visitChildren(node)
} else {
visit(node as Paragraph)
}
}
}
register the new renderer:
val renderer: HtmlRenderer = HtmlRenderer
.builder()
.nodeRendererFactory { context -> SkipParentWrapperParagraphsRenderer(context) }
.build()
There is an example in the documentation.
Related
I am writing java code to access a document open in Libre Office.
I now need to write some code which iterate over the entire document, hopefully in the same order it is shown in the editor.
I can use this code to iterate over all the normal text:
XComponent writerComponent=xComponentLoader.loadComponentFromURL(loadUrl, "_blank", 0, loadProps);
XTextDocument mxDoc=UnoRuntime.queryInterface(XTextDocument.class, writerComponent);
XText mxDocText=mxDoc.getText();
XEnumerationAccess xParaAccess = (XEnumerationAccess) UnoRuntime.queryInterface(XEnumerationAccess.class, mxDocText);
XEnumeration xParaEnum = xParaAccess.createEnumeration();
Object element = xParaEnum.nextElement();
while (xParaEnum.hasMoreElements()) {
XEnumerationAccess inlineAccess = (XEnumerationAccess) UnoRuntime.queryInterface(XEnumerationAccess.class, element);
XEnumeration inline = inlineAccess.createEnumeration();
// And I can then iterate over this inline element and get all the text and formatting.
}
But the problem is that this does not include any chart objects.
I can then use
XDrawPagesSupplier drawSupplier=UnoRuntime.queryInterface(XDrawPagesSupplier.class, writerComponent);
XDrawPages pages=drawSupplier.getDrawPages();
XDrawPage drawPage=UnoRuntime.queryInterface(XDrawPage.class,page);
for(int j=0;j!=drawPage.getCount();j++) {
Object sub=drawPage.getByIndex(j);
XShape subShape=UnoRuntime.queryInterface(XShape.class,sub);
// Now I got my subShape, but how do I know its position, relative to the text.
}
And this gives me all charts (And other figures I guess), but the problem is: How do I find out where these charts are positioned in relation to the text in the model. And how do I get a cursor which represent each chart?
Update:
I am now looking for an anchor for my XShape, but XShape don't have a getAnchor() method.
But If I use
XPropertySet prop=UnoRuntime.queryInterface(XPropertySet.class,shape);
I get the prop class.
And I call prop.getPropertyValue("AnchorType") which gives me an ancher type of TextContentAnchorType.AS_CHARACTER
but I just can't get the anchor itself. There are no anchor or textrange property.
btw: I tried looking into installing "MRI" for libre office, but the only version I could find hav libreoffice 3.3 as supported version, and it would not install on version 7.1
----- Update 2 -----
I managed to make it work. It turns out that my XShape also implements XTextContent (Thank you MRI), so all I had to do was:
XTextContent subContent=UnoRuntime.queryInterface(XTextContent.class,subShape);
XTextRange anchor=subContent.getAnchor();
XTextCursor cursor = anchor.getText().createTextCursorByRange(anchor.getStart());
cursor.goRight((short)50,true);
System.out.println("String=" + cursor.getString());
This gives me a cursor which point to the paragraph, which I can then move forward/backward to find out where the shape is. So this println call will print the 50 chars following the XShape.
How do I find out where these charts are positioned in relation to the text in the model. And how do I get a cursor which represent each chart?
Abridged comments
Anchors pin objects to a specific location. Does the shape have a method getAnchor() or property AnchorType? I would use an introspection tool such as MRI to determine this. Download MRI 1.3.4 from https://github.com/hanya/MRI/releases.
As far as a cursor, maybe it is similar to tables:
oText = oTable.getAnchor().getText()
oCurs = oText.createTextCursor()
Code solution given by OP
XTextContent subContent=UnoRuntime.queryInterface(XTextContent.class,subShape);
XTextRange anchor=subContent.getAnchor();
XTextCursor cursor = anchor.getText().createTextCursorByRange(anchor.getStart());
cursor.goRight((short)50,true);
System.out.println("String=" + cursor.getString());
I want to use a single YAML file which contains several different objects - for different applications. I need to fetch one object to get an instance of MyClass1, ignoring the rest of docs for MyClass2, MyClass3, etc. Some sort of selective de-serializing: now this class, then that one... The structure of MyClass2, MyClass3 is totally unknown to the application working with MyClass1. The file is always a valid YAML, of course.
The YAML may be of any structure we need to implement such a multi-class container. The preferred parsing tool is snakeyaml.
Is it sensible? How can I ignore all but one object?
UPD: replaced all "document" with "object". I think we have to speak about the single YAML document containing several objects of different structure. More of it, the parser knows exactly only 1 structure and wants to ignore the rest.
UDP2: I think it is impossible with snakeyaml. We have to read all objects anyway - and select the needed one later. But maybe I'm wrong.
UPD2: sample config file
---
-
exportConfiguration781:
attachmentFieldName: "name"
baseSftpInboxPath: /home/user/somedir/
somebool: false
days: 9999
expected:
- ABC w/o quotes
- "Cat ABC"
- "Some string"
dateFormat: yyyy-MMdd-HHmm
user: someuser
-
anotherConfiguration:
k1: v1
k2:
- v21
- v22
This is definitely possible with SnakeYAML, albeit not trivial. Here's a general rundown what you need to do:
First, let's have a look what loading with SnakeYAML does. Here's the important part of the YAML class:
private Object loadFromReader(StreamReader sreader, Class<?> type) {
Composer composer = new Composer(new ParserImpl(sreader), resolver, loadingConfig);
constructor.setComposer(composer);
return constructor.getSingleData(type);
}
The composer parses YAML input into Nodes. To do that, it doesn't need any knowledge about the structure of your classes, since every node is either a ScalarNode, a SequenceNode or a MappingNode and they just represent the YAML structure.
The constructor takes a root node generated by the composer and generates native POJOs from it. So what you want to do is to throw away parts of the node graph before they reach the constructor.
The easiest way to do that is probably to derive from Composer and override two methods like this:
public class MyComposer extends Composer {
private final int objIndex;
public MyComposer(Parser parser, Resolver resolver, int objIndex) {
super(parser, resolver);
this.objIndex = objIndex;
}
public MyComposer(Parser parser, Resolver resolver, LoaderOptions loadingConfig, int objIndex) {
super(parser, resolver, loadingConfig);
this.objIndex = objIndex;
}
#Override
public Node getNode() {
return strip(super.getNode());
}
private Node strip(Node input) {
return ((SequenceNode)input).getValue().get(objIndex);
}
}
The strip implementation is just an example. In this case, I assumed your YAML looks like this (object content is arbitrary):
- {first: obj}
- {second: obj}
- {third: obj}
And you simply select the object you actually want to deserialize by its index in the sequence. But you can also have something more complex like a searching algorithm.
Now that you have your own composer, you can do
Constructor constructor = new Constructor();
// assuming we want to get the object at index 1 (i.e. second object)
Composer composer = new MyComposer(new ParserImpl(sreader), new Resolver(), 1);
constructor.setComposer(composer);
MyObject result = (MyObject)constructor.getSingleData(MyObject.class);
The answer of #flyx was very helpful for me, opening the way to workaround the library (in our case - snakeyaml) limitations by overriding some methods. Thanks a lot! It's quite possible there is a final solution in it - but not now. Besides, the simple solution below is robust and should be considered even if we'd found the complete library-intruding solution.
I've decided to solve the task by double distilling, sorry, processing the configuration file. Imagine the latter consisting of several parts and every part is marked by the unique token-delimiter. For the sake of keeping the YAML-likenes, it may be
---
#this is a unique key for the configuration A
<some YAML document>
---
#this is another key for the configuration B
<some YAML document
The first pass is pre-processing. For the given String fileString and String key (and DELIMITER = "\n---\n". for example) we select a substring with the key-defined configuration:
int begIndex;
do {
begIndex= fileString.indexOf(DELIMITER);
if (begIndex == -1) {
break;
}
if (fileString.startsWith(DELIMITER + key, begIndex)) {
fileString = fileString.substring(begIndex + DELIMITER.length() + key.length());
break;
}
// spoil alien delimiter and repeat search
fileString = fileString.replaceFirst(DELIMITER, " ");
} while (true);
int endIndex = fileString.indexOf(DELIMITER);
if (endIndex != -1) {
fileString = fileString.substring(0, endIndex);
}
Now we feed the fileString to the simple YAML parsing
ExportConfiguration configuration = new Yaml(new Constructor(ExportConfiguration.class))
.loadAs(fileString, ExportConfiguration.class);
This time we have a single document that must co-respond to the ExportConfiguration class.
Note 1: The structure and even the very content of the rest of configuration file plays absolutely no role. This was the main idea, to get independent configurations in a single file
Note 2: the rest of configurations may be JSON or XML or whatever. We have a method-preprocessor that returns a String configuration - and the next processor parses it properly.
I would like to extend the CDT language plugin for gnu c, to create some kind of new language based on this.
The new language should have a different visual appearence in editor. I would like to color a method body in gray if there is a special pre-processor directive in front of (like an annotation).
Does anybody know where to extend the GCC language for a modification like this?
EDIT1:
As example I want that the colour of the method body of specialFunction to be gray, as a reason of an example annotation -> #annotation
#annotation
int specialFunction(){
return 1;
}
EDIT2:
What i have tried so far is to build a "extended language". The plan was to highlight a preprocessor position and also save the position so that the method below would be colored. I managed to get the preprocessor keyword colored but not how to work on method bodies color.
public class OwnKeyWords extends GCCLanguage implements ICLanguageKeywords
#Override
public String[] getPreprocessorKeywords() {
//System.out.println("Called keywords" + timesPre++);
return new String[]{
"hide",
"show"
};
}
Example to be colored:
#hide
int specialFunction(){
return 1;
}
In the example above "hide" would be highlighted.
EDIT3:
I tried to implement ISemanticHighlighter and tried a few ways to highlight my code:
CVariable
CFunction
ObjectStyleMacro
...
But non of them where suitable to highlight a method body with a preprocessor directive or anything else on top.
Also the note in ISemanticHighlighter:
* NOTE: Implementors are not allowed to keep a reference on the token or on any object retrieved from the
* token.
Is not what I want to achieve, because I would like to keep reference to the highlighted object for later operations.
Maybe the org.eclipse.cdt.ui.text.folding.DefaultCFoldingStructureProvider would be an option too, there I couldn't colour the instrumentation, I could instead hide it.
This does not sound like a new language so much as semantic highlighting.
CDT has a great extension point called org.eclipse.cdt.ui.semanticHighlighting that allows you to define custom semantic highlighting rules.
Here is an example of the plugin.xml entry:
<extension
point="org.eclipse.cdt.ui.semanticHighlighting">
<semanticHighlighting
class="com.example.SemanticHighlighter"
defaultBold="true"
defaultEnabled="true"
defaultTextColor="35,0,35"
displayName="Example Semantic Highlighter"
id="com.example.SemanticHighlighter"
preferenceKey="com.example.SemanticHighlighter.pref"
priority="5">
</semanticHighlighting>
</extension>
Then in your com.example.SemanticHighlighter you implement the org.eclipse.cdt.ui.text.ISemanticHighlighter interface. There is only one method, consumes that takes a ISemanticToken. Analyse the token to see if it is relevant to your highlighter and return true to have it highlighted.
Here is a trivial implementation of the method:
#Override
public boolean consumes(ISemanticToken token) {
IBinding binding = token.getBinding();
if (binding instanceof IFunction) {
IASTNode node = token.getNode();
if (binding != null && node instanceof IASTName && ((IASTName) node).isReference()) {
String n = binding.getName();
if ("MySpecialFunction".equals(n)) {
return true;
}
}
}
return false;
}
Once implemented, users can modify the colour and applicability via the preference page C/C++ - Editor - Syntax Coloring:
You should be able to use ISemanticHighlighter to do the kind of highlighting you want.
For your example of coloring the body of a function with a particular annotation, it could work like this:
class MyHighlighter implements ISemanticHighlighter {
#Override
public boolean consumes(ISemanticToken token) {
IASTNode node = token.getNode();
// Walk up the AST to determine if 'node' is inside a function body.
// If it's not, return false.
// Navigate the AST some more to examine what comes before the
// function's declaration. If it's the annotation in question,
// return true. Otherwise, return false.
}
}
I left out the details of how to navigate the AST, but CDT has a pretty rich AST API so it's definitely doable. Feel free to ask specific questions if you have them.
Basically I have changed the css for a text field in javafx by adding a style class like this:
textfield.getStyleClass().add("textfieldstyle");
But then I want to be able to revert it back to its original appearance. But since the original appearance in this case is the default skin for JavaFX, I can't find the original layout for the textfields. I found the textfieldskin properties here, but its a jungle, and I can't find anything about the color of the -fx-control-inner-background, -fx-text-box-border and -fx-focus-color, which is what I want to know.
I've triedtextfield.getStyleClass().remove("textfieldstyle"); and think that does remove the new css, but it doesn't apply the old one again.
Thanks to the comments by #UlukBiy and #varren I solved the issue. System.out.println(textfield.getStyleClass()); was of great use since it allowed me to check which style classes were applied on the text field as default. And as it is pointed out in the comments those where text-input and text-field.
So to restore the text field's css to its default value I just did:
textfield.getStyleClass().clear();
textfield.getStyleClass().addAll("text-field", "text-input");
To reset an element's default styling after setting it using .setStyle("css settings....."); you can simply use -
textfield.setStyle(null);
I'm not sure if this would work on it's own for an element that's had a class applied using .getStyleClass().add("textfieldstyle"); but if not you could do something like -
textfield.getStyleClass().clear();
textfield.setStyle(null);
A short way to effictively remove your style class even in case of duplicates, with a lambda :
textfield.getStyleClass().removeIf(style -> style.equals("textfieldstyle"));
The following test code works for me when adding and removing a class from a control such as Textfield:
import javafx.scene.control.TextInputControl;
public class test
{
protected void setEditable(final TextInputControl toControl, final boolean tlEditable)
{
toControl.setEditable(tlEditable);
if (tlEditable)
{
if (toControl.getStyleClass().contains("non-editable-class"))
{
toControl.getStyleClass().removeAll("non-editable-class");
}
}
else if (!toControl.getStyleClass().contains("non-editable-class"))
{
toControl.getStyleClass().add("non-editable-class");
}
}
}
I have to check some textField with the following rule:
if (the value A != the value B) {
this.A.forceInvalid("");
}
This work really fine, but I want to remove the "info bubble" of the error,on the textfield.
I have tried to simply put a css with red border around it, but it seems that my superior dont want that.
How can I erase that bubble?
First of all, this validation looks wrong. It seems you are using gxt Field which already has built-in validators. Here is an example:
yourField.addValidator(new Validator<String>() {
#Override
public List<EditorError> validate(Editor<String> editor, String value) {
final List<EditorError> errors = new ArrayList<EditorError>();
if (!value.equals("test")) {
errors.add(new DefaultEditorError(yourField, "Value is not \"test\"", value));
}
return errors;
}
});
By default it looks like this:
You can change it by using non-default ErrorHandler on the field. It is not clear what exactly do you want, as far as I can understand you want to get rid of (!) sign and its popup. I think that TitleErrorHandler will suit your needs.
yourField.setErrorSupport(new TitleErrorHandler(yourField));