@contentstorage/core 0.3.21 → 0.3.23

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.
@@ -16,3 +16,20 @@ export declare function setContentLanguage(contentJson: object): void;
16
16
  * @returns The text string from the JSON, or the fallbackValue, or undefined.
17
17
  */
18
18
  export declare function getText(pathString: keyof ContentStructure, fallbackValue?: string): string | undefined;
19
+ export declare class CsText extends HTMLElement {
20
+ private _id;
21
+ private _keyForGetText;
22
+ static get observedAttributes(): string[];
23
+ constructor();
24
+ connectedCallback(): void;
25
+ disconnectedCallback(): void;
26
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
27
+ get idKey(): string | null;
28
+ set idKey(value: string | null);
29
+ /**
30
+ * Handles cases where properties might be set on the element before it's upgraded.
31
+ * Ensures initial attribute values are processed.
32
+ */
33
+ private upgradeProperties;
34
+ private updateText;
35
+ }
@@ -43,22 +43,117 @@ pathString, fallbackValue) {
43
43
  // However, CustomContentStructure is initially `[key: string]: any` in the library,
44
44
  // so we might need a cast here if strict typing is desired for `value`.
45
45
  // But the consumer's augmentation makes CustomContentStructure specific.
46
- const value = activeContent[pathString]; // Using `as string` because keys are strings with dots.
47
- if (typeof value === 'string') {
48
- return value;
46
+ const keys = pathString.split('.');
47
+ let current = activeContent;
48
+ for (const key of keys) {
49
+ if (current && typeof current === 'object' && key in current) {
50
+ current = current[key];
51
+ }
52
+ else {
53
+ const msg = `[Contentstorage] getText: Path "${String(pathString)}" not found in loaded content.`;
54
+ console.warn(msg);
55
+ return fallbackValue;
56
+ }
57
+ }
58
+ if (typeof current === 'string') {
59
+ return current;
49
60
  }
50
61
  else {
51
- const msg = `[Contentstorage] getText: Value at key "${String(pathString)}" is not a string (actual type: ${typeof value}).'}'.`;
62
+ const msg = `[Contentstorage] getText: Value at path "${String(pathString)}" is not a string (actual type: ${typeof current}).`;
52
63
  console.warn(msg);
53
64
  return fallbackValue;
54
65
  }
55
66
  }
56
67
  else {
57
- // This case should ideally be caught by TypeScript if pathString is truly `keyof CustomContentStructure`
58
- // and the key doesn't exist, unless `activeContent` is out of sync with the types.
59
- // However, it's good for runtime robustness.
60
68
  const msg = `[Contentstorage] getText: Key "${String(pathString)}" not found in loaded content'.`;
61
69
  console.warn(msg);
62
70
  return fallbackValue;
63
71
  }
64
72
  }
