mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:08:12 +00:00
LibHTML: Start working on a simple HTML library.
I'd like to have rich text, and we might as well use HTML for that. :^)
This commit is contained in:
parent
01d1aee922
commit
a67e823838
19 changed files with 329 additions and 0 deletions
|
@ -83,6 +83,7 @@ cp ../Servers/LookupServer/LookupServer mnt/bin/LookupServer
|
|||
cp ../Servers/SystemServer/SystemServer mnt/bin/SystemServer
|
||||
cp ../Servers/WindowServer/WindowServer mnt/bin/WindowServer
|
||||
cp ../Shell/Shell mnt/bin/Shell
|
||||
cp ../LibHTML/tho mnt/bin/tho
|
||||
echo "done"
|
||||
|
||||
echo -n "installing shortcuts... "
|
||||
|
|
|
@ -17,6 +17,7 @@ build_targets="$build_targets ../Servers/SystemServer"
|
|||
build_targets="$build_targets ../Servers/LookupServer"
|
||||
build_targets="$build_targets ../Servers/WindowServer"
|
||||
build_targets="$build_targets ../LibGUI"
|
||||
build_targets="$build_targets ../LibHTML"
|
||||
build_targets="$build_targets ../Userland"
|
||||
build_targets="$build_targets ../Applications/Terminal"
|
||||
build_targets="$build_targets ../Applications/FontEditor"
|
||||
|
|
4
LibHTML/.gitignore
vendored
Normal file
4
LibHTML/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.o
|
||||
*.d
|
||||
libhtml.a
|
||||
tho
|
11
LibHTML/Document.cpp
Normal file
11
LibHTML/Document.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <LibHTML/Document.h>
|
||||
|
||||
Document::Document()
|
||||
: ParentNode(NodeType::DOCUMENT_NODE)
|
||||
{
|
||||
}
|
||||
|
||||
Document::~Document()
|
||||
{
|
||||
}
|
||||
|
13
LibHTML/Document.h
Normal file
13
LibHTML/Document.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/AKString.h>
|
||||
#include <LibHTML/ParentNode.h>
|
||||
|
||||
class Document : public ParentNode {
|
||||
public:
|
||||
Document();
|
||||
virtual ~Document() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
26
LibHTML/Dump.cpp
Normal file
26
LibHTML/Dump.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <LibHTML/Document.h>
|
||||
#include <LibHTML/Dump.h>
|
||||
#include <LibHTML/Element.h>
|
||||
#include <LibHTML/Text.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void dump_tree(Node& node)
|
||||
{
|
||||
static int indent = 0;
|
||||
for (int i = 0; i < indent; ++i)
|
||||
printf(" ");
|
||||
if (node.is_document()) {
|
||||
printf("*Document*\n");
|
||||
} else if (node.is_element()) {
|
||||
printf("<%s>\n", static_cast<Element&>(node).tag_name().characters());
|
||||
} else if (node.is_text()) {
|
||||
printf("\"%s\"\n", static_cast<Text&>(node).data().characters());
|
||||
}
|
||||
++indent;
|
||||
if (node.is_parent_node()) {
|
||||
static_cast<ParentNode&>(node).for_each_child([](Node& child) {
|
||||
dump_tree(child);
|
||||
});
|
||||
}
|
||||
--indent;
|
||||
}
|
5
LibHTML/Dump.h
Normal file
5
LibHTML/Dump.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
class Node;
|
||||
|
||||
void dump_tree(Node&);
|
12
LibHTML/Element.cpp
Normal file
12
LibHTML/Element.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <LibHTML/Element.h>
|
||||
|
||||
Element::Element(const String& tag_name)
|
||||
: ParentNode(NodeType::ELEMENT_NODE)
|
||||
, m_tag_name(tag_name)
|
||||
{
|
||||
}
|
||||
|
||||
Element::~Element()
|
||||
{
|
||||
}
|
||||
|
30
LibHTML/Element.h
Normal file
30
LibHTML/Element.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibHTML/ParentNode.h>
|
||||
#include <AK/AKString.h>
|
||||
|
||||
class Attribute {
|
||||
public:
|
||||
Attribute(const String& name, const String& value)
|
||||
: m_name(name)
|
||||
, m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
String m_name;
|
||||
String m_value;
|
||||
};
|
||||
|
||||
class Element : public ParentNode {
|
||||
public:
|
||||
explicit Element(const String& tag_name);
|
||||
virtual ~Element() override;
|
||||
|
||||
const String& tag_name() const { return m_tag_name; }
|
||||
|
||||
private:
|
||||
String m_tag_name;
|
||||
Vector<Attribute> m_attributes;
|
||||
};
|
||||
|
42
LibHTML/Makefile
Normal file
42
LibHTML/Makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
include ../Makefile.common
|
||||
|
||||
LIBHTML_OBJS = \
|
||||
Node.o \
|
||||
ParentNode.o \
|
||||
Element.o \
|
||||
Document.o \
|
||||
Text.o \
|
||||
Parser.o \
|
||||
Dump.o
|
||||
|
||||
TEST_OBJS = test.o
|
||||
TEST_PROGRAM = tho
|
||||
|
||||
OBJS = $(LIBHTML_OBJS) $(TEST_OBJS)
|
||||
|
||||
LIBRARY = libhtml.a
|
||||
DEFINES += -DUSERLAND
|
||||
|
||||
all: $(LIBRARY) $(TEST_PROGRAM)
|
||||
|
||||
$(TEST_PROGRAM): $(TEST_OBJS) $(LIBRARY)
|
||||
$(LD) -o $@ $(LDFLAGS) -L. $(TEST_OBJS) -lhtml -lgui -lcore -lc
|
||||
|
||||
$(LIBRARY): $(LIBHTML_OBJS)
|
||||
@echo "LIB $@"; $(AR) rcs $@ $(LIBHTML_OBJS)
|
||||
|
||||
.cpp.o:
|
||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
-include $(OBJS:%.o=%.d)
|
||||
|
||||
clean:
|
||||
@echo "CLEAN"; rm -f $(TEST_PROGRAM) $(LIBRARY) $(OBJS) *.d
|
||||
|
||||
install: $(LIBRARY)
|
||||
mkdir -p ../Root/usr/include/LibHTML
|
||||
# Copy headers
|
||||
rsync -r -a --include '*/' --include '*.h' --exclude '*' . ../Root/usr/include/LibHTML
|
||||
# Install the library
|
||||
cp $(LIBRARY) ../Root/usr/lib
|
||||
|
24
LibHTML/Node.cpp
Normal file
24
LibHTML/Node.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include <AK/Retained.h>
|
||||
#include <LibHTML/Node.h>
|
||||
|
||||
Node::Node(NodeType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
{
|
||||
}
|
||||
|
||||
void Node::retain()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
++m_retain_count;
|
||||
}
|
||||
|
||||
void Node::release()
|
||||
{
|
||||
ASSERT(m_retain_count);
|
||||
if (!--m_retain_count)
|
||||
delete this;
|
||||
}
|
41
LibHTML/Node.h
Normal file
41
LibHTML/Node.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Retained.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
enum class NodeType : unsigned {
|
||||
INVALID = 0,
|
||||
ELEMENT_NODE = 1,
|
||||
TEXT_NODE = 3,
|
||||
DOCUMENT_NODE = 9,
|
||||
};
|
||||
|
||||
class Node {
|
||||
public:
|
||||
virtual ~Node();
|
||||
|
||||
void retain();
|
||||
void release();
|
||||
int retain_count() const { return m_retain_count; }
|
||||
|
||||
NodeType type() const { return m_type; }
|
||||
bool is_element() const { return type() == NodeType::ELEMENT_NODE; }
|
||||
bool is_text() const { return type() == NodeType::TEXT_NODE; }
|
||||
bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
|
||||
bool is_parent_node() const { return is_element() || is_document(); }
|
||||
|
||||
Node* next_sibling() { return m_next_sibling; }
|
||||
Node* previous_sibling() { return m_previous_sibling; }
|
||||
void set_next_sibling(Node* node) { m_next_sibling = node; }
|
||||
void set_previous_sibling(Node* node) { m_previous_sibling = node; }
|
||||
|
||||
protected:
|
||||
explicit Node(NodeType);
|
||||
|
||||
int m_retain_count { 1 };
|
||||
NodeType m_type { NodeType::INVALID };
|
||||
Vector<Node*> m_children;
|
||||
Node* m_next_sibling { nullptr };
|
||||
Node* m_previous_sibling { nullptr };
|
||||
};
|
||||
|
10
LibHTML/ParentNode.cpp
Normal file
10
LibHTML/ParentNode.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <LibHTML/ParentNode.h>
|
||||
|
||||
void ParentNode::append_child(Retained<Node> node)
|
||||
{
|
||||
if (m_last_child)
|
||||
m_last_child->set_next_sibling(node.ptr());
|
||||
m_last_child = &node.leak_ref();
|
||||
if (!m_first_child)
|
||||
m_first_child = m_last_child;
|
||||
}
|
32
LibHTML/ParentNode.h
Normal file
32
LibHTML/ParentNode.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibHTML/Node.h>
|
||||
|
||||
class ParentNode : public Node {
|
||||
public:
|
||||
void append_child(Retained<Node>);
|
||||
|
||||
Node* first_child() { return m_first_child; }
|
||||
Node* last_child() { return m_last_child; }
|
||||
|
||||
template<typename F> void for_each_child(F);
|
||||
|
||||
protected:
|
||||
explicit ParentNode(NodeType type)
|
||||
: Node(type)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Node* m_first_child { nullptr };
|
||||
Node* m_last_child { nullptr };
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
inline void ParentNode::for_each_child(F func)
|
||||
{
|
||||
for (auto* node = first_child(); node; node = node->next_sibling()) {
|
||||
func(*node);
|
||||
}
|
||||
}
|
||||
|
32
LibHTML/Parser.cpp
Normal file
32
LibHTML/Parser.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <LibHTML/Element.h>
|
||||
#include <LibHTML/Parser.h>
|
||||
#include <LibHTML/Text.h>
|
||||
|
||||
static Retained<Element> create_element(const String& tag_name)
|
||||
{
|
||||
return adopt(*new Element(tag_name));
|
||||
}
|
||||
|
||||
Retained<Document> parse(const String& html)
|
||||
{
|
||||
auto doc = adopt(*new Document);
|
||||
|
||||
auto head = create_element("head");
|
||||
auto title = create_element("title");
|
||||
auto title_text = adopt(*new Text("Page Title"));
|
||||
title->append_child(title_text);
|
||||
head->append_child(title);
|
||||
|
||||
doc->append_child(head);
|
||||
|
||||
auto body = create_element("body");
|
||||
auto h1 = create_element("h1");
|
||||
auto h1_text = adopt(*new Text("Hello World!"));
|
||||
|
||||
h1->append_child(h1_text);
|
||||
body->append_child(h1);
|
||||
doc->append_child(body);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
7
LibHTML/Parser.h
Normal file
7
LibHTML/Parser.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Retained.h>
|
||||
#include <LibHTML/Document.h>
|
||||
|
||||
Retained<Document> parse(const String& html);
|
||||
|
13
LibHTML/Text.cpp
Normal file
13
LibHTML/Text.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <LibHTML/Text.h>
|
||||
|
||||
Text::Text(const String& data)
|
||||
: Node(NodeType::TEXT_NODE)
|
||||
, m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
}
|
||||
|
||||
|
15
LibHTML/Text.h
Normal file
15
LibHTML/Text.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/AKString.h>
|
||||
#include <LibHTML/Node.h>
|
||||
|
||||
class Text final : public Node {
|
||||
public:
|
||||
explicit Text(const String&);
|
||||
virtual ~Text() override;
|
||||
|
||||
const String& data() const { return m_data; }
|
||||
|
||||
private:
|
||||
String m_data;
|
||||
};
|
10
LibHTML/test.cpp
Normal file
10
LibHTML/test.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <LibHTML/Dump.h>
|
||||
#include <LibHTML/Element.h>
|
||||
#include <LibHTML/Parser.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
String html = "<html><head><title>my page</title></head><body><h1>Hi there</h1><p>Hello World!</p></body></html>";
|
||||
auto doc = parse(html);
|
||||
dump_tree(doc);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue