HaikuDepot: Added very simplistic markup parser.
* Follows MediaWiki or TracWiki style. * Supports only level 2 headings, bold, italic and top-level bullet paragraphs. * Line break handling would need to be changed. * Outputs a TextDocument.
This commit is contained in:
parent
c6a0782a8f
commit
59b52a1163
@ -17,6 +17,7 @@ local textDocumentSources =
|
||||
BulletData.cpp
|
||||
CharacterStyle.cpp
|
||||
CharacterStyleData.cpp
|
||||
MarkupParser.cpp
|
||||
Paragraph.cpp
|
||||
ParagraphLayout.cpp
|
||||
ParagraphStyle.cpp
|
||||
|
233
src/apps/haiku-depot/textview/MarkupParser.cpp
Normal file
233
src/apps/haiku-depot/textview/MarkupParser.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "MarkupParser.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <utf8_functions.h>
|
||||
|
||||
|
||||
MarkupParser::MarkupParser()
|
||||
:
|
||||
fNormalStyle(),
|
||||
fBoldStyle(),
|
||||
fItalicStyle(),
|
||||
fBoldItalicStyle(),
|
||||
fHeadingStyle(),
|
||||
|
||||
fParagraphStyle(),
|
||||
fHeadingParagraphStyle(),
|
||||
fBulletStyle(),
|
||||
|
||||
fCurrentCharacterStyle(&fNormalStyle),
|
||||
fCurrentParagraphStyle(&fParagraphStyle)
|
||||
{
|
||||
_InitStyles();
|
||||
}
|
||||
|
||||
|
||||
MarkupParser::MarkupParser(const CharacterStyle& characterStyle,
|
||||
const ParagraphStyle& paragraphStyle)
|
||||
:
|
||||
fNormalStyle(characterStyle),
|
||||
fBoldStyle(),
|
||||
fItalicStyle(),
|
||||
fBoldItalicStyle(),
|
||||
fHeadingStyle(),
|
||||
|
||||
fParagraphStyle(paragraphStyle),
|
||||
fHeadingParagraphStyle(),
|
||||
fBulletStyle(),
|
||||
|
||||
fCurrentCharacterStyle(&fNormalStyle),
|
||||
fCurrentParagraphStyle(&fParagraphStyle)
|
||||
{
|
||||
_InitStyles();
|
||||
}
|
||||
|
||||
|
||||
TextDocumentRef
|
||||
MarkupParser::CreateDocumentFromMarkup(const BString& text)
|
||||
{
|
||||
fTextDocument.SetTo(new(std::nothrow) TextDocument(), true);
|
||||
if (fTextDocument.Get() == NULL)
|
||||
return fTextDocument;
|
||||
|
||||
fCurrentCharacterStyle = &fNormalStyle;
|
||||
fCurrentParagraphStyle = &fParagraphStyle;
|
||||
|
||||
fCurrentParagraph = Paragraph(*fCurrentParagraphStyle);
|
||||
fSpanStartOffset = 0;
|
||||
|
||||
_ParseText(text);
|
||||
|
||||
return fTextDocument;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
MarkupParser::_InitStyles()
|
||||
{
|
||||
fBoldStyle = fNormalStyle;
|
||||
fBoldStyle.SetBold(true);
|
||||
|
||||
fItalicStyle = fNormalStyle;
|
||||
fItalicStyle.SetItalic(true);
|
||||
|
||||
fBoldItalicStyle = fNormalStyle;
|
||||
fBoldItalicStyle.SetBold(true);
|
||||
fBoldItalicStyle.SetItalic(true);
|
||||
|
||||
float fontSize = fNormalStyle.Font().Size();
|
||||
|
||||
fHeadingStyle = fNormalStyle;
|
||||
fHeadingStyle.SetFontSize(ceilf(fontSize * 1.15f));
|
||||
fHeadingStyle.SetBold(true);
|
||||
|
||||
fHeadingParagraphStyle = fParagraphStyle;
|
||||
fHeadingParagraphStyle.SetSpacingTop(ceilf(fontSize * 0.8f));
|
||||
fHeadingParagraphStyle.SetSpacingBottom(ceilf(fontSize * 0.5f));
|
||||
fHeadingParagraphStyle.SetJustify(false);
|
||||
|
||||
fBulletStyle = fParagraphStyle;
|
||||
fBulletStyle.SetBullet(Bullet("•", fontSize));
|
||||
fBulletStyle.SetLineInset(ceilf(fontSize * 0.8f));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MarkupParser::_ParseText(const BString& text)
|
||||
{
|
||||
int32 start = 0;
|
||||
int32 offset = 0;
|
||||
|
||||
int32 charCount = text.CountChars();
|
||||
const char* c = text.String();
|
||||
|
||||
while (offset < charCount) {
|
||||
uint32 nextChar = UTF8ToCharCode(&c);
|
||||
|
||||
switch (nextChar) {
|
||||
case '\n':
|
||||
case '\0':
|
||||
_CopySpan(text, start, offset - 1);
|
||||
_FinishParagraph();
|
||||
start = offset + 1;
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
if (offset + 2 < charCount && c[0] == '\'') {
|
||||
int32 tickCount = 2;
|
||||
if (c[1] == '\'')
|
||||
tickCount = 3;
|
||||
|
||||
// Copy previous span using current style, excluding the
|
||||
// ticks.
|
||||
_CopySpan(text, start, offset);
|
||||
|
||||
if (tickCount == 2)
|
||||
_ToggleStyle(fItalicStyle);
|
||||
else if (tickCount == 3)
|
||||
_ToggleStyle(fBoldStyle);
|
||||
|
||||
// Don't include the ticks in the next span.
|
||||
offset += tickCount - 1;
|
||||
start = offset + 1;
|
||||
c += tickCount - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
// Detect headings
|
||||
if (offset == start
|
||||
&& fCurrentParagraph.IsEmpty()
|
||||
&& offset + 2 < charCount
|
||||
&& c[0] == '=' && c[1] == ' ') {
|
||||
|
||||
fCurrentParagraph.SetStyle(fHeadingParagraphStyle);
|
||||
fCurrentCharacterStyle = &fHeadingStyle;
|
||||
|
||||
offset += 2;
|
||||
c += 2;
|
||||
|
||||
start = offset + 1;
|
||||
} else if (offset > start
|
||||
&& offset + 2 < charCount
|
||||
&& c[0] == '=' && c[1] == '\n') {
|
||||
|
||||
_CopySpan(text, start, offset - 1);
|
||||
_FinishParagraph();
|
||||
|
||||
offset += 2;
|
||||
c += 2;
|
||||
|
||||
start = offset + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
// Detect bullets at line starts
|
||||
if (offset == start
|
||||
&& fCurrentParagraph.IsEmpty()
|
||||
&& offset + 2 < charCount
|
||||
&& c[0] == '*' && c[1] == ' ') {
|
||||
|
||||
fCurrentParagraph.SetStyle(fBulletStyle);
|
||||
|
||||
offset += 2;
|
||||
c += 2;
|
||||
|
||||
start = offset + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MarkupParser::_CopySpan(const BString& text, int32& start, int32 end)
|
||||
{
|
||||
if (start >= end)
|
||||
return;
|
||||
|
||||
BString subString;
|
||||
text.CopyCharsInto(subString, start, end - start);
|
||||
fCurrentParagraph.Append(TextSpan(subString,
|
||||
*fCurrentCharacterStyle));
|
||||
|
||||
start = end;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MarkupParser::_ToggleStyle(const CharacterStyle& style)
|
||||
{
|
||||
if (fCurrentCharacterStyle == &style)
|
||||
fCurrentCharacterStyle = &fNormalStyle;
|
||||
else
|
||||
fCurrentCharacterStyle = &style;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MarkupParser::_FinishParagraph()
|
||||
{
|
||||
fTextDocument->Append(fCurrentParagraph);
|
||||
fCurrentParagraph.Clear();
|
||||
fCurrentParagraph.SetStyle(fParagraphStyle);
|
||||
fCurrentCharacterStyle = &fNormalStyle;
|
||||
}
|
50
src/apps/haiku-depot/textview/MarkupParser.h
Normal file
50
src/apps/haiku-depot/textview/MarkupParser.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MARKUP_PARSER_H
|
||||
#define MARKUP_PARSER_H
|
||||
|
||||
#include "TextDocument.h"
|
||||
|
||||
|
||||
class MarkupParser {
|
||||
public:
|
||||
MarkupParser();
|
||||
MarkupParser(
|
||||
const CharacterStyle& characterStyle,
|
||||
const ParagraphStyle& paragraphStyle);
|
||||
|
||||
TextDocumentRef CreateDocumentFromMarkup(const BString& text);
|
||||
|
||||
private:
|
||||
void _InitStyles();
|
||||
|
||||
void _ParseText(const BString& text);
|
||||
void _CopySpan(const BString& text,
|
||||
int32& start, int32 end);
|
||||
void _ToggleStyle(const CharacterStyle& style);
|
||||
void _FinishParagraph();
|
||||
|
||||
private:
|
||||
CharacterStyle fNormalStyle;
|
||||
CharacterStyle fBoldStyle;
|
||||
CharacterStyle fItalicStyle;
|
||||
CharacterStyle fBoldItalicStyle;
|
||||
CharacterStyle fHeadingStyle;
|
||||
|
||||
ParagraphStyle fParagraphStyle;
|
||||
ParagraphStyle fHeadingParagraphStyle;
|
||||
ParagraphStyle fBulletStyle;
|
||||
|
||||
const CharacterStyle* fCurrentCharacterStyle;
|
||||
const ParagraphStyle* fCurrentParagraphStyle;
|
||||
|
||||
// while parsing:
|
||||
TextDocumentRef fTextDocument;
|
||||
Paragraph fCurrentParagraph;
|
||||
int32 fSpanStartOffset;
|
||||
};
|
||||
|
||||
|
||||
#endif // MARKUP_PARSER_H
|
@ -5,11 +5,13 @@
|
||||
|
||||
#include "TextDocumentTest.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <LayoutBuilder.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "MarkupParser.h"
|
||||
#include "TextDocumentView.h"
|
||||
|
||||
TextDocumentTest::TextDocumentTest()
|
||||
@ -38,64 +40,80 @@ TextDocumentTest::ReadyToRun()
|
||||
.Add(documentView)
|
||||
;
|
||||
|
||||
ParagraphStyle paragraphStyle;
|
||||
paragraphStyle.SetJustify(true);
|
||||
|
||||
CharacterStyle regularStyle;
|
||||
|
||||
CharacterStyle boldStyle(regularStyle);
|
||||
boldStyle.SetBold(true);
|
||||
|
||||
CharacterStyle italicStyle(regularStyle);
|
||||
italicStyle.SetItalic(true);
|
||||
|
||||
CharacterStyle italicAndBoldStyle(boldStyle);
|
||||
italicAndBoldStyle.SetItalic(true);
|
||||
float fontSize = regularStyle.Font().Size();
|
||||
|
||||
CharacterStyle bigStyle(regularStyle);
|
||||
bigStyle.SetFontSize(24);
|
||||
bigStyle.SetForegroundColor(255, 50, 50);
|
||||
|
||||
TextDocumentRef document(new TextDocument(), true);
|
||||
|
||||
Paragraph paragraph(paragraphStyle);
|
||||
paragraph.Append(TextSpan("This is a", regularStyle));
|
||||
paragraph.Append(TextSpan(" test ", bigStyle));
|
||||
paragraph.Append(TextSpan("to see if ", regularStyle));
|
||||
paragraph.Append(TextSpan("different", boldStyle));
|
||||
paragraph.Append(TextSpan(" character styles already work.", regularStyle));
|
||||
document->Append(paragraph);
|
||||
|
||||
paragraphStyle.SetSpacingTop(8.0f);
|
||||
paragraphStyle.SetAlignment(ALIGN_CENTER);
|
||||
paragraphStyle.SetJustify(false);
|
||||
|
||||
paragraph = Paragraph(paragraphStyle);
|
||||
paragraph.Append(TextSpan("Different alignment styles ", regularStyle));
|
||||
paragraph.Append(TextSpan("are", boldStyle));
|
||||
paragraph.Append(TextSpan(" supported as of now!", regularStyle));
|
||||
document->Append(paragraph);
|
||||
|
||||
// Test a bullet list
|
||||
paragraphStyle.SetSpacingTop(8.0f);
|
||||
paragraphStyle.SetAlignment(ALIGN_LEFT);
|
||||
ParagraphStyle paragraphStyle;
|
||||
paragraphStyle.SetJustify(true);
|
||||
paragraphStyle.SetBullet(Bullet("•", 12.0f));
|
||||
paragraphStyle.SetLineInset(10.0f);
|
||||
|
||||
paragraph = Paragraph(paragraphStyle);
|
||||
paragraph.Append(TextSpan("Even bullet lists are supported.", regularStyle));
|
||||
document->Append(paragraph);
|
||||
|
||||
paragraph = Paragraph(paragraphStyle);
|
||||
paragraph.Append(TextSpan("The wrapping in ", regularStyle));
|
||||
paragraph.Append(TextSpan("this", italicStyle));
|
||||
paragraphStyle.SetSpacingTop(ceilf(fontSize * 0.6f));
|
||||
paragraphStyle.SetLineSpacing(ceilf(fontSize * 0.2f));
|
||||
|
||||
paragraph.Append(TextSpan(" bullet item should look visually "
|
||||
"pleasing. And ", regularStyle));
|
||||
paragraph.Append(TextSpan("why", italicAndBoldStyle));
|
||||
paragraph.Append(TextSpan(" should it not?", regularStyle));
|
||||
document->Append(paragraph);
|
||||
// CharacterStyle boldStyle(regularStyle);
|
||||
// boldStyle.SetBold(true);
|
||||
//
|
||||
// CharacterStyle italicStyle(regularStyle);
|
||||
// italicStyle.SetItalic(true);
|
||||
//
|
||||
// CharacterStyle italicAndBoldStyle(boldStyle);
|
||||
// italicAndBoldStyle.SetItalic(true);
|
||||
//
|
||||
// CharacterStyle bigStyle(regularStyle);
|
||||
// bigStyle.SetFontSize(24);
|
||||
// bigStyle.SetForegroundColor(255, 50, 50);
|
||||
//
|
||||
// TextDocumentRef document(new TextDocument(), true);
|
||||
//
|
||||
// Paragraph paragraph(paragraphStyle);
|
||||
// paragraph.Append(TextSpan("This is a", regularStyle));
|
||||
// paragraph.Append(TextSpan(" test ", bigStyle));
|
||||
// paragraph.Append(TextSpan("to see if ", regularStyle));
|
||||
// paragraph.Append(TextSpan("different", boldStyle));
|
||||
// paragraph.Append(TextSpan(" character styles already work.", regularStyle));
|
||||
// document->Append(paragraph);
|
||||
//
|
||||
// paragraphStyle.SetSpacingTop(8.0f);
|
||||
// paragraphStyle.SetAlignment(ALIGN_CENTER);
|
||||
// paragraphStyle.SetJustify(false);
|
||||
//
|
||||
// paragraph = Paragraph(paragraphStyle);
|
||||
// paragraph.Append(TextSpan("Different alignment styles ", regularStyle));
|
||||
// paragraph.Append(TextSpan("are", boldStyle));
|
||||
// paragraph.Append(TextSpan(" supported as of now!", regularStyle));
|
||||
// document->Append(paragraph);
|
||||
//
|
||||
// // Test a bullet list
|
||||
// paragraphStyle.SetSpacingTop(8.0f);
|
||||
// paragraphStyle.SetAlignment(ALIGN_LEFT);
|
||||
// paragraphStyle.SetJustify(true);
|
||||
// paragraphStyle.SetBullet(Bullet("•", 12.0f));
|
||||
// paragraphStyle.SetLineInset(10.0f);
|
||||
//
|
||||
// paragraph = Paragraph(paragraphStyle);
|
||||
// paragraph.Append(TextSpan("Even bullet lists are supported.", regularStyle));
|
||||
// document->Append(paragraph);
|
||||
//
|
||||
// paragraph = Paragraph(paragraphStyle);
|
||||
// paragraph.Append(TextSpan("The wrapping in ", regularStyle));
|
||||
// paragraph.Append(TextSpan("this", italicStyle));
|
||||
//
|
||||
// paragraph.Append(TextSpan(" bullet item should look visually "
|
||||
// "pleasing. And ", regularStyle));
|
||||
// paragraph.Append(TextSpan("why", italicAndBoldStyle));
|
||||
// paragraph.Append(TextSpan(" should it not?", regularStyle));
|
||||
// document->Append(paragraph);
|
||||
|
||||
MarkupParser parser(regularStyle, paragraphStyle);
|
||||
|
||||
TextDocumentRef document = parser.CreateDocumentFromMarkup(
|
||||
"== Text document test ==\n"
|
||||
"This is a test to see if '''different''' "
|
||||
"character styles already work.\n"
|
||||
"Different alignment styles '''are''' supported as of now!\n"
|
||||
" * Even bullet lists are supported.\n"
|
||||
" * The wrapping in ''this'' bullet item should look visually "
|
||||
"pleasing. And ''why'' should it not?\n"
|
||||
);
|
||||
|
||||
documentView->SetTextDocument(document);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user