mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 08:34:29 +01:00
WIP eTemplate2.0 DTD
This commit is contained in:
parent
c04cf276b7
commit
d1b3786b2a
127
doc/etemplate2-rng.php
Normal file → Executable file
127
doc/etemplate2-rng.php
Normal file → Executable file
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* eTemplate2 XML schema
|
* 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!");
|
die("Missing file '$file', you need to generate it from 'etemplate2.dtd' e.g. with PHPStorm!");
|
||||||
}
|
}
|
||||||
$grammar = new SimpleXMLElement(file_get_contents($file));
|
$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
|
* 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
|
* @todo fix in TS sources
|
||||||
*/
|
*/
|
||||||
$overwrites = [
|
$overwrites = [
|
||||||
@ -44,7 +46,9 @@ $overwrites = [
|
|||||||
'id' => 'string', // commented out with some reasoning in Et2Widget
|
'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
|
//'data' => null, // ToDo: not sure, but AFAIK this is no attribute, but somehow listed in each widget
|
||||||
'width' => 'string',
|
'width' => 'string',
|
||||||
|
'height' => 'string',
|
||||||
'span' => 'string', // actually int|"all"
|
'span' => 'string', // actually int|"all"
|
||||||
|
'slot' => 'string',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'Et2InputWidget' => [
|
'Et2InputWidget' => [
|
||||||
@ -109,7 +113,34 @@ $overwrites = [
|
|||||||
'et2-split' => [
|
'et2-split' => [
|
||||||
'.children' => 'Widgets',
|
'.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
|
// make overlay the only allowed start element
|
||||||
removeNode($grammar->start->choice);
|
removeNode($grammar->start->choice);
|
||||||
$grammar->start->addChild('ref')->addAttribute('name', 'overlay');
|
$grammar->start->addChild('ref')->addAttribute('name', 'overlay');
|
||||||
// overlay can only container template, not all widgets
|
// fix legacy widgets: attribute-name => (array of) widgets
|
||||||
getByName($grammar, 'overlay')->element->zeroOrMore->ref->attributes()['name'] = 'template';
|
$missing_legacy_attributes = [
|
||||||
getByName($grammar, 'attlist.vfs-upload')->addChild('optional')
|
'callback' => 'vfs-upload',
|
||||||
->addChild('attribute')->addAttribute('name', 'callback');
|
'statustext' => 'tab',
|
||||||
// add statustext to tab
|
'minWidth' => 'column',
|
||||||
getByName($grammar, 'attlist.tab')->addChild('optional')
|
'maxWidth' => 'column',
|
||||||
->addChild('attribute')->addAttribute('name', 'statustext');
|
'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
|
// build a hashed version of all classes, members and attributes to e.g. find ancestors
|
||||||
$classes = [];
|
$classes = [];
|
||||||
@ -175,7 +268,7 @@ foreach($data['modules'] as $module)
|
|||||||
$attrs = $element->addChild('ref');
|
$attrs = $element->addChild('ref');
|
||||||
$attrs->addAttribute('name', 'attlist.'.$export['name']);
|
$attrs->addAttribute('name', 'attlist.'.$export['name']);
|
||||||
// add to widgets
|
// add to widgets
|
||||||
$widgets->choice->addChild('ref')->addAttribute('name', $export['name']);
|
$widgets_choice->addChild('ref')->addAttribute('name', $export['name']);
|
||||||
|
|
||||||
// add the element-attributes
|
// add the element-attributes
|
||||||
$attrs = $grammar->addChild('define');
|
$attrs = $grammar->addChild('define');
|
||||||
@ -193,10 +286,11 @@ foreach($data['modules'] as $module)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
$list = $element->addChild('oneOrMore'); // zeroOrMore for e.g. empty boxes?
|
||||||
// add allowed children
|
// add allowed children
|
||||||
foreach((array)$overwrites[$export['name']]['.children'] as $child)
|
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 = [];
|
$remove = [];
|
||||||
foreach($widgets->choice->children() as $widget)
|
foreach($widgets_choice->children() as $widget)
|
||||||
{
|
{
|
||||||
if (preg_match($overwrites['.remove'], $name=(string)$widget->attributes()['name']))
|
if (preg_match($overwrites['.remove'], $name=(string)$widget->attributes()['name']))
|
||||||
{
|
{
|
||||||
@ -261,8 +355,8 @@ echo preg_replace('#<choice>
|
|||||||
*/
|
*/
|
||||||
function removeWidget(string $name)
|
function removeWidget(string $name)
|
||||||
{
|
{
|
||||||
global $grammar, $widgets;
|
global $grammar, $widgets_choice;
|
||||||
if (removeByName($widgets->choice, $name))
|
if (removeByName($widgets_choice, $name))
|
||||||
{
|
{
|
||||||
removeByName($grammar, $name);
|
removeByName($grammar, $name);
|
||||||
removeByName($grammar, 'attlist.'.$name);
|
removeByName($grammar, 'attlist.'.$name);
|
||||||
@ -381,7 +475,10 @@ function attributes(array $class, ?SimpleXMLElement $attrs=null)
|
|||||||
{
|
{
|
||||||
$default = substr($default, 1, -1);
|
$default = substr($default, 1, -1);
|
||||||
}
|
}
|
||||||
$attribute->addAttribute('a:defaultValue', $default, 'http://relaxng.org/ns/compatibility/annotations/1.0');
|
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')
|
switch ($attr['type']['text'] ?? 'any')
|
||||||
{
|
{
|
||||||
|
@ -26,9 +26,9 @@ function replace(string, terms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
globs: ["api/js/etemplate/**/Et2*/*.ts"],
|
globs: ["api/js/etemplate/**/Et2*.ts","api/js/etemplate/Et2Nextmatch/**/*.ts"],
|
||||||
/** Globs to exclude */
|
/** 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,
|
dev: false,
|
||||||
litelement: true,
|
litelement: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
@ -195,4 +195,4 @@ export default {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
]
|
]
|
||||||
};
|
};
|
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">
|
<!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;)*>
|
<!ELEMENT template (%Widgets;)*>
|
||||||
<!ATTLIST template
|
<!ATTLIST template
|
||||||
template CDATA #IMPLIED
|
template CDATA #IMPLIED
|
||||||
@ -59,13 +59,14 @@ attributes CDATA #IMPLIED
|
|||||||
class CDATA #IMPLIED
|
class CDATA #IMPLIED
|
||||||
width CDATA #IMPLIED>
|
width CDATA #IMPLIED>
|
||||||
<!ELEMENT rows (row)*>
|
<!ELEMENT rows (row)*>
|
||||||
<!ELEMENT row (%Widgets;)>
|
<!ELEMENT row (%Widgets;)+>
|
||||||
<!ATTLIST row
|
<!ATTLIST row
|
||||||
class CDATA #IMPLIED
|
class CDATA #IMPLIED
|
||||||
height CDATA #IMPLIED
|
height CDATA #IMPLIED
|
||||||
valign CDATA #IMPLIED
|
valign CDATA #IMPLIED
|
||||||
disabled CDATA #IMPLIED
|
disabled CDATA #IMPLIED
|
||||||
part CDATA #IMPLIED
|
part CDATA #IMPLIED
|
||||||
|
id CDATA #IMPLIED
|
||||||
>
|
>
|
||||||
<!ATTLIST grid
|
<!ATTLIST grid
|
||||||
border CDATA #IMPLIED
|
border CDATA #IMPLIED
|
||||||
@ -2984,7 +2985,7 @@ customfields CDATA #IMPLIED
|
|||||||
fields CDATA #IMPLIED
|
fields CDATA #IMPLIED
|
||||||
value CDATA #IMPLIED
|
value CDATA #IMPLIED
|
||||||
type_filter CDATA #IMPLIED
|
type_filter CDATA #IMPLIED
|
||||||
private (true|false) "undefined"
|
private (true|false) #IMPLIED
|
||||||
sub_app CDATA #IMPLIED
|
sub_app CDATA #IMPLIED
|
||||||
onchange CDATA #IMPLIED
|
onchange CDATA #IMPLIED
|
||||||
prefix CDATA "#"
|
prefix CDATA "#"
|
||||||
@ -3017,7 +3018,7 @@ customfields CDATA #IMPLIED
|
|||||||
fields CDATA #IMPLIED
|
fields CDATA #IMPLIED
|
||||||
value CDATA #IMPLIED
|
value CDATA #IMPLIED
|
||||||
type_filter CDATA #IMPLIED
|
type_filter CDATA #IMPLIED
|
||||||
private (true|false) "undefined"
|
private (true|false) #IMPLIED
|
||||||
sub_app CDATA #IMPLIED
|
sub_app CDATA #IMPLIED
|
||||||
onchange CDATA #IMPLIED
|
onchange CDATA #IMPLIED
|
||||||
prefix CDATA "#"
|
prefix CDATA "#"
|
||||||
@ -3158,7 +3159,7 @@ add_tabs (true|false) "false"
|
|||||||
tab_height CDATA #IMPLIED
|
tab_height CDATA #IMPLIED
|
||||||
align_tabs (v|h) "h"
|
align_tabs (v|h) "h"
|
||||||
>
|
>
|
||||||
<!ELEMENT tabs (tab)>
|
<!ELEMENT tabs (tab)*>
|
||||||
<!ELEMENT tab EMPTY>
|
<!ELEMENT tab EMPTY>
|
||||||
<!ATTLIST tab
|
<!ATTLIST tab
|
||||||
id CDATA #IMPLIED
|
id CDATA #IMPLIED
|
||||||
|
@ -147,7 +147,7 @@
|
|||||||
<element name="overlay">
|
<element name="overlay">
|
||||||
<ref name="attlist.overlay"/>
|
<ref name="attlist.overlay"/>
|
||||||
<zeroOrMore>
|
<zeroOrMore>
|
||||||
<ref name="Widgets"/>
|
<ref name="template"/>
|
||||||
</zeroOrMore>
|
</zeroOrMore>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
@ -295,7 +295,9 @@
|
|||||||
<define name="row">
|
<define name="row">
|
||||||
<element name="row">
|
<element name="row">
|
||||||
<ref name="attlist.row"/>
|
<ref name="attlist.row"/>
|
||||||
<ref name="Widgets"/>
|
<oneOrMore>
|
||||||
|
<ref name="Widgets"/>
|
||||||
|
</oneOrMore>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
<define name="attlist.row" combine="interleave">
|
<define name="attlist.row" combine="interleave">
|
||||||
@ -314,6 +316,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<attribute name="part"/>
|
<attribute name="part"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="id"/>
|
||||||
|
</optional>
|
||||||
</define>
|
</define>
|
||||||
<define name="attlist.grid" combine="interleave">
|
<define name="attlist.grid" combine="interleave">
|
||||||
<optional>
|
<optional>
|
||||||
@ -11611,7 +11616,7 @@
|
|||||||
<attribute name="type_filter"/>
|
<attribute name="type_filter"/>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="private" a:defaultValue="undefined">
|
<attribute name="private">
|
||||||
<choice>
|
<choice>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
@ -11729,7 +11734,7 @@
|
|||||||
<attribute name="type_filter"/>
|
<attribute name="type_filter"/>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="private" a:defaultValue="undefined">
|
<attribute name="private">
|
||||||
<choice>
|
<choice>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
@ -12254,7 +12259,9 @@
|
|||||||
<define name="tabs">
|
<define name="tabs">
|
||||||
<element name="tabs">
|
<element name="tabs">
|
||||||
<ref name="attlist.tabs"/>
|
<ref name="attlist.tabs"/>
|
||||||
<ref name="tab"/>
|
<zeroOrMore>
|
||||||
|
<ref name="tab"/>
|
||||||
|
</zeroOrMore>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
<define name="attlist.tabs" combine="interleave">
|
<define name="attlist.tabs" combine="interleave">
|
||||||
|
Loading…
Reference in New Issue
Block a user