Skip to content

Commit f47c3ed

Browse files
authored
feat(js sdk): Allow element wrapping & test TG-280 (#435)
1 parent a5c402a commit f47c3ed

45 files changed

Lines changed: 44472 additions & 35800 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/core/jest.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module.exports = {
77
'<rootDir>/src/__testFixtures/*',
88
'/node_modules/*',
99
],
10-
modulePathIgnorePatterns: ['cypress'],
1110
moduleNameMapper: {
1211
'@testFixtures/(.*)': '<rootDir>/src/__testFixtures/$1',
1312
},

packages/core/src/Constants/Global.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export const RESTRICTED_ASCENDANT_ATTRIBUTE = 'data-tolgee-restricted';
22

33
export const TOLGEE_ATTRIBUTE_NAME = '_tolgee';
44
export const TOLGEE_TARGET_ATTRIBUTE = '_tolgee-target';
5+
export const TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE = 'data-tolgee-key-only';

packages/core/src/Tolgee.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import { EventEmitterImpl } from './services/EventEmitter';
55
import { DependencyStore } from './services/DependencyStore';
66

77
export class Tolgee {
8-
export;
9-
default;
10-
Tolgee;
118
private dependencyStore: DependencyStore;
129

1310
constructor(config: TolgeeConfig) {
@@ -46,6 +43,10 @@ export class Tolgee {
4643
return this.dependencyStore.eventService.LANGUAGE_CHANGED;
4744
}
4845

46+
public get onTranslationChange() {
47+
return this.dependencyStore.eventService.TRANSLATION_CHANGED;
48+
}
49+
4950
public get onLangLoaded() {
5051
return this.dependencyStore.eventService.LANGUAGE_LOADED;
5152
}

packages/core/src/handlers/AbstractHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export abstract class AbstractHandler {
2525
protected translationHighlighter: TranslationHighlighter
2626
) {}
2727

28-
private static initParentElement(element: Element): ElementWithMeta {
28+
protected static initParentElement(element: Element): ElementWithMeta {
2929
if (element[TOLGEE_ATTRIBUTE_NAME] === undefined) {
3030
element[TOLGEE_ATTRIBUTE_NAME] = {
3131
nodes: new Set(),

packages/core/src/handlers/CoreHandler.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Properties } from '../Properties';
66
import { AttributeHandler } from './AttributeHandler';
77
import { ElementWithMeta } from '../types';
88
import { TextService } from '../services/TextService';
9+
import { WrappedHandler } from './WrappedHandler';
910

1011
export class CoreHandler {
1112
constructor(
@@ -14,7 +15,8 @@ export class CoreHandler {
1415
private eventService: EventService,
1516
private properties: Properties,
1617
private attributeHandler: AttributeHandler,
17-
private textService: TextService
18+
private textService: TextService,
19+
private wrappedHandler: WrappedHandler
1820
) {
1921
eventService.LANGUAGE_CHANGED.subscribe(this.refresh.bind(this));
2022
eventService.TRANSLATION_CHANGED.subscribe(this.refresh.bind(this));
@@ -23,6 +25,7 @@ export class CoreHandler {
2325
public async handleSubtree(target: Element) {
2426
await this.attributeHandler.handle(target);
2527
await this.textHandler.handle(target);
28+
await this.wrappedHandler.handle(target);
2629
}
2730

2831
private async refresh() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { NodeHelper } from '../helpers/NodeHelper';
2+
import { Properties } from '../Properties';
3+
import { TranslationHighlighter } from '../highlighter/TranslationHighlighter';
4+
import { TextService } from '../services/TextService';
5+
import { AbstractHandler } from './AbstractHandler';
6+
import { ElementRegistrar } from '../services/ElementRegistrar';
7+
import { TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE } from '../Constants/Global';
8+
9+
export class WrappedHandler extends AbstractHandler {
10+
constructor(
11+
protected properties: Properties,
12+
protected translationHighlighter: TranslationHighlighter,
13+
protected textService: TextService,
14+
protected elementRegistrar: ElementRegistrar
15+
) {
16+
super(properties, textService, elementRegistrar, translationHighlighter);
17+
}
18+
19+
async handle(node: Node): Promise<void> {
20+
const xPath = `./descendant-or-self::*[@${TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE}]`;
21+
const nodes = NodeHelper.evaluate(xPath, node);
22+
const filtered: Element[] = this.filterRestricted(nodes as Element[]);
23+
filtered.forEach((element) => {
24+
const elementWithMeta = AbstractHandler.initParentElement(element);
25+
elementWithMeta._tolgee.wrappedWithElementOnlyKey = element.getAttribute(
26+
TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE
27+
);
28+
this.elementRegistrar.register(elementWithMeta);
29+
});
30+
}
31+
}

packages/core/src/highlighter/TranslationHighlighter.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import { TranslationService } from '../services/TranslationService';
66
import { MouseEventHandler } from './MouseEventHandler';
77

88
export class TranslationHighlighter {
9-
private _renderer: any;
10-
119
constructor(
1210
private service: CoreService,
1311
private properties: Properties,
@@ -16,6 +14,31 @@ export class TranslationHighlighter {
1614
private mouseEventHandler: MouseEventHandler
1715
) {}
1816

17+
private _renderer: any;
18+
19+
private get renderer() {
20+
if (this._renderer === undefined) {
21+
if (typeof this.properties.config.ui === 'function') {
22+
this._renderer = new this.properties.config.ui({
23+
coreService: this.service,
24+
properties: this.properties,
25+
eventService: this.eventService,
26+
translationService: this.translationService,
27+
});
28+
}
29+
}
30+
return this._renderer;
31+
}
32+
33+
private static getKeyOptions(node: ElementWithMeta): Set<string> {
34+
const nodes = Array.from(node._tolgee.nodes);
35+
const keys = nodes.reduce(
36+
(acc, curr) => [...acc, ...curr._tolgee.keys.map((k) => k.key)],
37+
[]
38+
);
39+
return new Set(keys);
40+
}
41+
1942
listen(element: ElementWithMeta & ElementCSSInlineStyle) {
2043
this.mouseEventHandler.handle(
2144
element,
@@ -27,6 +50,9 @@ export class TranslationHighlighter {
2750
mouseEvent: MouseEvent,
2851
element: ElementWithMeta
2952
): Promise<string> {
53+
if (element._tolgee.wrappedWithElementOnlyKey) {
54+
return element._tolgee.wrappedWithElementOnlyKey;
55+
}
3056
const keys = TranslationHighlighter.getKeyOptions(element);
3157
if (keys.size > 1) {
3258
return await this.renderer.getKey({ keys: keys, openEvent: mouseEvent });
@@ -38,15 +64,6 @@ export class TranslationHighlighter {
3864
console.error('No key to translate. This seems like a bug in tolgee.');
3965
}
4066

41-
private static getKeyOptions(node: ElementWithMeta): Set<string> {
42-
const nodes = Array.from(node._tolgee.nodes);
43-
const keys = nodes.reduce(
44-
(acc, curr) => [...acc, ...curr._tolgee.keys.map((k) => k.key)],
45-
[]
46-
);
47-
return new Set(keys);
48-
}
49-
5067
private translationEdit = async (e: MouseEvent, element: ElementWithMeta) => {
5168
if (typeof this.renderer === 'object') {
5269
const key = await this.getKey(e, element);
@@ -62,18 +79,4 @@ export class TranslationHighlighter {
6279
'To disable highlighting use production mode.'
6380
);
6481
};
65-
66-
private get renderer() {
67-
if (this._renderer === undefined) {
68-
if (typeof this.properties.config.ui === 'function') {
69-
this._renderer = new this.properties.config.ui({
70-
coreService: this.service,
71-
properties: this.properties,
72-
eventService: this.eventService,
73-
translationService: this.translationService,
74-
});
75-
}
76-
}
77-
return this._renderer;
78-
}
7982
}

packages/core/src/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { Tolgee } from './Tolgee';
22
import { TolgeeConfig } from './TolgeeConfig';
33
import { ModifierKey } from './Constants/ModifierKey';
4+
import { TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE } from './Constants/Global';
5+
import { TranslationData } from './DTOs/TranslationData';
46

5-
export { Tolgee, TolgeeConfig, ModifierKey };
7+
export {
8+
Tolgee,
9+
TolgeeConfig,
10+
ModifierKey,
11+
TOLGEE_WRAPPED_ONLY_DATA_ATTRIBUTE,
12+
TranslationData,
13+
};

packages/core/src/services/DependencyStore.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { CoreHandler } from '../handlers/CoreHandler';
1212
import { Observer } from '../Observer';
1313
import { CoreService } from './CoreService';
1414
import { TolgeeConfig } from '../TolgeeConfig';
15+
import { WrappedHandler } from '../handlers/WrappedHandler';
1516

1617
export class DependencyStore {
1718
public properties: Properties = new Properties();
@@ -55,13 +56,22 @@ export class DependencyStore {
5556
this.elementRegistrar,
5657
this.translationHighlighter
5758
);
59+
60+
public wrappedHandler = new WrappedHandler(
61+
this.properties,
62+
this.translationHighlighter,
63+
this.textService,
64+
this.elementRegistrar
65+
);
66+
5867
public coreHandler: CoreHandler = new CoreHandler(
5968
this.coreService,
6069
this.textHandler,
6170
this.eventService,
6271
this.properties,
6372
this.attributeHandler,
64-
this.textService
73+
this.textService,
74+
this.wrappedHandler
6575
);
6676
public observer: Observer = new Observer(
6777
this.properties,

packages/core/src/services/ElementRegistrar.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ export class ElementRegistrar {
1414

1515
register(element: ElementWithMeta) {
1616
//ignore element with no active nodes
17-
if (this.getActiveNodes(element).next().value === undefined) {
17+
if (
18+
this.getActiveNodes(element).next().value === undefined &&
19+
!element._tolgee.wrappedWithElementOnlyKey
20+
) {
1821
return;
1922
}
2023
if (
@@ -29,7 +32,10 @@ export class ElementRegistrar {
2932
refreshAll() {
3033
for (const element of this.registeredElements) {
3134
this.cleanElementInactiveNodes(element);
32-
if (element._tolgee.nodes.size === 0) {
35+
if (
36+
element._tolgee.nodes.size === 0 &&
37+
!element._tolgee.wrappedWithElementOnlyKey
38+
) {
3339
this.cleanElement(element);
3440
}
3541
}

0 commit comments

Comments
 (0)