File: tag-processor.hpp

package info (click to toggle)
libzeep 5.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 3,596 kB
  • sloc: cpp: 27,393; xml: 7,798; javascript: 180; sh: 37; makefile: 8
file content (174 lines) | stat: -rw-r--r-- 9,358 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//          Copyright Maarten L. Hekkelman, 2019
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#pragma once

/// \file
/// definition of the zeep::http::tag_processor classes. These classes take care of processing HTML templates

#include <zeep/config.hpp>

#include <filesystem>

#include <zeep/xml/document.hpp>
#include <zeep/http/el-processing.hpp>

namespace zeep::http
{

class html_controller;
class basic_template_processor;

// --------------------------------------------------------------------
//

/// \brief Abstract base class for tag_processor. 
///
/// Note that this class should be light in construction, we create it every time a page is rendered.

class tag_processor
{
  public:
	tag_processor(const tag_processor&) = delete;
	tag_processor& operator=(const tag_processor&) = delete;

	virtual ~tag_processor() = default;

	/// \brief process xml parses the XHTML and fills in the special tags and evaluates the el constructs
	///
	/// This function is called to modify the xml tree in \a node
	///
	/// \param node		The XML zeep::xml::node (element) to manipulate
	/// \param scope	The zeep::http::scope containing the variables and request
	/// \param dir		The path to the docroot, the directory containing the XHTML templates
	/// \param webapp	The instance of webapp that called this function
	virtual void process_xml(xml::node* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader) = 0;

  protected:

	/// \brief constructor
	///
	/// \param ns	Then XML namespace for the tags and attributes that are processed by this tag_processor 
	tag_processor(const char* ns)
		: m_ns(ns) {}

	std::string	m_ns;
};

// --------------------------------------------------------------------

/// \brief A tag_processor compatible with the old version of libzeep. Works
/// on tags only, not on attributes. Also parses any occurrence of ${}.
/// For newer code, please consider using the v2 version only.

class tag_processor_v1 : public tag_processor
{
  public:
	/// \brief default namespace for this processor
	static constexpr const char* ns() { return "http://www.hekkelman.com/libzeep/m1"; }

	/// \brief constructor
	///
	/// By default the namespace for the v1 processor is the one in ns()
	tag_processor_v1(const char* ns = tag_processor_v1::ns());

	/// \brief actual implementation of the tag processing.
	virtual void process_xml(xml::node* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);

  protected:

	virtual void process_tag(const std::string& tag, xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);

  private:

	/// handler for mrs:include tags
	void process_include(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_if(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_iterate(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_for(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_number(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_options(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_option(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_checkbox(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_url(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_param(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_embed(xml::element* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);

	bool process_el(const scope& scope, std::string& s);
};

// --------------------------------------------------------------------

/// \brief version two of the tag_processor in libzeep
///
/// This is the new tag_processor. It is designed to look a bit like
/// Thymeleaf (https://www.thymeleaf.org/)
/// This processor works on attributes mostly, but can process inline
/// el constructs as well.
///
/// The documentention contains a section describing all the
/// xml tags and attributes this processor handles.

class tag_processor_v2 : public tag_processor
{
  public:
	/// \brief default namespace for this processor
	static constexpr const char* ns() { return "http://www.hekkelman.com/libzeep/m2"; }

	/// \brief each handler returns a code telling the processor what to do with the node
	enum class AttributeAction
	{
		none, remove, replace
	};

	using attr_handler = std::function<AttributeAction(xml::element*, xml::attribute*, scope&, std::filesystem::path, basic_template_processor& loader)>;

	/// \brief constructor with default namespace
	tag_processor_v2(const char* ns = tag_processor_v2::ns());

	/// \brief process xml parses the XHTML and fills in the special tags and evaluates the el constructs
	virtual void process_xml(xml::node* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);

	/// \brief It is possible to extend this processor with custom handlers
	void register_attr_handler(const std::string& attr, attr_handler&& handler)
	{
		m_attr_handlers.emplace(attr, std::forward<attr_handler>(handler));
	}

  protected:

	void process_node(xml::node* node, const scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	void process_text(xml::text& t, const scope& scope);
	void post_process(xml::element* e, const scope& parentScope, std::filesystem::path dir, basic_template_processor& loader);

	// std::vector<std::unique_ptr<xml::node>> resolve_fragment_spec(xml::element* node, std::filesystem::path dir, basic_html_controller& controller, const std::string& spec, const scope& scope);
	std::vector<std::unique_ptr<xml::node>> resolve_fragment_spec(xml::element* node, std::filesystem::path dir, basic_template_processor& loader, const json::element& spec, const scope& scope);
	std::vector<std::unique_ptr<xml::node>> resolve_fragment_spec(xml::element* node, std::filesystem::path dir, basic_template_processor& loader, const std::string& file, const std::string& selector, bool byID);

	// virtual void process_node_attr(xml::node* node, const scope& scope, std::filesystem::path dir);
	AttributeAction process_attr_if(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader, bool unless);
	AttributeAction process_attr_assert(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_text(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader, bool escaped);
	AttributeAction process_attr_switch(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_each(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_attr(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_with(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_generic(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_boolean_value(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_inline(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_append(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader, std::string dest, bool prepend);
	AttributeAction process_attr_classappend(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_styleappend(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);
	AttributeAction process_attr_remove(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader);

	enum class TemplateIncludeAction { include, insert, replace };

	AttributeAction process_attr_include(xml::element* node, xml::attribute* attr, scope& scope, std::filesystem::path dir, basic_template_processor& loader, TemplateIncludeAction tia);

	std::map<std::string, attr_handler> m_attr_handlers;
	xml::document m_template;	// copy of the entire document...
};

}