Merge branch 'develop' into ryzomclassic-develop
commit
28fd4d9011
@ -0,0 +1,74 @@
|
||||
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
#ifndef XML_MACROS_H
|
||||
#define XML_MACROS_H
|
||||
|
||||
//
|
||||
// xmlNodePtr cur;
|
||||
// CXMLAutoPtr prop;
|
||||
//
|
||||
// sint i;
|
||||
// XML_READ_SINT(cur, "prop_name", i, -1);
|
||||
//
|
||||
|
||||
#define XML_READ_UINT(node, name, var, def) { \
|
||||
uint tmp; \
|
||||
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
|
||||
if (prop && fromString((const char*)prop, tmp)) \
|
||||
var = tmp; \
|
||||
else \
|
||||
var = def; \
|
||||
}
|
||||
|
||||
#define XML_READ_SINT(node, name, var, def) { \
|
||||
sint tmp; \
|
||||
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
|
||||
if (prop && fromString((const char*)prop, tmp)) \
|
||||
var = tmp; \
|
||||
else \
|
||||
var = def; \
|
||||
}
|
||||
|
||||
#define XML_READ_BOOL(node, name, var, def) { \
|
||||
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
|
||||
if (prop) \
|
||||
var = NLMISC::toBool((const char*)prop); \
|
||||
else \
|
||||
var = def; \
|
||||
}
|
||||
|
||||
#define XML_READ_COLOR(node, name, var, def) { \
|
||||
NLMISC::CRGBA tmp; \
|
||||
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
|
||||
if (prop && fromString((const char*)prop, tmp)) \
|
||||
var = tmp; \
|
||||
else \
|
||||
var = def; \
|
||||
}
|
||||
|
||||
#define XML_READ_STRING(node, name, var, def) { \
|
||||
prop = (char *) xmlGetProp(node, (xmlChar*)name); \
|
||||
if (prop) \
|
||||
var = (const char*)prop; \
|
||||
else \
|
||||
var = def; \
|
||||
}
|
||||
|
||||
#endif // XML_MACROS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
|
||||
CMAKE_POLICY(SET CMP0015 NEW)
|
||||
|
||||
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${CMAKE_LIBRARY_DIR})
|
||||
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS})
|
||||
|
||||
FILE(GLOB SRC htmlcss_test.cpp)
|
||||
ADD_EXECUTABLE(htmlcss_test ${SRC})
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${LUA_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} )
|
||||
TARGET_LINK_LIBRARIES(htmlcss_test nelmisc nelgui ${LUA_LIBRARIES} ${LIBXML2_LIBRARIES})
|
||||
NL_DEFAULT_PROPS(htmlcss_test "Ryzom, Tests: html/css parser tests")
|
||||
NL_ADD_RUNTIME_FLAGS(htmlcss_test)
|
||||
|
||||
INSTALL(TARGETS htmlcss_test RUNTIME DESTINATION bin COMPONENT tools)
|
||||
# TODO: test fixtures
|
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* File: main.cpp
|
||||
* Author: Karu <nimetu@gmail.com>
|
||||
*
|
||||
* Created on 2015-04-11
|
||||
*/
|
||||
|
||||
typedef struct _xmlNode xmlNode;
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "nel/misc/types_nl.h"
|
||||
#include "nel/misc/file.h"
|
||||
#include "nel/misc/path.h"
|
||||
|
||||
#include "nel/gui/html_parser.h"
|
||||
#include "nel/gui/css_parser.h"
|
||||
#include "nel/gui/html_element.h"
|
||||
#include "nel/gui/css_style.h"
|
||||
|
||||
#include "nel/gui/libwww.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace NLMISC;
|
||||
using namespace NLGUI;
|
||||
|
||||
sint indent { 0 };
|
||||
|
||||
// ***************************************************************************
|
||||
void checkRuleset(CHtmlElement &elm, CCssStyle &style, TStyleVec testset, bool exists)
|
||||
{
|
||||
bool verbose = false;
|
||||
std::string existsMessage = exists ? "exist" : "unset";
|
||||
for (auto it : testset)
|
||||
{
|
||||
bool failed = (exists != style.hasStyle(it.first));
|
||||
if (failed)
|
||||
{
|
||||
bool failed2 = true;
|
||||
if (it.first == "font-size")
|
||||
{
|
||||
printf("[%s]: font-size: %d; expected '%s'\n", existsMessage.c_str(), style.Current.FontSize, it.second.c_str());
|
||||
printf(" (%s)\n", elm.toString().c_str());
|
||||
failed2 = false;
|
||||
}
|
||||
else if (it.first == "background-color")
|
||||
{
|
||||
printf("[%s]: background-color: '%s'; expected '%s'\n", existsMessage.c_str(), style.Current.BackgroundColor.toString().c_str(), it.second.c_str());
|
||||
printf(" (%s)\n", elm.toString().c_str());
|
||||
failed2 = false;
|
||||
}
|
||||
|
||||
if (failed2)
|
||||
{
|
||||
printf("[%s] FAIL: '%s': '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str());
|
||||
printf(" (%s)\n", elm.toString().c_str());
|
||||
for (auto it2 : style.Current.StyleRules)
|
||||
printf("'%s': '%s'\n", it2.first.c_str(), it2.second.c_str());
|
||||
}
|
||||
}
|
||||
else if (exists && !style.checkStyle(it.first, it.second))
|
||||
{
|
||||
printf("[%s] FAIL: expecting '%s': '%s', got '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str(), style.getStyle(it.first).c_str());
|
||||
printf(" (%s)\n", elm.toString().c_str());
|
||||
}
|
||||
else if (!failed)
|
||||
{
|
||||
if (verbose)
|
||||
printf("[%s] PASS: '%s': '%s'\n", existsMessage.c_str(), it.first.c_str(), it.second.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void recursiveHtmlRender(CHtmlElement &elm, CCssStyle &style)
|
||||
{
|
||||
bool verbose = false;
|
||||
if (elm.Type == CHtmlElement::TEXT_NODE)
|
||||
{
|
||||
std::string val = trim(elm.Value);
|
||||
if (verbose)
|
||||
if (!val.empty())
|
||||
printf("[%d] '%s'\n", indent, val.c_str());
|
||||
}
|
||||
else if (elm.Type == CHtmlElement::ELEMENT_NODE)
|
||||
{
|
||||
style.pushStyle();
|
||||
|
||||
if (verbose)
|
||||
printf("========= '%s'\n", elm.toString().c_str());
|
||||
|
||||
style.getStyleFor(elm);
|
||||
style.applyStyle(elm.Style);
|
||||
if (elm.hasAttribute("data-ruleset"))
|
||||
{
|
||||
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleset"));
|
||||
checkRuleset(elm, style, testset, true);
|
||||
}
|
||||
|
||||
if (elm.hasAttribute("data-ruleunset"))
|
||||
{
|
||||
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleunset"));
|
||||
checkRuleset(elm, style, testset, false);
|
||||
}
|
||||
|
||||
if (elm.hasAttribute("data-ruleset-before"))
|
||||
{
|
||||
TStyleVec testset = CCssParser::parseDecls(elm.getAttribute("data-ruleset-before"));
|
||||
|
||||
}
|
||||
|
||||
for (auto it = elm.Children.begin(); it != elm.Children.end(); ++it)
|
||||
{
|
||||
recursiveHtmlRender(*it, style);
|
||||
}
|
||||
|
||||
style.popStyle();
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void runTestOnFile(const std::string &filename)
|
||||
{
|
||||
CHtmlElement dom;
|
||||
|
||||
CHtmlParser htmlParser;
|
||||
|
||||
std::vector<CHtmlParser::StyleLink> links;
|
||||
std::vector<std::string> styles;
|
||||
//, elm, styles, links
|
||||
|
||||
ifstream f(filename);
|
||||
if (!f.is_open())
|
||||
{
|
||||
printf("!! failed to open file '%s'\n", filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
printf(": %s\n", filename.c_str());
|
||||
std::string htmlString;
|
||||
std::string line;
|
||||
while (getline(f, line))
|
||||
htmlString += line;
|
||||
|
||||
htmlParser.getDOM(htmlString, dom, styles, links);
|
||||
|
||||
CCssStyle style;
|
||||
for (std::string s : styles)
|
||||
{
|
||||
if (!s.empty())
|
||||
style.parseStylesheet(s);
|
||||
}
|
||||
|
||||
for (auto it = dom.Children.begin(); it != dom.Children.end(); ++it)
|
||||
recursiveHtmlRender(*it, style);
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
CApplicationContext *appContext = new CApplicationContext;
|
||||
|
||||
// htmlcss_test file.html
|
||||
if (argc == 2)
|
||||
{
|
||||
runTestOnFile(argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
CPath::getPathContent("tests/", true /*recursive*/, false /*wantDir*/, true /*wantFile*/, result, NULL /*callback*/, true /*showEverything*/);
|
||||
printf(":: got %ld files\n", result.size());
|
||||
for (const auto &fname : result)
|
||||
{
|
||||
if (endsWith(fname, ".html") && fname != "tests/XX-template.html")
|
||||
runTestOnFile(fname);
|
||||
}
|
||||
}
|
||||
|
||||
printf(">>> all done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:lang(en) { --text: '(en)'; }
|
||||
:lang(de-DE) { --text: '(de-DE)'; }
|
||||
a { test: " (" var(--lang) ")"}
|
||||
|
||||
div {
|
||||
/* '--a' and '--b' are both 'initial' */
|
||||
--should-not-exist: var(--a, var(--b, ( "p() " ) ), { "b" [ "r" ] });
|
||||
/* 'before -var- after' */
|
||||
--concate-test: 'before' var(--exists) 'after';
|
||||
--exists: '-var-';
|
||||
/* fallback should be at least one char */
|
||||
--invalid-fallback: var(--exists,);
|
||||
/* using fallback */
|
||||
--fallback: var(--a, 'ok');
|
||||
}
|
||||
</style>
|
||||
<div data-ruleset="--concate-test: 'before' '-var-' 'after'; --exists: '-var-'; --fallback: 'ok';"
|
||||
data-ruleunset="--should-not-exists: 1; --invalid-fallback: 1;" />
|
||||
|
||||
<a lang="en" data-ruleset="--text: '(en)';">link</a>
|
||||
<a lang="de" data-ruleunset="--text: 1;">link</a>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
p {
|
||||
--mq-sm: initial;
|
||||
}
|
||||
|
||||
.small {
|
||||
--mq-sm: ;
|
||||
}
|
||||
|
||||
p {
|
||||
--padding-when-small: var(--mq-sm) 2rem;
|
||||
--padding-when-large: 4rem;
|
||||
padding: var(--padding-when-small, var(--padding-when-large));
|
||||
}
|
||||
</style>
|
||||
<p data-ruleset="padding-left: 4rem;" comment="--mq-sm==initial, should use fallback value" />
|
||||
<div>
|
||||
<p class="small" data-ruleset="padding-left: 2rem;" comment="--mq-sm==;, should use defined value"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:root {
|
||||
--main-color: #06c;
|
||||
--accent-color: #006;
|
||||
}
|
||||
/* The rest of the CSS file */
|
||||
#foo h1 {
|
||||
color: var(--main-color);
|
||||
}
|
||||
</style>
|
||||
<div id="foo">
|
||||
<h1 data-ruleset="color: #06c;">Header</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:root {
|
||||
--main-color: #06c;
|
||||
--accent-color: #006;
|
||||
--MAIN-COLOR: #f00;
|
||||
}
|
||||
/* The rest of the CSS file */
|
||||
#foo h1 {
|
||||
color: var(--main-color);
|
||||
}
|
||||
h2 {
|
||||
color: var(--MAIN-COLOR);
|
||||
}
|
||||
</style>
|
||||
<div id="foo">
|
||||
<h1 data-ruleset="color: #06c;">Header1</h1>
|
||||
<h2 data-ruleset="color: #f00;">Header2</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:root {
|
||||
--foo: if(x > 5) this.width = 10;
|
||||
}
|
||||
/* The rest of the CSS file */
|
||||
#foo h1 {
|
||||
test: var(--foo)
|
||||
}
|
||||
</style>
|
||||
<div id="foo">
|
||||
<h1 data-ruleset="test: if(x > 5) this.width = 10;">Header</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
a:lang(en) {--lang: 'en';}
|
||||
a:lang(de) {--lang: 'de';}
|
||||
a { test: var(--lang); }
|
||||
</style>
|
||||
|
||||
<a lang="en" data-ruleset="test: 'en';">link</a>
|
||||
|
||||
<a lang="de" data-ruleset="test: 'de';">link</a>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:root {
|
||||
--main-color: #c06;
|
||||
--accent-background: var(--main-color);
|
||||
}
|
||||
div {
|
||||
test: var(--accent-background);
|
||||
}
|
||||
</style>
|
||||
<div data-ruleset="test: #c06;"/>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
div {
|
||||
--one: calc(var(--two) + 20px);
|
||||
--two: calc(var(--one) - 20px);
|
||||
--ok: 'ok';
|
||||
}
|
||||
</style>
|
||||
<div data-ruleset="--ok: 'ok';"
|
||||
data-ruleunset="--one: 1; --two: 1;" />
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
one { --foo: 10px; }
|
||||
two { --bar: calc(var(--foo) + 10px); }
|
||||
three { --foo: calc(var(--bar) + 10px); }
|
||||
</style>
|
||||
<one data-ruleset="--foo: 10px;">
|
||||
<two data-ruleset="--bar: calc( 10px + 10px);">
|
||||
<three data-ruleset="--foo: calc( calc( 10px + 10px) + 10px);"/>
|
||||
</two>
|
||||
</one>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
div {
|
||||
--side: margin-top;
|
||||
var(--side): 20px;
|
||||
}
|
||||
</style>
|
||||
<div data-ruleset="--side: margin-top;" data-ruleunset="var(--side): 1;" />
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
div {
|
||||
--gap: 20;
|
||||
margin-top: var(--gap)px;
|
||||
}
|
||||
</style>
|
||||
<!-- should have whitespace, ie '20 px' -->
|
||||
<div data-ruleset="margin-top: 20 px;" />
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
:root { --not-a-color: 20px; }
|
||||
p { background-color: red; }
|
||||
p { background-color: var(--not-a-color); }
|
||||
</style>
|
||||
<!-- this should have 'red' because var() has invalid value for color -->
|
||||
<!-- TODO: not really supported by NEL currently -->
|
||||
<div data-ruleset="background-color: red;" />
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue