mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
WIP eTemplate2.0 DTD
This commit is contained in:
parent
c04cf276b7
commit
d1b3786b2a
125
doc/etemplate2-rng.php
Normal file → Executable file
125
doc/etemplate2-rng.php
Normal file → Executable file
@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* eTemplate2 XML schema
|
||||
@ -31,9 +32,10 @@ if (!file_exists(($file = __DIR__."/etemplate2/etemplate2.rng")))
|
||||
die("Missing file '$file', you need to generate it from 'etemplate2.dtd' e.g. with PHPStorm!");
|
||||
}
|
||||
$grammar = new SimpleXMLElement(file_get_contents($file));
|
||||
$widgets = getByName($grammar, 'Widgets');
|
||||
$widgets_choice = getByName($grammar, 'Widgets')->choice;
|
||||
/**
|
||||
* Manually overwriting problems / errors in what we automatically generate
|
||||
* Use class-name (e.g. Et2Button) so all descends inherit the fix, use-tag to fix only specific widget.
|
||||
* @todo fix in TS sources
|
||||
*/
|
||||
$overwrites = [
|
||||
@ -44,7 +46,9 @@ $overwrites = [
|
||||
'id' => 'string', // commented out with some reasoning in Et2Widget
|
||||
//'data' => null, // ToDo: not sure, but AFAIK this is no attribute, but somehow listed in each widget
|
||||
'width' => 'string',
|
||||
'height' => 'string',
|
||||
'span' => 'string', // actually int|"all"
|
||||
'slot' => 'string',
|
||||
],
|
||||
],
|
||||
'Et2InputWidget' => [
|
||||
@ -109,7 +113,34 @@ $overwrites = [
|
||||
'et2-split' => [
|
||||
'.children' => 'Widgets',
|
||||
],
|
||||
'et2-select-*' => 'et2-select', // seems like et2-select-* widgets are NOT parsed
|
||||
'et2-url-email' => [
|
||||
'.attrs' => [
|
||||
'emailDisplay' => 'string', // can't see that anywhere in the code, but in addressbook.index.xet
|
||||
],
|
||||
],
|
||||
'et2-nextmatch-header-custom' => [
|
||||
'.attrs' => [
|
||||
'emptyLabel' => 'string',
|
||||
],
|
||||
],
|
||||
'Et2Button' => [
|
||||
'.attrs' => [
|
||||
'image' => 'string',
|
||||
'noSubmit' => 'boolean',
|
||||
],
|
||||
],
|
||||
'Et2Select' => [
|
||||
'.attrs' => [
|
||||
'rows' => 'int',
|
||||
'tabindex' => 'int',
|
||||
'allowFreeEntries' => 'boolean',
|
||||
],
|
||||
],
|
||||
'et2-email' => [
|
||||
'.attrs' => [
|
||||
'onTagClick' => 'function',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
@ -118,13 +149,75 @@ $overwrites = [
|
||||
// make overlay the only allowed start element
|
||||
removeNode($grammar->start->choice);
|
||||
$grammar->start->addChild('ref')->addAttribute('name', 'overlay');
|
||||
// overlay can only container template, not all widgets
|
||||
getByName($grammar, 'overlay')->element->zeroOrMore->ref->attributes()['name'] = 'template';
|
||||
getByName($grammar, 'attlist.vfs-upload')->addChild('optional')
|
||||
->addChild('attribute')->addAttribute('name', 'callback');
|
||||
// add statustext to tab
|
||||
getByName($grammar, 'attlist.tab')->addChild('optional')
|
||||
->addChild('attribute')->addAttribute('name', 'statustext');
|
||||
// fix legacy widgets: attribute-name => (array of) widgets
|
||||
$missing_legacy_attributes = [
|
||||
'callback' => 'vfs-upload',
|
||||
'statustext' => 'tab',
|
||||
'minWidth' => 'column',
|
||||
'maxWidth' => 'column',
|
||||
'id' => [
|
||||
'.optional' => false,
|
||||
'nextmatch-header', 'nextmatch-sortheader', 'nextmatch-customfields', 'nextmatch',
|
||||
],
|
||||
'template' => ['.optional' => false, 'nextmatch'],
|
||||
'header_left' => 'nextmatch',
|
||||
'header_row' => 'nextmatch',
|
||||
'header_right' => 'nextmatch',
|
||||
'disabled' => 'nextmatch',
|
||||
'onselect' => 'nextmatch',
|
||||
'span' => ['nextmatch', 'nextmatch-header', 'nextmatch-customfields', 'nextmatch-sortheader'],
|
||||
'class' => ['nextmatch','nextmatch-header', 'nextmatch-customfields', 'nextmatch-sortheader'],
|
||||
'label' => [
|
||||
'.optional' => false,
|
||||
'nextmatch-header', 'nextmatch-sortheader',
|
||||
],
|
||||
'sortmode' => [
|
||||
'.values' => ['ASC', 'DESC'],
|
||||
'.default' => 'ASC',
|
||||
'nextmatch-sortheader',
|
||||
],
|
||||
];
|
||||
foreach($missing_legacy_attributes as $attribute => $widgets)
|
||||
{
|
||||
foreach((array)$widgets as $key => $widget)
|
||||
{
|
||||
if (!is_int($key)) continue; // .(values|default)
|
||||
// widget not found add it plus it's attribute-list
|
||||
if (!getByName($grammar, $widget))
|
||||
{
|
||||
$widgets_choice->addChild('ref')->addAttribute('name', $widget);
|
||||
($define = $grammar->addChild('define'))->addAttribute('name', $widget);
|
||||
($element = $define->addChild('element'))->addAttribute('name', $widget);
|
||||
$element->addChild('ref')->addAttribute('name', 'attlist.'.$widget);
|
||||
$element->addChild('empty'); // no children allowed
|
||||
$grammar->addChild('define')->addAttribute('name', 'attlist.'.$widget);
|
||||
}
|
||||
// add (optional) attribute
|
||||
if (!is_array($widgets) || (!isset($widgets['.optional']) || $widgets['.optional'] === true))
|
||||
{
|
||||
$attr = getByName($grammar, 'attlist.'.$widget)->addChild('optional')
|
||||
->addChild('attribute');
|
||||
}
|
||||
else
|
||||
{
|
||||
$attr = getByName($grammar, 'attlist.'.$widget)->addChild('attribute');
|
||||
}
|
||||
$attr->addAttribute('name', $attribute);
|
||||
// add values and/or default
|
||||
if (is_array($widgets) && isset($widgets['.values']))
|
||||
{
|
||||
$choice = $attr->addChild('choice');
|
||||
foreach($widgets['.values'] as $value)
|
||||
{
|
||||
$choice->addChild('value', $value);
|
||||
}
|
||||
}
|
||||
if (is_array($widgets) && isset($widgets['.default']))
|
||||
{
|
||||
$attr->addAttribute('a:defaultValue', $widgets['.default'], 'http://relaxng.org/ns/compatibility/annotations/1.0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build a hashed version of all classes, members and attributes to e.g. find ancestors
|
||||
$classes = [];
|
||||
@ -175,7 +268,7 @@ foreach($data['modules'] as $module)
|
||||
$attrs = $element->addChild('ref');
|
||||
$attrs->addAttribute('name', 'attlist.'.$export['name']);
|
||||
// add to widgets
|
||||
$widgets->choice->addChild('ref')->addAttribute('name', $export['name']);
|
||||
$widgets_choice->addChild('ref')->addAttribute('name', $export['name']);
|
||||
|
||||
// add the element-attributes
|
||||
$attrs = $grammar->addChild('define');
|
||||
@ -193,10 +286,11 @@ foreach($data['modules'] as $module)
|
||||
}
|
||||
else
|
||||
{
|
||||
$list = $element->addChild('oneOrMore'); // zeroOrMore for e.g. empty boxes?
|
||||
// add allowed children
|
||||
foreach((array)$overwrites[$export['name']]['.children'] as $child)
|
||||
{
|
||||
$element->addChild('ref')->addAttribute('name', $child);
|
||||
$list->addChild('ref')->addAttribute('name', $child);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +300,7 @@ foreach($data['modules'] as $module)
|
||||
}
|
||||
|
||||
$remove = [];
|
||||
foreach($widgets->choice->children() as $widget)
|
||||
foreach($widgets_choice->children() as $widget)
|
||||
{
|
||||
if (preg_match($overwrites['.remove'], $name=(string)$widget->attributes()['name']))
|
||||
{
|
||||
@ -261,8 +355,8 @@ echo preg_replace('#<choice>
|
||||
*/
|
||||
function removeWidget(string $name)
|
||||
{
|
||||
global $grammar, $widgets;
|
||||
if (removeByName($widgets->choice, $name))
|
||||
global $grammar, $widgets_choice;
|
||||
if (removeByName($widgets_choice, $name))
|
||||
{
|
||||
removeByName($grammar, $name);
|
||||
removeByName($grammar, 'attlist.'.$name);
|
||||
@ -381,7 +475,10 @@ function attributes(array $class, ?SimpleXMLElement $attrs=null)
|
||||
{
|
||||
$default = substr($default, 1, -1);
|
||||
}
|
||||
if ($default !== 'undefined') // do NOT add undefined, it's the default anyway
|
||||
{
|
||||
$attribute->addAttribute('a:defaultValue', $default, 'http://relaxng.org/ns/compatibility/annotations/1.0');
|
||||
}
|
||||
}
|
||||
switch ($attr['type']['text'] ?? 'any')
|
||||
{
|
||||
|
@ -26,9 +26,9 @@ function replace(string, terms)
|
||||
}
|
||||
|
||||
export default {
|
||||
globs: ["api/js/etemplate/**/Et2*/*.ts"],
|
||||
globs: ["api/js/etemplate/**/Et2*.ts","api/js/etemplate/Et2Nextmatch/**/*.ts"],
|
||||
/** Globs to exclude */
|
||||
exclude: [],//, 'et2_*.ts', '**/test/*', '**/*.styles.ts', '**/*.test.ts'],
|
||||
exclude: ["api/js/etemplate/**/test/*"],//, 'et2_*.ts', '**/test/*', '**/*.styles.ts', '**/*.test.ts'],
|
||||
dev: false,
|
||||
litelement: true,
|
||||
plugins: [
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,7 @@
|
||||
-->
|
||||
|
||||
<!ENTITY % Widgets "template|grid|vbox|box|details|hbox|groupbox|caption|split|button|buttononly|colorpicker|description|label|entry|contact-value|contact-account|contact-template|infolog-value|tracker-value|records-value|textbox|hidden|searchbox|int|integer|float|passwd|url|url-email|url-phone|url-fax|menupopup|listbox|select|select-cat|select-percent|select-priority|select-country|select-state|select-year|select-month|select-day|select-dow|select-hour|select-number|select-app|select-lang|select-bool|select-timezone|select-bitwise|menulist|checkbox|radio|radiogroup|date|date-time|date-timeonly|date-duration|date-since|date-time_today|time_or_date|date-range|diff|dropdown_button|styles|link-to|link-apps|link-entry|link|link-string|link-list|link-add|select-account|taglist|taglist-account|taglist-email|taglist-cat|taglist-thumbnail|taglist-state|customfields|customfields-list|favorites|html|htmlarea|tabbox|button-timestamp|timestamper|toolbar|tree|tree-cat|historylog|hrule|image|appicon|avatar|lavatar|iframe|file|progress|portlet|ajax_select|vfs|vfs-name|vfs-path|vfs-mime|vfs-size|vfs-mode|vfs-uid|vfs-gid|vfs-upload|vfs-select|video|audio|barcode|itempicker|script|countdown">
|
||||
<!ELEMENT overlay (%Widgets;)*>
|
||||
<!ELEMENT overlay (template)*>
|
||||
<!ELEMENT template (%Widgets;)*>
|
||||
<!ATTLIST template
|
||||
template CDATA #IMPLIED
|
||||
@ -59,13 +59,14 @@ attributes CDATA #IMPLIED
|
||||
class CDATA #IMPLIED
|
||||
width CDATA #IMPLIED>
|
||||
<!ELEMENT rows (row)*>
|
||||
<!ELEMENT row (%Widgets;)>
|
||||
<!ELEMENT row (%Widgets;)+>
|
||||
<!ATTLIST row
|
||||
class CDATA #IMPLIED
|
||||
height CDATA #IMPLIED
|
||||
valign CDATA #IMPLIED
|
||||
disabled CDATA #IMPLIED
|
||||
part CDATA #IMPLIED
|
||||
id CDATA #IMPLIED
|
||||
>
|
||||
<!ATTLIST grid
|
||||
border CDATA #IMPLIED
|
||||
@ -2984,7 +2985,7 @@ customfields CDATA #IMPLIED
|
||||
fields CDATA #IMPLIED
|
||||
value CDATA #IMPLIED
|
||||
type_filter CDATA #IMPLIED
|
||||
private (true|false) "undefined"
|
||||
private (true|false) #IMPLIED
|
||||
sub_app CDATA #IMPLIED
|
||||
onchange CDATA #IMPLIED
|
||||
prefix CDATA "#"
|
||||
@ -3017,7 +3018,7 @@ customfields CDATA #IMPLIED
|
||||
fields CDATA #IMPLIED
|
||||
value CDATA #IMPLIED
|
||||
type_filter CDATA #IMPLIED
|
||||
private (true|false) "undefined"
|
||||
private (true|false) #IMPLIED
|
||||
sub_app CDATA #IMPLIED
|
||||
onchange CDATA #IMPLIED
|
||||
prefix CDATA "#"
|
||||
@ -3158,7 +3159,7 @@ add_tabs (true|false) "false"
|
||||
tab_height CDATA #IMPLIED
|
||||
align_tabs (v|h) "h"
|
||||
>
|
||||
<!ELEMENT tabs (tab)>
|
||||
<!ELEMENT tabs (tab)*>
|
||||
<!ELEMENT tab EMPTY>
|
||||
<!ATTLIST tab
|
||||
id CDATA #IMPLIED
|
||||
|
@ -147,7 +147,7 @@
|
||||
<element name="overlay">
|
||||
<ref name="attlist.overlay"/>
|
||||
<zeroOrMore>
|
||||
<ref name="Widgets"/>
|
||||
<ref name="template"/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
@ -295,7 +295,9 @@
|
||||
<define name="row">
|
||||
<element name="row">
|
||||
<ref name="attlist.row"/>
|
||||
<oneOrMore>
|
||||
<ref name="Widgets"/>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
<define name="attlist.row" combine="interleave">
|
||||
@ -314,6 +316,9 @@
|
||||
<optional>
|
||||
<attribute name="part"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="id"/>
|
||||
</optional>
|
||||
</define>
|
||||
<define name="attlist.grid" combine="interleave">
|
||||
<optional>
|
||||
@ -11611,7 +11616,7 @@
|
||||
<attribute name="type_filter"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="private" a:defaultValue="undefined">
|
||||
<attribute name="private">
|
||||
<choice>
|
||||
<value>true</value>
|
||||
<value>false</value>
|
||||
@ -11729,7 +11734,7 @@
|
||||
<attribute name="type_filter"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="private" a:defaultValue="undefined">
|
||||
<attribute name="private">
|
||||
<choice>
|
||||
<value>true</value>
|
||||
<value>false</value>
|
||||
@ -12254,7 +12259,9 @@
|
||||
<define name="tabs">
|
||||
<element name="tabs">
|
||||
<ref name="attlist.tabs"/>
|
||||
<zeroOrMore>
|
||||
<ref name="tab"/>
|
||||
</zeroOrMore>
|
||||
</element>
|
||||
</define>
|
||||
<define name="attlist.tabs" combine="interleave">
|
||||
|
Loading…
Reference in New Issue
Block a user