u2ui 1.5.2 → 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/el/ico/ico.js +5 -5
- package/el/rte/README.md +53 -13
- package/el/rte/manifest.json +19 -4
- package/el/rte/rte.css +31 -6
- package/el/rte/rte.js +174 -44
- package/el/rte0/README.md +37 -0
- package/el/rte0/manifest.json +33 -0
- package/el/rte0/rte0.css +9 -0
- package/el/rte0/rte0.js +56 -0
- package/el/system/styler.js +2 -0
- package/el/tooltip/tooltip.css +2 -2
- package/js/Placer/Placer.js +2 -1
- package/js/rte/AGENTS.md +142 -0
- package/js/rte/PLAN.md +488 -0
- package/js/rte/README.md +319 -25
- package/js/rte/blocks.js +7 -0
- package/js/rte/breaks.js +6 -0
- package/js/rte/classes.js +7 -0
- package/js/rte/docs/usage.md +845 -0
- package/js/rte/images.js +7 -0
- package/js/rte/link.js +8 -0
- package/js/rte/playground/README.md +95 -0
- package/js/rte/playground/hosts.html +518 -0
- package/js/rte/playground/index.html +824 -0
- package/js/rte/rte.js +56 -5
- package/js/rte/source.js +12 -0
- package/js/rte/src/browser/README.md +40 -0
- package/js/rte/src/browser/range-rect.js +82 -0
- package/js/rte/src/client/README.md +378 -0
- package/js/rte/src/client/blocks.js +38 -0
- package/js/rte/src/client/breaks.js +212 -0
- package/js/rte/src/client/classes.js +48 -0
- package/js/rte/src/client/editor.js +461 -0
- package/js/rte/src/client/external-input.js +47 -0
- package/js/rte/src/client/history.js +13 -0
- package/js/rte/src/client/images.js +275 -0
- package/js/rte/src/client/link.js +572 -0
- package/js/rte/src/client/marks.js +25 -0
- package/js/rte/src/client/source.js +182 -0
- package/js/rte/src/client/structure.js +27 -0
- package/js/rte/src/client/tables.js +162 -0
- package/js/rte/src/client/unstyle.js +32 -0
- package/js/rte/src/command/README.md +517 -0
- package/js/rte/src/command/block-boundary.js +43 -0
- package/js/rte/src/command/block-style.js +120 -0
- package/js/rte/src/command/commands.js +158 -0
- package/js/rte/src/command/delete.js +112 -0
- package/js/rte/src/command/edit.js +72 -0
- package/js/rte/src/command/element.js +45 -0
- package/js/rte/src/command/enter.js +175 -0
- package/js/rte/src/command/fragment.js +76 -0
- package/js/rte/src/command/insert.js +52 -0
- package/js/rte/src/command/list.js +284 -0
- package/js/rte/src/command/mark.js +583 -0
- package/js/rte/src/command/pending-marks.js +216 -0
- package/js/rte/src/command/table.js +207 -0
- package/js/rte/src/command/unstyle.js +248 -0
- package/js/rte/src/config/README.md +96 -0
- package/js/rte/src/config/config.js +127 -0
- package/js/rte/src/core/README.md +41 -0
- package/js/rte/src/core/core.js +156 -0
- package/js/rte/src/history/README.md +83 -0
- package/js/rte/src/history/history.js +283 -0
- package/js/rte/src/input/README.md +155 -0
- package/js/rte/src/input/external-input.js +130 -0
- package/js/rte/src/input/input-pipeline.js +414 -0
- package/js/rte/src/mark/README.md +219 -0
- package/js/rte/src/mark/dom-adapter.js +100 -0
- package/js/rte/src/mark/mark.js +133 -0
- package/js/rte/src/mark/standard.js +76 -0
- package/js/rte/src/model/README.md +71 -0
- package/js/rte/src/model/content-model.js +213 -0
- package/js/rte/src/model/html/README.md +51 -0
- package/js/rte/src/model/html/html-model.js +90 -0
- package/js/rte/src/normalize/execute/README.md +33 -0
- package/js/rte/src/normalize/execute/repair-executor.js +129 -0
- package/js/rte/src/normalize/normalizer/README.md +48 -0
- package/js/rte/src/normalize/normalizer/normalizer.js +141 -0
- package/js/rte/src/normalize/repair/README.md +70 -0
- package/js/rte/src/normalize/repair/repair-planner.js +208 -0
- package/js/rte/src/sanitize/README.md +105 -0
- package/js/rte/src/sanitize/native.js +43 -0
- package/js/rte/src/sanitize/policy.js +202 -0
- package/js/rte/src/selection/README.md +39 -0
- package/js/rte/src/selection/map/README.md +53 -0
- package/js/rte/src/selection/map/point-map.js +307 -0
- package/js/rte/src/selection/ownership/README.md +32 -0
- package/js/rte/src/selection/ownership/ownership.js +42 -0
- package/js/rte/src/selection/point/README.md +34 -0
- package/js/rte/src/selection/point/point.js +83 -0
- package/js/rte/src/selection/range/README.md +38 -0
- package/js/rte/src/selection/range/edit-range.js +223 -0
- package/js/rte/src/selection/snapshot.js +64 -0
- package/js/rte/src/source/README.md +64 -0
- package/js/rte/src/source/source.js +193 -0
- package/js/rte/src/surface/README.md +36 -0
- package/js/rte/src/surface/content.js +16 -0
- package/js/rte/src/surface/surface.js +87 -0
- package/js/rte/src/transaction/README.md +35 -0
- package/js/rte/src/transaction/transaction.js +56 -0
- package/js/rte/src/ui/README.md +255 -0
- package/js/rte/src/ui/chrome.js +214 -0
- package/js/rte/src/ui/handles.js +179 -0
- package/js/rte/src/ui/place.js +25 -0
- package/js/rte/src/ui/toolbar.js +283 -0
- package/js/rte/src/unstyle/README.md +103 -0
- package/js/rte/src/unstyle/unstyle.js +140 -0
- package/js/rte/tables.js +7 -0
- package/js/rte/unstyle.js +8 -0
- package/js/rte0/README.md +37 -0
- package/js/rte0/rte.js +7 -0
- package/js/{rte → rte0}/src/behavior.js +0 -1
- package/js/{rte → rte0}/src/events.js +0 -1
- package/js/{rte → rte0}/src/range.js +0 -2
- package/js/{rte → rte0}/src/ui.items.js +0 -2
- package/js/{rte → rte0}/src/ui.js +0 -1
- package/package.json +1 -1
- package/u2/Element.js +16 -4
- package/u2/enhance.js +2 -1
- package/u2/plan-scoped-refactoring.md +133 -304
- package/u2/projects.json +18 -2
- package/u2/tools/update.repos.json.js +1 -1
- package/u2/utils.js +0 -16
- package/el/qrcode/package.json +0 -22
- /package/js/{rte → rte0}/old/NodeCleaner.js +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.ui.items.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.ui.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/crossbrowser.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/font/tinymce.svg +0 -0
- /package/js/{rte → rte0}/old/Rte/font/tinymce.woff +0 -0
- /package/js/{rte → rte0}/old/Rte/helpers.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/htmlparser.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/index.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/main.css +0 -0
- /package/js/{rte → rte0}/old/old.rte.js +0 -0
- /package/js/{rte → rte0}/old/range-selection.old.js +0 -0
- /package/js/{rte → rte0}/src/fixes.js +0 -0
- /package/js/{rte → rte0}/src/rte.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/ai.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/code.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/undo.js +0 -0
- /package/js/{rte → rte0}/src/util/htmlparser.js +0 -0
- /package/js/{rte → rte0}/src/util/indentHtml.js +0 -0
|
@@ -1,337 +1,166 @@
|
|
|
1
|
-
# Scoped
|
|
2
|
-
|
|
3
|
-
## Ziel
|
|
4
|
-
|
|
5
|
-
Eine u2-Instanz **isoliert** in einem Shadow-DOM betreiben — konkreter Anwendungsfall: das CMS-Panel
|
|
6
|
-
soll seine **eigene** u2-Version laden, ohne `window.customElements` zu verschmutzen
|
|
7
|
-
oder mit der u2-Version der Host-Seite zu kollidieren.
|
|
8
|
-
|
|
9
|
-
Dazu müssen zwei Dinge zusammenkommen:
|
|
10
|
-
|
|
11
|
-
1. Element-Dateien registrieren sich **nicht mehr selbst global** (kein
|
|
12
|
-
`customElements.define(...)` als Import-Side-Effect).
|
|
13
|
-
2. Registrierung läuft über eine **austauschbare Registry** — global
|
|
14
|
-
(`window.customElements`) oder scoped (`new CustomElementRegistry()`), gebunden
|
|
15
|
-
an einen ShadowRoot.
|
|
16
|
-
|
|
17
|
-
## Ausgangslage
|
|
18
|
-
|
|
19
|
-
- `el/{name}/{name}.js` definiert am Datei-Ende `customElements.define('u2-{name}', …)`
|
|
20
|
-
als Side-Effect.
|
|
21
|
-
- [`u2/auto.js`](auto.js) beobachtet das DOM per `MutationObserver`, importiert bei
|
|
22
|
-
Gebrauch das passende Modul und verlässt sich darauf, dass **der Import** das Element
|
|
23
|
-
global registriert.
|
|
24
|
-
- **43 von 44** Element-Dateien sind bereits 1:1 `el/{name}/{name}.js` → `u2-{name}`
|
|
25
|
-
und exportieren `export default class`.
|
|
26
|
-
- Sonderfälle:
|
|
27
|
-
- [`el/calendar/calendar.js`](../el/calendar/calendar.js) definiert **zwei** Elemente
|
|
28
|
-
(`u2-calendar` + `u2-calendaritem`); `U2CalendarItem` ist aktuell **nicht** exportiert.
|
|
29
|
-
- [`el/system/styler.js`](../el/system/styler.js) → `u2-system-styler` (Tag ≠ Ordnername,
|
|
30
|
-
wird nicht über auto.js geladen).
|
|
31
|
-
- Einige Elemente rendern **andere** u2-Elemente in ihr eigenes Shadow-DOM und
|
|
32
|
-
verlassen sich auf den globalen Side-Effect, z.B.
|
|
33
|
-
[`el/accordion/accordion.js`](../el/accordion/accordion.js) → `import('../ico/ico.js')`,
|
|
34
|
-
ebenso `buttongroup`→`focusgroup`, `fields`→`responsive`, `rating`→`ico`.
|
|
35
|
-
|
|
36
|
-
## Zielarchitektur
|
|
37
|
-
|
|
38
|
-
### `U2Auto` — Factory statt globalem Modul-Side-Effect
|
|
39
|
-
|
|
40
|
-
Der MutationObserver-Mechanismus aus [`u2/auto.js`](auto.js) wird zu einer Klasse,
|
|
41
|
-
die eine **Registry** und einen **Root** kapselt. Beim Erkennen eines Elements
|
|
42
|
-
importiert sie das Modul und registriert es **selbst** aus den Exports — statt sich auf
|
|
43
|
-
den Side-Effect zu verlassen.
|
|
1
|
+
# Scoped u2: mehrere u2-Versionen auf einer Seite
|
|
44
2
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
constructor(root, registry = root.registry ?? customElements) {
|
|
49
|
-
this.root = root;
|
|
50
|
-
this.registry = registry;
|
|
51
|
-
this.mo = new MutationObserver(entries => {
|
|
52
|
-
for (const entry of entries)
|
|
53
|
-
for (const node of entry.addedNodes) this._newNodeRoot(node);
|
|
54
|
-
});
|
|
55
|
-
this.mo.observe(root, { childList: true, subtree: true });
|
|
56
|
-
this._newNodeRoot(root);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async _loadEl(name) {
|
|
60
|
-
const tag = 'u2-' + name;
|
|
61
|
-
if (this.registry.get(tag)) return;
|
|
62
|
-
const mod = await import(rootUrl + 'el/' + name + '/' + name + '.js');
|
|
63
|
-
if (!this.registry.get(tag)) this.registry.define(tag, mod.default);
|
|
64
|
-
for (const [t, cls] of Object.entries(mod.extraElements ?? {}))
|
|
65
|
-
if (!this.registry.get(t)) this.registry.define(t, cls);
|
|
66
|
-
}
|
|
67
|
-
// … _newNode / _newNodeRoot / class + attr handling wie bisher
|
|
68
|
-
}
|
|
69
|
-
```
|
|
3
|
+
**Ziel:** Ein CMS-Panel (oder jedes andere eingebettete UI) läuft mit *seiner* u2-Version in
|
|
4
|
+
*seinem* Shadow-Root, unabhängig davon, welche u2-Version die Kundenseite lädt. Grundlage sind
|
|
5
|
+
Scoped Custom Element Registries — Chrome/Edge 146+, Safari 26+, Firefox noch nicht.
|
|
70
6
|
|
|
71
|
-
|
|
72
|
-
`new U2Auto(document.documentElement)` erzeugt → Registry = `customElements`.
|
|
73
|
-
- **Scoped**: `new U2Auto(shadowRoot, scopedRegistry)` → registriert **nur** in dieses
|
|
74
|
-
Shadow, `window.customElements` bleibt unberührt.
|
|
7
|
+
---
|
|
75
8
|
|
|
76
|
-
|
|
9
|
+
## Stand (1.5.3)
|
|
77
10
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
bekommt, ist es zum *Erzeugen* der Registry längst zu spät.
|
|
11
|
+
**Funktioniert.** Das Panel kann u2-Elemente benutzen, ohne dass auf der Kundenseite etwas kaputt
|
|
12
|
+
geht — auch wenn beide eine andere u2-Version fahren.
|
|
81
13
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
bekommt den Root selbst, nicht den Host).
|
|
14
|
+
| Datei | Rolle |
|
|
15
|
+
|---|---|
|
|
16
|
+
| [`u2/enhance.js`](enhance.js) | scannt einen Root, lädt Elemente/Klassen/Attribute nach, registriert sie in **dessen** Registry. `attachShadow(host, opts)` als Convenience. Ein `MutationObserver` hält es aktuell — dieselbe Mechanik wie `auto.js`, nur ohne globale Nebenwirkungen. |
|
|
17
|
+
| [`u2/Element.js`](Element.js) | Basisklasse. `attachShadow()` belegt `customElementRegistry` vor, `useEl`/`useClass`/`useAttr` holen Kinder samt CSS ins eigene Shadow. Hängt an nichts. |
|
|
18
|
+
| [`u2/auto.js`](auto.js) | unverändert im Verhalten, benutzt intern `enhance` |
|
|
19
|
+
| [`u2/tests/enhance.test.html`](tests/enhance.test.html) | Browser-Test, 35 grün, 1 bekannte Lücke |
|
|
89
20
|
|
|
90
|
-
|
|
21
|
+
`enhance` bindet `css/norm/norm.css` und `css/base/base.css` automatisch ein. Elemente definieren
|
|
22
|
+
sich weiterhin selbst global, aber mit Guard (`customElements.get(tag) || define(...)`) — deshalb
|
|
23
|
+
wirft eine zweite u2-Version nicht mehr.
|
|
91
24
|
|
|
92
|
-
|
|
25
|
+
### Zwei Regeln, die daraus folgen
|
|
93
26
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
27
|
+
**1. Wer ein u2-Element in sein eigenes Shadow rendert, erbt von `U2Element`.** Das ist keine
|
|
28
|
+
Migration — von 41 Elementen tun das genau sechs: `alert`, `accordion`, `calendar`, `rating`
|
|
29
|
+
(je `ico`), `input` (`ico`, `bytes`, `badge`) und `fields` (`responsive`). Die übrigen 35 öffnen
|
|
30
|
+
entweder kein Shadow oder rendern nichts von u2 hinein.
|
|
31
|
+
|
|
32
|
+
**2. Kind-CSS gehört in den Root, in dem das Kind steht.** u2-Elemente haben meist *kein* eigenes
|
|
33
|
+
Shadow — `ico` schreibt sein SVG ins Light DOM, und `ico.css` stylt `u2-ico { … }` von aussen. Ein
|
|
34
|
+
Kind kann sich nicht selbst stylen, der Vater muss die CSS holen. Das macht jetzt `use*()`.
|
|
35
|
+
|
|
36
|
+
### Warum keine Deklaration am Element
|
|
37
|
+
|
|
38
|
+
Ein `static hasCss` müsste erst per JS geladen werden, bevor die CSS überhaupt startet — es macht
|
|
39
|
+
den wichtigeren Request garantiert langsamer. `projects.json` wäre ebenfalls erst ein Fetch (und ist
|
|
40
|
+
Enhance-Territorium). Also beides parallel und bedingungslos; die Defaults kommen aus der Kategorie:
|
|
41
|
+
|
|
42
|
+
| | js | css | Dateien im Repo |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| `el` | ja | ja | js 41/41, css 37/41 |
|
|
45
|
+
| `class` | **nein** | ja | js 0/8, css 8/8 |
|
|
46
|
+
| `attr` | ja | **nein** | js 15/16, css 1/16 |
|
|
47
|
+
|
|
48
|
+
Ausreisser gehören an die Aufrufstelle, nicht als Feld an alle 41 Elemente:
|
|
49
|
+
`useAttr('skin', {css:true, js:false})`. `skin` bleibt dauerhaft ein Attribut, weil es einen Wert
|
|
50
|
+
trägt — als Klasse ginge das erst mit einem Selektor wie `.u2-class-*`.
|
|
51
|
+
|
|
52
|
+
`v1.5.3` ist veröffentlicht; qino zeigt darauf — beide Pins,
|
|
53
|
+
[`qino/deno.json`](../../qinojs/qino/deno.json) und `core/lib/util.ts`, ein Test wacht über den
|
|
54
|
+
Gleichlauf. `deno check --all qino/` ist grün.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Offen
|
|
102
59
|
|
|
103
|
-
###
|
|
60
|
+
### 1. Attribute — der eigentlich ungelöste Teil
|
|
104
61
|
|
|
105
|
-
|
|
62
|
+
Elemente sind isoliert, Attribute nicht. Ein Attribut-Modul hängt beim Auswerten Listener ans
|
|
63
|
+
`document`:
|
|
106
64
|
|
|
107
65
|
```js
|
|
108
|
-
|
|
109
|
-
export function define(tag, cls, registry = customElements) {
|
|
110
|
-
if (!registry.get(tag)) registry.define(tag, cls);
|
|
111
|
-
}
|
|
66
|
+
document.addEventListener('click', e => { … e.composedPath()[0].closest('[u2-confirm]') … });
|
|
112
67
|
```
|
|
113
68
|
|
|
114
|
-
Der
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
## Firefox / Scoped Custom Element Registries
|
|
118
|
-
|
|
119
|
-
- Native `attachShadow({ registry })`, `new CustomElementRegistry()` und der Getter
|
|
120
|
-
`ShadowRoot.prototype.registry`: **Chrome/Safari ja, Firefox noch nicht.**
|
|
121
|
-
- Lösung: der offizielle Polyfill
|
|
122
|
-
**`@webcomponents/scoped-custom-element-registry`**.
|
|
123
|
-
- **Wichtig:** der Polyfill **behält den Tag-Namen** bei (`u2-foo` bleibt `u2-foo`).
|
|
124
|
-
Er renamed nicht, sondern patcht `attachShadow`, den `innerHTML`-Setter,
|
|
125
|
-
`createElement`, `importNode` etc. und wendet im jeweiligen Scope den richtigen
|
|
126
|
-
Konstruktor auf denselben Tag an.
|
|
127
|
-
→ **CSS `u2-foo {}` matcht weiterhin**, Shadow-`<style>` sowieso.
|
|
128
|
-
- Der „Name ändert sich / CSS bricht"-Fall gilt nur bei selbstgebautem Poor-man's-Scoping
|
|
129
|
-
(`u2-foo-v2` pro Scope) — das machen wir **nicht**.
|
|
130
|
-
- Realkosten des Polyfills:
|
|
131
|
-
- muss **vor** dem ersten scoped ShadowRoot geladen sein,
|
|
132
|
-
- etwas Laufzeit-Overhead,
|
|
133
|
-
- wenige Edge-Cases (`el.constructor`).
|
|
134
|
-
- **Namen (recherchiert, nicht `registry` — das war ein Entwurfsname):**
|
|
135
|
-
`host.attachShadow({ customElementRegistry })`, Rücklesen über
|
|
136
|
-
`root.customElementRegistry`, programmatisch
|
|
137
|
-
`document.createElement(tag, { customElementRegistry })`, nachträglich
|
|
138
|
-
`registry.initialize(root)`. Chrome/Edge 146+, Safari 26+, Firefox noch nicht.
|
|
139
|
-
- Feature-Detection:
|
|
140
|
-
```js
|
|
141
|
-
if (!('customElementRegistry' in ShadowRoot.prototype))
|
|
142
|
-
await import('.../scoped-custom-element-registry.min.js');
|
|
143
|
-
```
|
|
144
|
-
Einmal am Anfang laden, danach funktioniert scoped überall gleich.
|
|
145
|
-
|
|
146
|
-
## CSS-Anmerkung
|
|
147
|
-
|
|
148
|
-
Komponenten-CSS liegt teils im Shadow des Elements (accordion importiert `ico.css` in sein
|
|
149
|
-
eigenes Shadow), teils stylt es das Element **von aussen**: `ico.css` setzt
|
|
150
|
-
`u2-ico { --size }` und `u2-ico > svg { height }`. Solches CSS muss in den
|
|
151
|
-
**konsumierenden** Root — ohne es hat `u2-ico` dort keine Grösse. `U2Auto` lädt Element-CSS
|
|
152
|
-
deshalb in seinen Root, nicht ins Dokument.
|
|
153
|
-
|
|
154
|
-
Das globale `impCss` (classless/utilities/base) bleibt davon unberührt; ob es zusätzlich ins
|
|
155
|
-
Panel-Shadow soll, entscheidet man separat.
|
|
156
|
-
|
|
157
|
-
**Was in einen Root gehört und was nicht** — die Trennlinie verläuft nach Selektor-Reichweite,
|
|
158
|
-
nicht nach Datei:
|
|
159
|
-
|
|
160
|
-
| | |
|
|
161
|
-
|---|---|
|
|
162
|
-
| vererbend (Tokens, `line-height`, `hyphens`, `font-family`) | kommt durch die Grenze — **nicht** in `:host` setzen, das wäre ein Zurücksetzen |
|
|
163
|
-
| Element-/Universalselektoren (`*{box-sizing}`, `input{font:inherit}`, `img{max-inline-size}`, `table`, `a`, `h1`) | hält an der Grenze — **nur dafür** adoptiert man ein Sheet |
|
|
164
|
-
| Host-Kasten (`block-size`, `overflow-y`, `scrollbar-gutter`) | gehört gar nicht auf `:host` |
|
|
69
|
+
Der Radius ist enger als es klingt: ein Attribut wirkt nur auf Elemente, die seinen Namen tragen.
|
|
70
|
+
Hat die Kundenseite kein `u2-confirm`, merkt sie von der Panel-Nutzung nichts. Drei echte Risiken,
|
|
71
|
+
nach Schwere:
|
|
165
72
|
|
|
166
|
-
`
|
|
167
|
-
|
|
73
|
+
**a) `draghandle` verändert die Kundenseite bedingungslos.** [`attr/draghandle/draghandle.js:1`](../attr/draghandle/draghandle.js)
|
|
74
|
+
importiert statisch einen Fremd-Polyfill von `bernardo-castilho.github.io` — ein Drittanbieter-Script
|
|
75
|
+
auf einer fremden Seite, plus CSP-Problem. Das CSS daneben ist harmlos, es hängt an
|
|
76
|
+
`[u2-draghandle]`. **Im Panel bis auf Weiteres meiden.**
|
|
168
77
|
|
|
169
|
-
|
|
170
|
-
|
|
78
|
+
**b) Doppelinstallation.** Lädt die Kundenseite dasselbe Attribut aus ihrer Version, hängen zwei
|
|
79
|
+
Listener-Sätze am Dokument → doppelte Confirm-Dialoge, doppelte Drops. Der realistische Alltagsfall.
|
|
171
80
|
|
|
172
|
-
|
|
81
|
+
**c) Version-Hijack.** Wer zuerst lädt, gewinnt — wie bei Elementen vor Phase 3.
|
|
173
82
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
83
|
+
**Billiger Zwischenschritt (nicht breaking, ~16 Einzeiler):** ein Idempotenz-Guard pro Attribut, das
|
|
84
|
+
Gegenstück zu `customElements.get()` — ein Symbol am `document`, die zweite Kopie installiert nicht.
|
|
85
|
+
Erledigt (b) vollständig; aus „zwei kaputte Kopien" wird „eine funktionierende". (c) bleibt.
|
|
177
86
|
|
|
178
|
-
**
|
|
87
|
+
**Richtige Lösung (1.6.0):** Attribute exportieren `install(root)` statt sich selbst zu installieren,
|
|
88
|
+
`useAttr` installiert in den Root. **Der Haken:** fünf von ihnen — `confirm`, `dropzone`,
|
|
89
|
+
`draghandle`, `movable`, `selectable` — benutzen `composedPath()` *absichtlich*, um über
|
|
90
|
+
Shadow-Grenzen hinweg zu arbeiten. Für die ist „der Root" nicht die richtige Grenze. Das geht Modul
|
|
91
|
+
für Modul und ist eine Design-, keine Fleissarbeit.
|
|
179
92
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
keine Singleton zu importieren, es folgt seinem Root.
|
|
93
|
+
**Nebenbefund, unabhängig davon:** manche Attribute funktionieren im Shadow-DOM *heute schon* nicht
|
|
94
|
+
sauber. `dropzone` sucht seine Zonen per [`document.querySelectorAll('[u2-dropzone]')`](../attr/dropzone/dropzone.js#L17),
|
|
95
|
+
was in einen Shadow-Root nicht hineinsieht — die Events kommen per `composedPath` an, die
|
|
96
|
+
Buchhaltung nicht.
|
|
185
97
|
|
|
186
|
-
|
|
98
|
+
### 2. Phase 3 — Selbstregistrierung entfernen (die letzte Lücke)
|
|
187
99
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
100
|
+
Die eine verbleibende rote Zeile im Browser-Test: `el/ico/ico.js` registriert sich weiterhin in
|
|
101
|
+
`window.customElements`.
|
|
102
|
+
|
|
103
|
+
**Was es bringt:** Ladereihenfolge wird egal. Heute gilt: lädt das **Panel zuerst**, definiert es
|
|
104
|
+
`u2-ico` aus seiner Version global; danach sieht das u2 der Kundenseite den Namen belegt,
|
|
105
|
+
überspringt still — und **die Kundenseite bekommt die Panel-Version**. Kein Fehler, kein Hinweis.
|
|
106
|
+
Umgekehrt (Kunde zuerst) ist alles korrekt.
|
|
107
|
+
|
|
108
|
+
**Was es kostet:** nicht die 16 Repo-Seiten, die ein Element-JS direkt per Script-Tag laden
|
|
109
|
+
(98 weitere gehen über `auto.js` und wären unberührt), sondern dass
|
|
191
110
|
|
|
192
|
-
|
|
193
|
-
|
|
111
|
+
```html
|
|
112
|
+
<script src="…/el/buttongroup/buttongroup.js" type=module async></script>
|
|
194
113
|
```
|
|
195
114
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
> Ohne diesen Schritt ist die Isolation genau eine Ebene tief: das Panel-Root benutzt seine
|
|
200
|
-
> Version, alles was ein Element in sein *eigenes* Shadow rendert, kommt aus der globalen —
|
|
201
|
-
> also aus der Version der Host-Seite. `enhance` kann das nicht beheben, sein
|
|
202
|
-
> MutationObserver endet an jeder Shadow-Grenze.
|
|
203
|
-
|
|
204
|
-
## Migrationsplan (phasenweise)
|
|
205
|
-
|
|
206
|
-
### Phase 1 — Additive Vorbereitung (non-breaking)
|
|
207
|
-
|
|
208
|
-
Ziel: alles vorbereiten, ohne bestehendes Verhalten zu ändern.
|
|
209
|
-
|
|
210
|
-
1. **`export default` überall garantieren** (fehlt nur in 3 Dateien).
|
|
211
|
-
Sekundär-Klassen mit exportieren:
|
|
212
|
-
```js
|
|
213
|
-
// el/calendar/calendar.js
|
|
214
|
-
export const extraElements = { 'u2-calendaritem': U2CalendarItem };
|
|
215
|
-
```
|
|
216
|
-
2. **`u2/define.js`** anlegen (siehe oben).
|
|
217
|
-
3. **Datei-Enden umstellen**: `customElements.define('u2-foo', U2Foo)` → `define('u2-foo', U2Foo)`.
|
|
218
|
-
Verhalten identisch (global), aber Registrierung läuft durch den Seam.
|
|
219
|
-
→ Codemod über die 44 Dateien.
|
|
220
|
-
4. **Interne Deps entkoppeln**: Side-Effect-Importe zwischen Elementen auf
|
|
221
|
-
`import Cls; define('u2-x', Cls)` umstellen. Dank Guard harmlos-redundant, aber schon
|
|
222
|
-
registry-agnostisch.
|
|
223
|
-
5. **`U2Auto`-Klasse** einführen; `auto.js` erzeugt die globale Default-Instanz
|
|
224
|
-
(`new U2Auto(document.documentElement)`) und registriert aus den Exports statt aus dem
|
|
225
|
-
Side-Effect.
|
|
226
|
-
|
|
227
|
-
Nach Phase 1: global unverändert, aber die gesamte Plumbing für scoped ist vorhanden.
|
|
228
|
-
|
|
229
|
-
### Phase 2 — Scoped-Betrieb ermöglichen
|
|
230
|
-
|
|
231
|
-
6. **Polyfill-Loader** + Feature-Detection einbauen.
|
|
232
|
-
7. **`attachU2Shadow(host)`** exportieren.
|
|
233
|
-
8. CMS-Panel: eigenes Shadow via `attachU2Shadow` erzeugen und dort die isolierte
|
|
234
|
-
u2-Instanz laufen lassen. Scoped werden nur die `u2-*`-Elemente; die eigenen Elemente
|
|
235
|
-
des Konsumenten bleiben global — sie haben eindeutige Namen, existieren in einer
|
|
236
|
-
Version, und der Host muss von aussen auffindbar bleiben.
|
|
237
|
-
|
|
238
|
-
### Phase 3 — Isolation scharf schalten (der einzige echte Break)
|
|
239
|
-
|
|
240
|
-
9. **Self-`define()` am Datei-Ende entfernen**, sodass ein direktes `import 'foo.js'`
|
|
241
|
-
nicht mehr registriert. Erst dann leakt nichts mehr global.
|
|
242
|
-
→ Ein-Zeilen-Codemod pro Datei; auto.js/U2Auto definieren zu dem Zeitpunkt längst selbst.
|
|
243
|
-
|
|
244
|
-
> **Ehrlicher Haken:** *volle* Isolation im Panel gibt es erst mit Phase 3. Solange die
|
|
245
|
-
> Dateien sich selbst global definieren, leakt jedes im Panel geladene Element in
|
|
246
|
-
> `window.customElements`. Phase 2 lässt sich aber komplett fertig testen; nur die
|
|
247
|
-
> Leak-Freiheit kommt zuletzt.
|
|
248
|
-
|
|
249
|
-
## Breaking Changes & Migrationsanweisungen
|
|
250
|
-
|
|
251
|
-
Erst ab **Phase 3** relevant:
|
|
252
|
-
|
|
253
|
-
1. **`import 'u2/el/foo/foo.js'` definiert das Element nicht mehr** — nur noch der Export
|
|
254
|
-
existiert. Grösster Bruch.
|
|
255
|
-
- *Migration:* entweder auto.js verwenden (keine Änderung nötig), oder manuell:
|
|
256
|
-
```js
|
|
257
|
-
import U2Foo from 'u2/el/foo/foo.js';
|
|
258
|
-
customElements.define('u2-foo', U2Foo); // bzw. define(...) aus u2/define.js
|
|
259
|
-
```
|
|
260
|
-
2. **Inter-Element-Side-Effect-Importe** greifen nicht mehr (bereits in Phase 1 auf
|
|
261
|
-
explizites `define()` umgestellt → kein Bruch, wenn Phase 1 gemacht wurde).
|
|
262
|
-
3. **`extraElements`** (calendaritem) muss explizit registriert werden (macht U2Auto).
|
|
263
|
-
|
|
264
|
-
## Offen / später
|
|
265
|
-
|
|
266
|
-
- **Die übrigen 36 Elemente auf `U2Element`.** Solange eines `extends HTMLElement` bleibt, fällt
|
|
267
|
-
sein Shadow auf `window.customElements` zurück, sobald es doch mal ein u2-Element rendert.
|
|
268
|
-
Mechanisch, aber 36 Dateien.
|
|
269
|
-
- **Attribute sind kein Registry-Problem.** Sie kollidieren nicht über Namen, sie
|
|
270
|
-
*installieren sich doppelt*, wenn zwei u2-Kopien laufen. Alle 10 hängen ihre Listener an
|
|
271
|
-
`document`, vier davon (`confirm`, `dropzone`, `draghandle`, `movable`) benutzen
|
|
272
|
-
`composedPath()` — sie arbeiten absichtlich über Shadow-Grenzen hinweg, und sie an einen
|
|
273
|
-
Scope zu binden würde sie kaputtmachen.
|
|
274
|
-
Zu klären ist deshalb nicht „wie scopen wir", sondern zweierlei: **einmal pro Dokument**
|
|
275
|
-
installieren, und **pro Modul** entscheiden, welche Wirkung wirklich subtree-lokal ist.
|
|
276
|
-
|
|
277
|
-
## Erledigt in 1.5.2 — `U2Element`
|
|
278
|
-
|
|
279
|
-
[`u2/Element.js`](Element.js): Basisklasse, die den Elementen die Registry-Arbeit abnimmt.
|
|
280
|
-
`attachShadow()` belegt `customElementRegistry: this.customElementRegistry` vor — alle
|
|
281
|
-
Aufrufstellen bleiben dadurch **wortgleich wie vorher**. `this.useEl(name)` importiert
|
|
282
|
-
`el/<name>/<name>.js` und definiert die Klasse in die eigene Registry (`?? customElements`).
|
|
283
|
-
Async ist unkritisch: ein Element upgraded auch, wenn es erst nach dem `innerHTML` definiert wird.
|
|
284
|
-
|
|
285
|
-
Dazu `useClass(name)` und `useAttr(name)`. Alle drei holen ausserdem die **CSS ins eigene Shadow** —
|
|
286
|
-
u2-Elemente haben meist kein eigenes Shadow (`ico` schreibt sein SVG ins Light DOM, `ico.css` stylt
|
|
287
|
-
`u2-ico { … }` von aussen), CSS gehört deshalb immer dem Root, in dem das Kind steht. Der Vater
|
|
288
|
-
musste sie bisher von Hand per `@import` holen, und `fields` vergass `responsive.css` dabei.
|
|
289
|
-
|
|
290
|
-
**Keine Deklaration am Kind.** Ein `static hasCss` müsste erst per JS geladen werden, bevor die CSS
|
|
291
|
-
überhaupt startet — es macht den wichtigeren Request garantiert langsamer. `projects.json` wäre
|
|
292
|
-
ebenfalls erst ein Fetch (und ist Enhance-Territorium). Also beides parallel, bedingungslos, und die
|
|
293
|
-
Defaults kommen aus der Kategorie — dieselben wie in `enhance`:
|
|
294
|
-
|
|
295
|
-
| | js | css | Dateien |
|
|
296
|
-
|---|---|---|---|
|
|
297
|
-
| `el` | ja | ja | js 41/41, css 37/41 |
|
|
298
|
-
| `class` | **nein** | ja | js 0/8, css 8/8 |
|
|
299
|
-
| `attr` | ja | **nein** | js 15/16, css 1/16 |
|
|
115
|
+
das **dokumentierte Installations-Snippet** ist — [`u2/tools/update.repos.json.js:159`](tools/update.repos.json.js#L159)
|
|
116
|
+
generiert es in jedes README. Neu wäre:
|
|
300
117
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
118
|
+
```html
|
|
119
|
+
<link href="…/el/buttongroup/buttongroup.css" rel=stylesheet>
|
|
120
|
+
<script type=module>
|
|
121
|
+
import U2Buttongroup from '…/el/buttongroup/buttongroup.js';
|
|
122
|
+
customElements.define('u2-buttongroup', U2Buttongroup);
|
|
123
|
+
</script>
|
|
124
|
+
```
|
|
304
125
|
|
|
305
|
-
|
|
306
|
-
Overrides des Vaters schlagen. `use()` macht darum `unshift`, nicht `push` — sobald der `<style>`
|
|
307
|
-
eines Vaters auch mal adoptiert wird, steht er hinter den Kindern, unabhängig davon, wann deren
|
|
308
|
-
Sheet eintrifft. Solange der Vater ein Tree-`<style>` hat, muss er die Kind-Regeln
|
|
309
|
-
**überspezifizieren**. Ein echter Fall bestand: `fields` überschrieb `u2-responsive {display:block}`
|
|
310
|
-
mit `u2-responsive {display:grid}` — Gleichstand, jetzt `#container`.
|
|
126
|
+
Das ist der geplante 1.6.0-Break: 41 Dateien, plus READMEs und SKILL.md neu generieren.
|
|
311
127
|
|
|
312
|
-
|
|
128
|
+
### 3. CSS-Reihenfolge — zwei Wege, der zweite ist besser
|
|
313
129
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
| `input` | `ico`, `bytes` |
|
|
318
|
-
| `fields` | `responsive` |
|
|
130
|
+
Adoptierte Sheets kommen **nach** den Tree-Styles. `use()` macht darum `unshift` statt `push` — der
|
|
131
|
+
Kind-Sheet landet vorne, egal wann er eintrifft. Solange ein Vater sein CSS aber als Tree-`<style>`
|
|
132
|
+
im `innerHTML` hat, gewinnt die Kind-CSS bei Gleichstand trotzdem.
|
|
319
133
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
134
|
+
Ein echter Fall bestand: `fields` überschrieb `u2-responsive {display:block}` mit `display:grid`,
|
|
135
|
+
Gleichstand — jetzt `#container`. Bei `alert` und `accordion` war die Eltern-Regel höher
|
|
136
|
+
spezifiziert, dort war nichts zu tun.
|
|
137
|
+
|
|
138
|
+
**Weg A — die sechs `<style>`-Blöcke adoptieren.** Dann bestimmt die Array-Reihenfolge
|
|
139
|
+
`[kind, eltern]` das Ergebnis statt der Spezifität. Zweiter Gewinn: ein Sheet auf Modulebene wird
|
|
140
|
+
einmal geparst statt einmal pro Instanz — heute parst ein `u2-alert` seinen Style-Block bei jeder
|
|
141
|
+
Instanz neu. Mechanisch, sechs Dateien, jede optisch nachzuprüfen.
|
|
142
|
+
|
|
143
|
+
**Weg B — Element-CSS in einen Layer legen.** `@layer u2.el { … }` in `ico.css` & Co. Ungelayerte
|
|
144
|
+
Regeln schlagen gelayerte **immer**, unabhängig von Spezifität und Reihenfolge. Damit gewinnt jeder
|
|
145
|
+
Vater automatisch, ohne `unshift`, ohne Umbau der sechs, ohne Spezifitäts-Nachrechnen — und
|
|
146
|
+
Anwender-Overrides werden allgemein einfacher statt schwerer. Bestehende Overrides brechen nicht:
|
|
147
|
+
sie sind heute ungelayert und werden dadurch stärker, nie schwächer.
|
|
148
|
+
|
|
149
|
+
Der Haken, den es wirklich gibt: **die Layer-Reihenfolge muss einmal deklariert werden.** u2 hat
|
|
150
|
+
schon `@layer normalize` in `base.css`/`norm.css`; kommt `u2.el` dazu, entscheidet die
|
|
151
|
+
Erstbegegnung — und `enhance` adoptiert asynchron. Die Antwort ist billig: `enhance` adoptiert als
|
|
152
|
+
allererstes ein Mini-Sheet mit `@layer u2.norm, u2.base, u2.el, u2.class;`. Danach ist die Ordnung
|
|
153
|
+
in jedem Root festgelegt, egal in welcher Reihenfolge die Sheets eintreffen.
|
|
154
|
+
|
|
155
|
+
Zweiter Haken, kleiner: `!important` kehrt die Layer-Reihenfolge um, und Anwender, deren *eigenes*
|
|
156
|
+
CSS gelayert ist, konkurrieren dann nach Layer-Ordnung statt nach „ungelayert schlägt gelayert".
|
|
157
|
+
Beides selten, beides dokumentierbar.
|
|
328
158
|
|
|
329
|
-
|
|
330
|
-
|
|
159
|
+
**Weg B macht Weg A überflüssig** — bis auf den Parse-Gewinn, der ein eigener, unabhängiger
|
|
160
|
+
Optimierungsschritt bleibt.
|
|
331
161
|
|
|
332
|
-
|
|
333
|
-
Registry-Thema; `table` erzeugt sein `u2-ico` im **Light DOM**, wo `enhance` es ohnehin sieht;
|
|
334
|
-
`input`s `u2-badge` ist eine *Klasse*, kein Tag; `tree`s `u2-ico` ist auskommentiert.
|
|
335
|
-
`U2CalendarItem` erbt `U2Element` mit, obwohl sein Shadow heute keine Custom Elements enthält.
|
|
162
|
+
### 4. Firefox
|
|
336
163
|
|
|
337
|
-
|
|
164
|
+
Ohne Scoped Registries fällt `enhance` auf `customElements` zurück und alles verhält sich wie
|
|
165
|
+
bisher — kein Fehler, aber auch keine Isolation. Fürs CMS-Panel bewusst als Voraussetzung gesetzt.
|
|
166
|
+
Wenn Firefox nachzieht, ist nichts zu tun.
|
package/u2/projects.json
CHANGED
|
@@ -196,6 +196,14 @@
|
|
|
196
196
|
}
|
|
197
197
|
},
|
|
198
198
|
"el": {
|
|
199
|
+
"rte0": {
|
|
200
|
+
"name": "rte0",
|
|
201
|
+
"description": "\"Rich\" Rich Text Editor (alpha)",
|
|
202
|
+
"beta": false,
|
|
203
|
+
"deprecated": false,
|
|
204
|
+
"css": true,
|
|
205
|
+
"js": true
|
|
206
|
+
},
|
|
199
207
|
"tabs": {
|
|
200
208
|
"name": "tabs",
|
|
201
209
|
"description": "Turns HTML structures with headings into an interactive, tabbed interface, using the content between headings as each tab’s content.",
|
|
@@ -278,7 +286,7 @@
|
|
|
278
286
|
},
|
|
279
287
|
"rte": {
|
|
280
288
|
"name": "rte",
|
|
281
|
-
"description": "
|
|
289
|
+
"description": "Progressively enhances one native textarea with the RTE rich-text editor",
|
|
282
290
|
"beta": false,
|
|
283
291
|
"deprecated": false,
|
|
284
292
|
"css": true,
|
|
@@ -560,6 +568,14 @@
|
|
|
560
568
|
}
|
|
561
569
|
},
|
|
562
570
|
"js": {
|
|
571
|
+
"rte0": {
|
|
572
|
+
"name": "rte0",
|
|
573
|
+
"description": "Easily Make Elements Editable with Intuitive Controls",
|
|
574
|
+
"beta": false,
|
|
575
|
+
"deprecated": false,
|
|
576
|
+
"css": false,
|
|
577
|
+
"js": false
|
|
578
|
+
},
|
|
563
579
|
"serviceWorker": {
|
|
564
580
|
"name": "serviceWorker",
|
|
565
581
|
"description": "",
|
|
@@ -586,7 +602,7 @@
|
|
|
586
602
|
},
|
|
587
603
|
"rte": {
|
|
588
604
|
"name": "rte",
|
|
589
|
-
"description": "
|
|
605
|
+
"description": "A modular rich-text editing engine for current browsers",
|
|
590
606
|
"beta": false,
|
|
591
607
|
"deprecated": false,
|
|
592
608
|
"css": false,
|
|
@@ -124,7 +124,7 @@ async function UsagePart(category, entry){
|
|
|
124
124
|
content += '```js\n'+dedent(js).trim()+'\n```\n\n';
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
let html = code.split(/<section[^>]*>/)[1]
|
|
127
|
+
let html = code.split(/<section[^>]*>/)?.[1]?.split?.('<\/section>')?.[0];
|
|
128
128
|
if (html) {
|
|
129
129
|
html = dedent(html);
|
|
130
130
|
content += '```html\n'+html+'\n```\n\n';
|
package/u2/utils.js
CHANGED
|
@@ -60,19 +60,3 @@ function rootGetStyleWrapper(root) {
|
|
|
60
60
|
return styleWrapper;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
///////////////////////////
|
|
65
|
-
// stylesheets
|
|
66
|
-
|
|
67
|
-
const sheets = new Map();
|
|
68
|
-
/** One parsed CSSStyleSheet per url, shared by every root that adopts it. */
|
|
69
|
-
export function sheet(url) {
|
|
70
|
-
if (!sheets.has(url)) {
|
|
71
|
-
sheets.set(url, fetch(url).then(r => r.text()).then(css => {
|
|
72
|
-
const s = new CSSStyleSheet();
|
|
73
|
-
s.replaceSync(css); // u2 css has no relative url() and no @import
|
|
74
|
-
return s;
|
|
75
|
-
}));
|
|
76
|
-
}
|
|
77
|
-
return sheets.get(url);
|
|
78
|
-
}
|
package/el/qrcode/package.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "u2-qrcode.el",
|
|
3
|
-
"version": "2.0.2",
|
|
4
|
-
"description": "qr-code element",
|
|
5
|
-
"main": "qrcode.js",
|
|
6
|
-
"author": "Tobias Buschor",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/u2ui/qrcode.el.git"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"ui",
|
|
14
|
-
],
|
|
15
|
-
"bugs": {
|
|
16
|
-
"url": "https://github.com/u2ui/qrcode.el/issues"
|
|
17
|
-
},
|
|
18
|
-
"homepage": "https://github.com/u2ui/qrcode.el#readme",
|
|
19
|
-
"scripts": {
|
|
20
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|