73
+ // Ensure getText and potentially ContentStructure are imported or available in the scope.
74
+ // For this example, let's assume they are, along with activeContent.
75
+ // import { getText, ContentStructure, activeContent } from './contentStorage'; // Adjust path as needed
76
+ // Placeholder for ContentStructure if not already globally available for the cast
77
+ // This would ideally be the same ContentStructure interface your getText function uses.
78
+ export class CsText extends HTMLElement {
79
+ static get observedAttributes() {
80
+ // Define which attributes to observe for changes.
81
+ return ['data-contentstorage-id'];
82
+ }
83
+ constructor() {
84
+ super();
85
+ this._id = null;
86
+ // You can attach a Shadow DOM here if you need style encapsulation:
87
+ // this.attachShadow({ mode: 'open' });
88
+ // For simplicity, this example will manipulate the light DOM (this.textContent).
89
+ }
90
+ connectedCallback() {
91
+ // Called when the element is added to the document's DOM.
92
+ this.upgradeProperties();
93
+ this.updateText();
94
+ }
95
+ disconnectedCallback() {
96
+ // Called when the element is removed from the document's DOM.
97
+ // Perform any necessary cleanup here (e.g., remove event listeners if any were added).
98
+ }
99
+ attributeChangedCallback(name, oldValue, newValue) {
100
+ // Called when one of the observed attributes changes.
101
+ let shouldUpdate = false;
102
+ if (name === 'data-contentstorage-id' && oldValue !== newValue) {
103
+ this._id = newValue;
104
+ // Important: The string from the attribute needs to be treated as keyof ContentStructure.
105
+ // This cast assumes the provided ID string is a valid key.
106
+ // Runtime validation against available keys in `activeContent` could be added for robustness.
107
+ this._keyForGetText = newValue;
108
+ shouldUpdate = true;
109
+ }
110
+ if (shouldUpdate) {
111
+ this.updateText();
112
+ }
113
+ }
114
+ // Property getters/setters (optional, but good practice if you want to interact via JS properties)
115
+ get idKey() {
116
+ return this._id;
117
+ }
118
+ set idKey(value) {
119
+ this._id = value;
120
+ this._keyForGetText = value; // Cast here as well
121
+ if (value === null) {
122
+ this.removeAttribute('data-contentstorage-id');
123
+ }
124
+ else {
125
+ this.setAttribute('data-contentstorage-id', value);
126
+ }
127
+ // Note: setAttribute will trigger attributeChangedCallback if observed.
128
+ }
129
+ /**
130
+ * Handles cases where properties might be set on the element before it's upgraded.
131
+ * Ensures initial attribute values are processed.
132
+ */
133
+ upgradeProperties() {
134
+ // Check if properties were set before upgrade by checking attributes.
135
+ if (!this._id && this.hasAttribute('data-contentstorage-id')) {
136
+ this._id = this.getAttribute('data-contentstorage-id');
137
+ this._keyForGetText = this._id;
138
+ }
139
+ }
140
+ updateText() {
141
+ if (!this.isConnected) {
142
+ // Don't try to update if the element isn't in the DOM.
143
+ return;
144
+ }
145
+ if (this._keyForGetText) {
146
+ const textValue = getText(this._keyForGetText);
147
+ this.textContent = textValue !== undefined ? textValue : '';
148
+ }
149
+ else {
150
+ // No ID provided.
151
+ this.textContent = '';
152
+ }
153
+ }
154
+ }
155
+ // Define the custom element for the browser to use.
156
+ // Ensure this is called only once.
157
+ if (typeof window !== 'undefined' && !customElements.get('cs-text')) {
158
+ customElements.define('cs-text', CsText);
159
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@contentstorage/core",
3
3
  "author": "Kaido Hussar <kaidohus@gmail.com>",
4
4
  "homepage": "https://contentstorage.app",
5
- "version": "0.3.21",
5
+ "version": "0.3.23",
6
6
  "type": "module",
7
7
  "description": "Fetch content from contentstorage and generate TypeScript types",
8
8
  "module": "dist/index.js",
@@ -1,6 +0,0 @@
1
- import { AppConfig } from '../types.js';
2
- /**
3
- * Helper function to define your application configuration.
4
- * Provides autocompletion and type-checking for contentstorage.config.js files.
5
- */
6
- export declare function defineConfig(config: AppConfig): AppConfig;
@@ -1,19 +0,0 @@
1
- /**
2
- * Helper function to define your application configuration.
3
- * Provides autocompletion and type-checking for contentstorage.config.js files.
4
- */
5
- export function defineConfig(config) {
6
- // You can add basic runtime validation here if desired,
7
- // e.g., check if contentUrl is a valid URL format,
8
- // or if languageCodes is not empty.
9
- if (!config.languageCodes || config.languageCodes.length === 0) {
10
- console.warn('Warning: languageCodes array is empty or missing in the configuration.');
11
- }
12
- if (!config.contentDir) {
13
- // This would typically be a hard error, but defineConfig is more for type safety at edit time.
14
- // Runtime validation (see point 3) is better for hard errors.
15
- console.warn('Warning: contentDir is missing in the configuration.');
16
- }
17
- // ... other checks
18
- return config;
19
- }