Skip to content

Commit e88dd28

Browse files
BarelyML v0.2.1
- Fixes a bug where AsciiDoc link labels with spaces in them are not recognized - Improves BarelyML <--> Markdown conversion - Adds custom colour scheme and non-standard font to BarelyMLDemo - Improves drawing of text blocks
1 parent 1c3a206 commit e88dd28

File tree

4 files changed

+136
-53
lines changed

4 files changed

+136
-53
lines changed

BarelyML.cpp

Lines changed: 96 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
BarelyML.cpp
55
Created: 5 Oct 2023
66
Author: Fritz Menzer
7-
Version: 0.2
7+
Version: 0.2.1
88
99
==============================================================================
1010
Copyright (C) 2023 Fritz Menzer
@@ -114,11 +114,11 @@ void BarelyMLDisplay::resized()
114114
int h = margin;
115115
for (int i=0; i<blocks.size(); i++) {
116116
int bh;
117-
bh = blocks[i]->getHeightRequired(getWidth()-2*margin);
117+
bh = blocks[i]->getHeightRequired(getWidth()-2*margin)+5; // just to be on the safe side
118118
if (blocks[i]->canExtendBeyondMargin()) {
119119
blocks[i]->setBounds(0,h,getWidth(),bh);
120120
} else {
121-
blocks[i]->setBounds(margin,h,getWidth()-2*margin,bh);
121+
blocks[i]->setBounds(margin,h,getWidth()-2*margin,bh+10);
122122
}
123123
h += bh;
124124
}
@@ -190,14 +190,17 @@ void BarelyMLDisplay::setMarkupString(String s) {
190190
li++; // ...and go to next line.
191191
} else { // otherwise we assume that we have a text block
192192
StringArray blines; // set up text block lines
193+
bool blockEnd = false;
193194
while (!ListItem::isListItem(line) && // while line is not part of a list...
194195
!TableBlock::isTableLine(line) && // ...nor a table...
195196
!AdmonitionBlock::isAdmonitionLine(line) && // ...nor an admonition...
196197
!ImageBlock::isImageLine(line) && // ...nor an image...
197198
!Block::containsLink(line) && // ...and doesn't contain a link...
198-
li<lines.size()) { // ...and we're not done yet...
199+
li<lines.size() && !blockEnd) { // ...and we're not done yet...
199200
blines.add(line); // ...add line to text block lines...
200-
line = lines[++li]; // ...and read next line.
201+
blockEnd = line.isEmpty(); // ...and set up shouldEndBlock...
202+
line = lines[++li]; // ...read next line...
203+
blockEnd &= line.isNotEmpty(); // ...and finish shouldEndBloc...
201204
}
202205
TextBlock* b = new TextBlock(); // set up a new text block object...
203206
b->setColours(&colours); // ...set its colours...
@@ -237,7 +240,7 @@ String BarelyMLDisplay::convertFromMarkdown(String md) {
237240
String address = line.substring(idx2+2, idx3);
238241
line = line.substring(0, idx1) + "{{" + address + "}}" + line.substring(idx3+2);
239242
}
240-
// replace links
243+
// replace links with labels
241244
while (line.contains("[") &&
242245
line.fromFirstOccurrenceOf("[", false, false).contains("](") &&
243246
line.fromLastOccurrenceOf("](", false, false).contains(")")) {
@@ -247,7 +250,20 @@ String BarelyMLDisplay::convertFromMarkdown(String md) {
247250
int idx3 = line.indexOf(idx2+2, ")");
248251
String text = line.substring(idx1+1, idx2);
249252
String address = line.substring(idx2+2, idx3);
250-
line = line.substring(0, idx1) + "[[" + address + "|" + text + "]]" + line.substring(idx3+2);
253+
line = line.substring(0, idx1) + "[[" + address + "|" + text + "]]" + line.substring(idx3+1);
254+
}
255+
// replace links without labels
256+
while (line.contains("<") &&
257+
line.fromFirstOccurrenceOf("<", false, false).contains(">") && (
258+
line.fromFirstOccurrenceOf("<", false, false).startsWith("http://") ||
259+
line.fromFirstOccurrenceOf("<", false, false).startsWith("https://") ||
260+
line.fromFirstOccurrenceOf("<", false, false).startsWith("mailto:"))
261+
) {
262+
// replace links
263+
int idx1 = line.indexOf("<");
264+
int idx2 = line.indexOf(idx1+1, ">");
265+
String address = line.substring(idx1+1, idx2);
266+
line = line.substring(0, idx1) + "[[" + address + "]]" + line.substring(idx2+1);
251267
}
252268
// when in a table, skip lines which look like this : | --- | --- |
253269
if (!lastLineWasTable || !(line.containsOnly("| -\t") && line.isNotEmpty())) {
@@ -261,7 +277,7 @@ String BarelyMLDisplay::convertFromMarkdown(String md) {
261277
} else {
262278
lastLineWasTable = false; // ...otherwise, keep also track.
263279
}
264-
bml += line + "\n";
280+
bml += line + (li<lines.size()-1?"\n":"");
265281
}
266282
}
267283
// replace bold and italic markers
@@ -274,11 +290,60 @@ String BarelyMLDisplay::convertFromMarkdown(String md) {
274290
}
275291

276292
String BarelyMLDisplay::convertToMarkdown(String bml) {
277-
// NOTE: for now, all this method does is convert a BarelyML string
278-
// to something that convertFromMarkdown will turn into a
279-
// BarelyML string again.
293+
StringArray lines;
294+
lines.addLines(bml);
295+
String md;
296+
297+
bool isTable = false;
298+
for (int li=0; li<lines.size(); li++) {
299+
String line = lines[li];
300+
301+
// replace table headers
302+
if (line.startsWith("^") && !isTable) {
303+
isTable = true;
304+
line = line.replace("^", "|");
305+
// count columns
306+
String tmp = line.substring(1);
307+
Array<int> colWidths;
308+
while (tmp.contains("|")) {
309+
colWidths.add(tmp.indexOf("|"));
310+
tmp = tmp.fromFirstOccurrenceOf("|", false, false);
311+
}
312+
if (!colWidths.isEmpty()) {
313+
line += "\n|";
314+
for (int i=0; i<colWidths.size(); i++) {
315+
int nhyphen = jmax(3,colWidths[i]-2);
316+
line += " ";
317+
while (nhyphen>0) {
318+
line += "-";
319+
nhyphen--;
320+
}
321+
line += " |";
322+
}
323+
}
324+
}
325+
if (line.startsWith("^") | line.startsWith("|")) {
326+
isTable = true;
327+
} else {
328+
isTable = false;
329+
}
330+
331+
// replace links
332+
while (line.contains("[[") && line.fromFirstOccurrenceOf("[[", false, false).contains("]]")) {
333+
int idx1 = line.indexOf("[[");
334+
int idx2 = line.indexOf(idx1, "]]");
335+
String link = line.substring(idx1+2, idx2);
336+
if (link.contains("|")) {
337+
line = line.substring(0, idx1) + "[" + link.fromFirstOccurrenceOf("|", false, false) + "](" + link.upToFirstOccurrenceOf("|", false, false) + ")" + line.substring(idx2+2);
338+
} else {
339+
line = line.substring(0, idx1) + "<" + link + ">" + line.substring(idx2+2);
340+
}
341+
}
280342

281-
String md = bml;
343+
// add line
344+
md += line + (li<lines.size()-1?"\n":"");
345+
}
346+
282347
// replace bold markers
283348
md = md.replace("*", "**");
284349
return md;
@@ -325,7 +390,7 @@ String BarelyMLDisplay::convertFromDokuWiki(String dw) {
325390
if (line.startsWith(" * ")) { line = " - " + line.substring(10); }
326391
if (line.startsWith(" * ")) { line = " - " + line.substring(12); }
327392
// add line
328-
bml += line + "\n";
393+
bml += line + (li<lines.size()-1?"\n":"");
329394
}
330395

331396
// save the URLs
@@ -348,10 +413,6 @@ String BarelyMLDisplay::convertFromDokuWiki(String dw) {
348413
}
349414

350415
String BarelyMLDisplay::convertToDokuWiki(String bml) {
351-
// NOTE: for now, all this method does is convert a BarelyML string
352-
// to something that convertFromDokuWiki will turn into a
353-
// BarelyML string again.
354-
355416
StringArray lines;
356417
lines.addLines(bml);
357418
String dw;
@@ -383,7 +444,7 @@ String BarelyMLDisplay::convertToDokuWiki(String bml) {
383444
if ( line.substring(0, didx).containsOnly("0123456789")) { line = " - " + line.substring(didx+2); }
384445
}
385446
// add line
386-
dw += line + "\n";
447+
dw += line + (li<lines.size()-1?"\n":"");
387448
}
388449

389450
// replace color markers (supporting a subset of the "color" plugin syntax)
@@ -493,6 +554,10 @@ String BarelyMLDisplay::convertFromAsciiDoc(String ad) {
493554
int idx2 = line.indexOf(idx1, " ");
494555
if (idx2<0) { idx2 = line.indexOf(idx1, "\t"); }
495556
if (idx2<0) { idx2 = line.length(); }
557+
// needed for cases like this: [JUCE Forum] (space in label)
558+
if (line.substring(idx1, idx2).contains("[")) {
559+
idx2 = jmax(idx2, line.indexOf(idx1, "]")+1);
560+
}
496561
String link = line.substring(idx1, idx2);
497562
if (link.contains("[") && link.endsWith("]")) {
498563
int lidx = link.indexOf("[");
@@ -506,7 +571,7 @@ String BarelyMLDisplay::convertFromAsciiDoc(String ad) {
506571

507572
// add line
508573
if (!skipLine) {
509-
bml += line + "\n";
574+
bml += line + (li<lines.size()-1?"\n":"");
510575
}
511576
}
512577

@@ -526,10 +591,6 @@ String BarelyMLDisplay::convertFromAsciiDoc(String ad) {
526591
}
527592

528593
String BarelyMLDisplay::convertToAsciiDoc(String bml) {
529-
// NOTE: for now, all this method does is convert a BarelyML string
530-
// to something that convertFromAsciiDoc will turn into a
531-
// BarelyML string again.
532-
533594
StringArray lines;
534595
lines.addLines(bml);
535596
String ad;
@@ -594,7 +655,7 @@ String BarelyMLDisplay::convertToAsciiDoc(String bml) {
594655
if (line.startsWith("HINT: ")) { line = "TIP: " + line.substring(6); }
595656

596657
// add line
597-
ad += line + "\n";
658+
ad += line + (li<lines.size()-1?"\n":"");
598659
}
599660

600661
// replace color markers (named colors only)
@@ -673,9 +734,10 @@ void BarelyMLDisplay::Block::mouseUp(const MouseEvent& event) {
673734
}
674735
}
675736

676-
AttributedString BarelyMLDisplay::Block::parsePureText(const StringArray& lines, Font font)
737+
AttributedString BarelyMLDisplay::Block::parsePureText(const StringArray& lines, Font font, bool addNewline)
677738
{
678739
AttributedString attributedString;
740+
679741
String currentLine;
680742
currentColour = defaultColour;
681743

@@ -686,23 +748,23 @@ AttributedString BarelyMLDisplay::Block::parsePureText(const StringArray& lines,
686748
{
687749
if (line.startsWith("##### "))
688750
{
689-
attributedString.append(line.substring(6), font.boldened().withHeight(font.getHeight()*1.1f), defaultColour);
751+
attributedString.append(parsePureText(line.substring(6), font.boldened().withHeight(font.getHeight()*1.1f),false));
690752
}
691753
else if (line.startsWith("#### "))
692754
{
693-
attributedString.append(line.substring(5), font.boldened().withHeight(font.getHeight()*1.25f), defaultColour);
755+
attributedString.append(parsePureText(line.substring(5), font.boldened().withHeight(font.getHeight()*1.25f),false));
694756
}
695757
else if (line.startsWith("### "))
696758
{
697-
attributedString.append(line.substring(4), font.boldened().withHeight(font.getHeight()*1.42f), defaultColour);
759+
attributedString.append(parsePureText(line.substring(4), font.boldened().withHeight(font.getHeight()*1.42f),false));
698760
}
699761
else if (line.startsWith("## "))
700762
{
701-
attributedString.append(line.substring(3), font.boldened().withHeight(font.getHeight()*1.7f), defaultColour);
763+
attributedString.append(parsePureText(line.substring(3), font.boldened().withHeight(font.getHeight()*1.7f),false));
702764
}
703765
else if (line.startsWith("# "))
704766
{
705-
attributedString.append(line.substring(2), font.boldened().withHeight(font.getHeight()*2.1f), defaultColour);
767+
attributedString.append(parsePureText(line.substring(2), font.boldened().withHeight(font.getHeight()*2.1f),false));
706768
}
707769
else
708770
{
@@ -778,7 +840,9 @@ AttributedString BarelyMLDisplay::Block::parsePureText(const StringArray& lines,
778840
}
779841
}
780842

781-
attributedString.append(" \n", font, defaultColour);
843+
if (addNewline) {
844+
attributedString.append(" \n", font, defaultColour);
845+
}
782846
}
783847
return attributedString;
784848
}
@@ -796,8 +860,7 @@ float BarelyMLDisplay::TextBlock::getHeightRequired(float width) {
796860
}
797861

798862
void BarelyMLDisplay::TextBlock::paint(juce::Graphics& g) {
799-
// g.fillAll(Colours::lightblue); // clear the background
800-
attributedString.draw(g, getLocalBounds().toFloat().expanded(0, 1.f));
863+
attributedString.draw(g, getLocalBounds().toFloat());
801864
}
802865

803866
// MARK: - Admonition Block
@@ -942,7 +1005,6 @@ void BarelyMLDisplay::TableBlock::resized() {
9421005
}
9431006

9441007
void BarelyMLDisplay::TableBlock::Table::paint(juce::Graphics& g) {
945-
// g.fillAll(Colours::lightpink); // clear the background
9461008
float y = 0.f; // Y coordinate of cell's top left corner
9471009
for (int i=0; i<cells.size(); i++) {
9481010
float x = leftmargin; // X coordinate of cell's top left corner

BarelyML.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
BarelyML.h
55
Created: 5 Oct 2023
66
Author: Fritz Menzer
7-
Version: 0.2
7+
Version: 0.2.1
88
99
==============================================================================
1010
Copyright (C) 2023 Fritz Menzer
@@ -185,14 +185,17 @@ class BarelyMLDisplay : public juce::Component
185185
juce::String consumeLink(juce::String line);
186186
virtual void parseMarkup(const juce::StringArray& lines, juce::Font font) {};
187187
virtual float getHeightRequired(float width) = 0;
188-
void setColours(juce::StringPairArray* c) { colours = c; };
188+
void setColours(juce::StringPairArray* c) {
189+
colours = c;
190+
defaultColour = parseHexColour((*colours)["default"]);
191+
};
189192
virtual bool canExtendBeyondMargin() { return false; }; // for tables
190193
// mouse handlers for clicking on links
191194
void mouseDown(const juce::MouseEvent& event) override;
192195
void mouseUp(const juce::MouseEvent& event) override;
193196

194197
protected:
195-
juce::AttributedString parsePureText(const juce::StringArray& lines, juce::Font font);
198+
juce::AttributedString parsePureText(const juce::StringArray& lines, juce::Font font, bool addNewline = true);
196199
juce::Colour defaultColour;
197200
juce::Colour currentColour;
198201
juce::StringPairArray* colours;
@@ -249,7 +252,7 @@ class BarelyMLDisplay : public juce::Component
249252
private:
250253
typedef struct {
251254
juce::AttributedString s;
252-
bool isHeader;
255+
bool isHeader;
253256
float width;
254257
float height;
255258
} Cell;

0 commit comments

Comments
 (0)