neo.mjs 10.0.0-alpha.5 → 10.0.0-beta.2
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/ServiceWorker.mjs +2 -2
- package/apps/colors/view/GridContainer.mjs +1 -1
- package/apps/covid/view/AttributionComponent.mjs +1 -1
- package/apps/covid/view/HeaderContainer.mjs +6 -6
- package/apps/covid/view/MainContainerController.mjs +5 -5
- package/apps/covid/view/TableContainerController.mjs +1 -1
- package/apps/covid/view/country/Gallery.mjs +13 -13
- package/apps/covid/view/country/Helix.mjs +13 -13
- package/apps/covid/view/country/HistoricalDataTable.mjs +1 -1
- package/apps/email/view/Viewport.mjs +2 -2
- package/apps/form/view/SideNavList.mjs +1 -1
- package/apps/portal/index.html +1 -1
- package/apps/portal/resources/data/examples_devmode.json +26 -27
- package/apps/portal/resources/data/examples_dist_dev.json +26 -27
- package/apps/portal/resources/data/examples_dist_esm.json +25 -26
- package/apps/portal/resources/data/examples_dist_prod.json +26 -27
- package/apps/portal/view/HeaderToolbar.mjs +3 -3
- package/apps/portal/view/about/Container.mjs +2 -2
- package/apps/portal/view/about/MemberContainer.mjs +3 -3
- package/apps/portal/view/blog/List.mjs +7 -7
- package/apps/portal/view/examples/List.mjs +4 -4
- package/apps/portal/view/home/ContentBox.mjs +2 -2
- package/apps/portal/view/home/FeatureSection.mjs +3 -3
- package/apps/portal/view/home/FooterContainer.mjs +7 -7
- package/apps/portal/view/home/parts/AfterMath.mjs +3 -3
- package/apps/portal/view/home/parts/MainNeo.mjs +3 -3
- package/apps/portal/view/home/parts/References.mjs +6 -6
- package/apps/portal/view/learn/ContentComponent.mjs +102 -111
- package/apps/portal/view/learn/PageSectionsContainer.mjs +1 -1
- package/apps/portal/view/learn/PageSectionsList.mjs +2 -2
- package/apps/portal/view/services/Component.mjs +16 -16
- package/apps/realworld/view/FooterComponent.mjs +1 -1
- package/apps/realworld/view/HeaderComponent.mjs +8 -8
- package/apps/realworld/view/HomeComponent.mjs +6 -6
- package/apps/realworld/view/article/CommentComponent.mjs +4 -4
- package/apps/realworld/view/article/Component.mjs +14 -14
- package/apps/realworld/view/article/CreateCommentComponent.mjs +3 -3
- package/apps/realworld/view/article/CreateComponent.mjs +3 -3
- package/apps/realworld/view/article/PreviewComponent.mjs +1 -1
- package/apps/realworld/view/article/TagListComponent.mjs +2 -2
- package/apps/realworld/view/user/ProfileComponent.mjs +8 -8
- package/apps/realworld/view/user/SettingsComponent.mjs +4 -4
- package/apps/realworld/view/user/SignUpComponent.mjs +4 -4
- package/apps/realworld2/view/FooterComponent.mjs +1 -1
- package/apps/realworld2/view/HomeContainer.mjs +3 -3
- package/apps/realworld2/view/article/DetailsContainer.mjs +1 -1
- package/apps/realworld2/view/article/PreviewComponent.mjs +7 -7
- package/apps/realworld2/view/article/TagListComponent.mjs +2 -2
- package/apps/realworld2/view/user/ProfileContainer.mjs +1 -1
- package/apps/route/view/center/CardAdministration.mjs +2 -2
- package/apps/route/view/center/CardAdministrationDenied.mjs +1 -1
- package/apps/route/view/center/CardContact.mjs +2 -2
- package/apps/route/view/center/CardHome.mjs +1 -1
- package/apps/route/view/center/CardSection1.mjs +1 -1
- package/apps/route/view/center/CardSection2.mjs +1 -1
- package/apps/sharedcovid/view/AttributionComponent.mjs +1 -1
- package/apps/sharedcovid/view/HeaderContainer.mjs +6 -6
- package/apps/sharedcovid/view/MainContainerController.mjs +5 -5
- package/apps/sharedcovid/view/TableContainerController.mjs +1 -1
- package/apps/sharedcovid/view/country/Gallery.mjs +13 -13
- package/apps/sharedcovid/view/country/Helix.mjs +13 -13
- package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -1
- package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +1 -1
- package/apps/shareddialog/view/MainContainer.mjs +1 -1
- package/buildScripts/createApp.mjs +2 -2
- package/examples/table/cellEditing/MainContainer.mjs +1 -1
- package/examples/table/container/MainContainer.mjs +3 -3
- package/examples/table/nestedRecordFields/Viewport.mjs +6 -6
- package/examples/tableFiltering/MainContainer.mjs +1 -1
- package/examples/tablePerformance/MainContainer.mjs +1 -1
- package/examples/tablePerformance/MainContainer2.mjs +1 -1
- package/examples/tablePerformance/MainContainer3.mjs +2 -2
- package/examples/tableStore/MainContainer.mjs +2 -2
- package/learn/Glossary.md +261 -0
- package/learn/UsingTheseTopics.md +2 -2
- package/learn/benefits/ConfigSystem.md +538 -28
- package/learn/benefits/Effort.md +47 -2
- package/learn/benefits/Features.md +50 -32
- package/learn/benefits/FormsEngine.md +68 -38
- package/learn/benefits/MultiWindow.md +33 -7
- package/learn/benefits/OffTheMainThread.md +2 -2
- package/learn/benefits/Quick.md +45 -12
- package/learn/benefits/RPCLayer.md +75 -0
- package/learn/benefits/Speed.md +16 -11
- package/learn/gettingstarted/ComponentModels.md +4 -4
- package/learn/gettingstarted/Config.md +6 -6
- package/learn/gettingstarted/DescribingTheUI.md +4 -4
- package/learn/gettingstarted/Events.md +6 -6
- package/learn/gettingstarted/Extending.md +4 -4
- package/learn/gettingstarted/References.md +6 -6
- package/learn/gettingstarted/Workspaces.md +6 -6
- package/learn/guides/ApplicationBootstrap.md +26 -26
- package/learn/guides/ComponentsAndContainers.md +12 -12
- package/learn/guides/ConfigSystemDeepDive.md +280 -0
- package/learn/guides/CustomComponents.md +2 -2
- package/learn/guides/DeclarativeComponentTreesVsImperativeVdom.md +17 -17
- package/learn/guides/InstanceLifecycle.md +295 -1
- package/learn/guides/MainThreadAddons.md +475 -0
- package/learn/guides/PortalApp.md +2 -2
- package/learn/guides/StateProviders.md +12 -12
- package/learn/guides/WorkingWithVDom.md +14 -14
- package/learn/guides/events/CustomEvents.md +16 -16
- package/learn/guides/events/DomEvents.md +12 -12
- package/learn/javascript/ClassFeatures.md +3 -2
- package/learn/javascript/Classes.md +8 -8
- package/learn/javascript/NewNode.md +4 -4
- package/learn/javascript/Overrides.md +8 -8
- package/learn/javascript/Super.md +10 -8
- package/learn/tree.json +52 -51
- package/learn/tutorials/Earthquakes.md +54 -57
- package/learn/tutorials/TodoList.md +4 -4
- package/package.json +2 -2
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +12 -0
- package/resources/scss/src/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/src/table/plugin/CellEditing.scss +1 -1
- package/resources/scss/theme-dark/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-light/table/{View.scss → Body.scss} +1 -1
- package/resources/scss/theme-neo-light/Global.scss +1 -2
- package/resources/scss/theme-neo-light/table/{View.scss → Body.scss} +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/Main.mjs +8 -7
- package/src/Neo.mjs +16 -2
- package/src/button/Base.mjs +2 -2
- package/src/calendar/view/SettingsContainer.mjs +2 -2
- package/src/calendar/view/YearComponent.mjs +9 -9
- package/src/calendar/view/calendars/ColorsList.mjs +1 -1
- package/src/calendar/view/calendars/List.mjs +1 -1
- package/src/calendar/view/month/Component.mjs +15 -15
- package/src/calendar/view/week/Component.mjs +12 -12
- package/src/calendar/view/week/EventDragZone.mjs +4 -4
- package/src/calendar/view/week/TimeAxisComponent.mjs +3 -3
- package/src/component/Base.mjs +17 -2
- package/src/component/Carousel.mjs +2 -2
- package/src/component/Chip.mjs +3 -3
- package/src/component/Circle.mjs +2 -2
- package/src/component/DateSelector.mjs +8 -8
- package/src/component/Helix.mjs +1 -1
- package/src/component/Label.mjs +3 -18
- package/src/component/Legend.mjs +3 -3
- package/src/component/MagicMoveText.mjs +6 -14
- package/src/component/Process.mjs +3 -3
- package/src/component/Progress.mjs +1 -1
- package/src/component/StatusBadge.mjs +2 -2
- package/src/component/Timer.mjs +2 -2
- package/src/component/Toast.mjs +5 -3
- package/src/container/AccordionItem.mjs +2 -2
- package/src/container/Base.mjs +1 -1
- package/src/core/Base.mjs +77 -14
- package/src/core/Util.mjs +14 -2
- package/src/date/DayViewComponent.mjs +2 -2
- package/src/date/SelectorContainer.mjs +1 -1
- package/src/draggable/grid/header/toolbar/SortZone.mjs +21 -21
- package/src/draggable/table/header/toolbar/SortZone.mjs +1 -1
- package/src/form/field/CheckBox.mjs +4 -4
- package/src/form/field/FileUpload.mjs +25 -39
- package/src/form/field/Range.mjs +1 -1
- package/src/form/field/Text.mjs +3 -3
- package/src/form/field/TextArea.mjs +2 -3
- package/src/grid/Body.mjs +8 -5
- package/src/grid/_export.mjs +1 -1
- package/src/list/Color.mjs +2 -2
- package/src/main/DeltaUpdates.mjs +157 -98
- package/src/main/addon/AmCharts.mjs +61 -84
- package/src/main/addon/Base.mjs +161 -42
- package/src/main/addon/GoogleMaps.mjs +9 -16
- package/src/main/addon/HighlightJS.mjs +2 -13
- package/src/main/addon/IntersectionObserver.mjs +21 -21
- package/src/main/addon/MonacoEditor.mjs +32 -64
- package/src/manager/ClassHierarchy.mjs +114 -0
- package/src/menu/List.mjs +1 -1
- package/src/plugin/Popover.mjs +2 -2
- package/src/sitemap/Component.mjs +1 -1
- package/src/table/{View.mjs → Body.mjs} +25 -22
- package/src/table/Container.mjs +43 -43
- package/src/table/_export.mjs +2 -2
- package/src/table/plugin/CellEditing.mjs +19 -19
- package/src/tooltip/Base.mjs +1 -6
- package/src/tree/Accordion.mjs +3 -3
- package/src/vdom/Helper.mjs +19 -22
- package/src/worker/App.mjs +1 -2
- package/src/worker/Base.mjs +7 -5
- package/src/worker/Canvas.mjs +2 -3
- package/src/worker/Data.mjs +5 -7
- package/src/worker/Task.mjs +2 -3
- package/src/worker/VDom.mjs +3 -4
- package/src/worker/mixin/RemoteMethodAccess.mjs +5 -2
- package/learn/guides/MainThreadAddonExample.md +0 -15
- package/learn/guides/MainThreadAddonIntro.md +0 -44
@@ -5,9 +5,9 @@ import {marked} from '../../../../node_modules/marked/lib/marked.esm.js';
|
|
5
5
|
const
|
6
6
|
labCloseRegex = /<!--\s*\/lab\s*-->/g,
|
7
7
|
labOpenRegex = /<!--\s*lab\s*-->/g,
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
regexLivePreview = /```(javascript|html|css|json)\s+live-preview\s*\n([\s\S]*?)\n\s*```/g,
|
9
|
+
regexNeoComponent = /```json\s+neo-component\s*\n([\s\S]*?)\n\s*```/g,
|
10
|
+
regexReadonly = /```(javascript|html|css|json)\s+readonly\s*\n([\s\S]*?)\n\s*```/g;
|
11
11
|
|
12
12
|
/**
|
13
13
|
* @class Portal.view.learn.ContentComponent
|
@@ -164,48 +164,48 @@ class ContentComponent extends Component {
|
|
164
164
|
{appName, windowId} = me,
|
165
165
|
path = me.getStateProvider().getData('contentPath'),
|
166
166
|
pagesFolder = path.includes('/learn/') ? '' : 'pages/',
|
167
|
-
baseConfigs, content, data, html, instance,
|
167
|
+
baseConfigs, content, data, html, instance, neoComponents, neoDivs;
|
168
168
|
|
169
169
|
path += `${pagesFolder + record.id.replaceAll('.', '/')}.md`;
|
170
170
|
|
171
171
|
if (record.isLeaf && path) {
|
172
|
-
baseConfigs
|
173
|
-
data
|
174
|
-
content
|
175
|
-
|
176
|
-
content
|
177
|
-
|
172
|
+
baseConfigs = {appName, autoMount: true, autoRender: true, parentComponent: me, windowId};
|
173
|
+
data = await fetch(path);
|
174
|
+
content = await data.text();
|
175
|
+
// Update content sections (modifies markdown content with h2/h3 tags and IDs)
|
176
|
+
content = me.updateContentSectionsStore(content);
|
177
|
+
content = `<h1 class='neo-h1'>${record.name}</h1>\n${content}`;
|
178
|
+
// Initialize maps for custom components and live previews
|
178
179
|
neoComponents = {};
|
179
180
|
neoDivs = {};
|
180
|
-
|
181
|
-
|
182
|
-
//
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
//
|
188
|
-
//
|
189
|
-
|
190
|
-
|
191
|
-
html =
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
me.html = html;
|
181
|
+
// Process custom Neo.mjs component blocks (synchronous)
|
182
|
+
content = me.processNeoComponentsBlocks(content, neoComponents);
|
183
|
+
// Process custom Live Preview blocks (synchronous)
|
184
|
+
content = me.processLivePreviewBlocks(content, neoDivs);
|
185
|
+
// Process custom Readonly Code blocks (asynchronous due to HighlightJS)
|
186
|
+
// This will replace the markdown fenced block with the highlighted HTML <pre> tag.
|
187
|
+
content = await me.processReadonlyCodeBlocks(content, windowId);
|
188
|
+
// Parse the (now modified) markdown content into HTML
|
189
|
+
// This content string now contains standard markdown PLUS the HTML divs/pres we injected.
|
190
|
+
html = marked.parse(content);
|
191
|
+
// Insert lab divs (these are markdown comments, so process on the final HTML)
|
192
|
+
html = me.insertLabDivs(html); // Keep existing method
|
193
|
+
|
194
|
+
me.toggleCls('lab', record.name?.startsWith('Lab:')); // Keep existing method
|
195
|
+
|
196
|
+
me.html = html; // Set the component's HTML
|
197
197
|
|
198
198
|
await me.timeout(Neo.config.environment === 'development' ? 100 : 150);
|
199
199
|
|
200
|
+
// Create instances for custom components and live previews (keep existing logic)
|
200
201
|
Object.keys(neoComponents).forEach(key => {
|
201
202
|
instance = Neo.create({
|
202
203
|
...baseConfigs,
|
203
|
-
className: 'Neo.component.Base',
|
204
|
+
className: 'Neo.component.Base', // Adjust if specific component classes are implied by JSON
|
204
205
|
parentId : key,
|
205
206
|
...neoComponents[key]
|
206
207
|
});
|
207
|
-
|
208
|
-
me.customComponents.push(instance)
|
208
|
+
me.customComponents.push(instance);
|
209
209
|
});
|
210
210
|
|
211
211
|
Object.keys(neoDivs).forEach(key => {
|
@@ -213,10 +213,9 @@ class ContentComponent extends Component {
|
|
213
213
|
...baseConfigs,
|
214
214
|
module : LivePreview,
|
215
215
|
parentId: key,
|
216
|
-
value : neoDivs[key]
|
216
|
+
value : neoDivs[key].code // Pass the extracted code content
|
217
217
|
});
|
218
|
-
|
219
|
-
me.livePreviews.push(instance)
|
218
|
+
me.livePreviews.push(instance);
|
220
219
|
});
|
221
220
|
|
222
221
|
Neo.main.addon.IntersectionObserver.observe({
|
@@ -224,87 +223,10 @@ class ContentComponent extends Component {
|
|
224
223
|
id : me.id,
|
225
224
|
observe : ['.neo-h2', '.neo-h3'],
|
226
225
|
windowId : me.windowId
|
227
|
-
})
|
226
|
+
});
|
228
227
|
}
|
229
228
|
}
|
230
229
|
|
231
|
-
/**
|
232
|
-
* @param {String} htmlString
|
233
|
-
* @param {Object} map
|
234
|
-
* @returns {String}
|
235
|
-
*/
|
236
|
-
extractNeoComponents(htmlString, map) {
|
237
|
-
// 1. Replace <pre data-neo-component> with <div id='neo-learn-content-component-x'/>
|
238
|
-
// and update map with key/value pairs, where the key is the ID and the value is the <pre> contents.
|
239
|
-
// Replace the content with tokens, and create a promise to update the corresponding content
|
240
|
-
return htmlString.replace(preNeoComponentRegex, (match, preContent) => {
|
241
|
-
const key = Neo.core.IdGenerator.getId('learn-content-component');
|
242
|
-
map[key] = JSON.parse(preContent);
|
243
|
-
return `<div id="${key}"></div>`
|
244
|
-
})
|
245
|
-
}
|
246
|
-
|
247
|
-
/**
|
248
|
-
* @param {String} htmlString
|
249
|
-
* @param {Object} map
|
250
|
-
* @returns {String}
|
251
|
-
*/
|
252
|
-
extractLivePreviewContent(htmlString, map) {
|
253
|
-
// 1. Replace <pre data-neo> with <div id='neo-pre-live-preview-x'/>
|
254
|
-
// and update map with key/value pairs, where the key is the ID and the value is the <pre> contents.
|
255
|
-
// Replace the content with tokens, and create a promise to update the corresponding content
|
256
|
-
return htmlString.replace(preLivePreviewRegex, (match, preContent) => {
|
257
|
-
const key = Neo.core.IdGenerator.getId('pre-live-preview');
|
258
|
-
map[key] = preContent;
|
259
|
-
return `<div id="${key}"></div>`
|
260
|
-
})
|
261
|
-
}
|
262
|
-
|
263
|
-
/**
|
264
|
-
* @param preContent
|
265
|
-
* @param token
|
266
|
-
* @param id
|
267
|
-
* @returns {Object}
|
268
|
-
*/
|
269
|
-
getHighlightPromise(preContent, token, id) {
|
270
|
-
// Resolves to an object of the form {after, token}, where after is the updated <pre> tag content
|
271
|
-
return Neo.main.addon.HighlightJS.highlightAuto({html: preContent, windowId: this.windowId})
|
272
|
-
.then(value => ({after: `<pre data-javascript id="${id}">${value}</pre>`, token}))
|
273
|
-
}
|
274
|
-
|
275
|
-
/**
|
276
|
-
* @param {String} htmlString
|
277
|
-
* @returns {Promise<*>}
|
278
|
-
*/
|
279
|
-
async highlightPreContent(htmlString) {
|
280
|
-
// 1. Replace <pre data-javascript> with unique tokens and create a HighlightJS.highlightAuto promise for each
|
281
|
-
// 2. When all promises are resolved, use their values to replace the tokens.
|
282
|
-
|
283
|
-
// Note that if we were to import HighlightJS directly, we wouldn't need all this async code.
|
284
|
-
|
285
|
-
// Create an array to store promises for each replacement
|
286
|
-
const replacementPromises = [];
|
287
|
-
let count = 0;
|
288
|
-
|
289
|
-
// Replace the content with tokens, and create a promise to update the corresponding content
|
290
|
-
let updatedHtml = htmlString.replace(preJsRegex, (match, preContent) => {
|
291
|
-
const token = `__NEO-PRE-TOKEN-${++count}__`;
|
292
|
-
replacementPromises.push(this.getHighlightPromise(preContent, token, `pre-preview-${Neo.core.IdGenerator.getId()}`));
|
293
|
-
return token
|
294
|
-
});
|
295
|
-
|
296
|
-
// Assert: updateHtml is the original, but with <pre data-javascript> replaced with tokens.
|
297
|
-
|
298
|
-
// Wait for all replacement promises to resolve
|
299
|
-
let replacements = await Promise.all(replacementPromises)
|
300
|
-
|
301
|
-
// Replace each token with the resolved content
|
302
|
-
replacements.forEach((replacement) => updatedHtml = updatedHtml.replace(replacement.token, replacement.after));
|
303
|
-
|
304
|
-
// Return the final updated HTML string
|
305
|
-
return updatedHtml
|
306
|
-
}
|
307
|
-
|
308
230
|
/**
|
309
231
|
* @param {String} inputString
|
310
232
|
* @returns {String}
|
@@ -335,6 +257,75 @@ class ContentComponent extends Component {
|
|
335
257
|
}
|
336
258
|
}
|
337
259
|
|
260
|
+
/**
|
261
|
+
* Extracts live preview code blocks from Markdown content before marked.js parsing.
|
262
|
+
* Replaces them with HTML placeholders.
|
263
|
+
* @param {String} contentString The raw Markdown content string.
|
264
|
+
* @param {Object} map A map to store the extracted code content keyed by placeholder ID.
|
265
|
+
* @returns {String} The modified Markdown content string with placeholders.
|
266
|
+
*/
|
267
|
+
processLivePreviewBlocks(contentString, map) {
|
268
|
+
return contentString.replace(regexLivePreview, (match, language, code) => {
|
269
|
+
const key = Neo.core.IdGenerator.getId('pre-live-preview');
|
270
|
+
map[key] = {code, language};
|
271
|
+
return `<div id="${key}"></div>`
|
272
|
+
})
|
273
|
+
}
|
274
|
+
|
275
|
+
/**
|
276
|
+
* Extracts Neo.mjs component config blocks from Markdown content before marked.js parsing.
|
277
|
+
* Replaces them with HTML placeholders.
|
278
|
+
* @param {String} contentString The raw Markdown content string.
|
279
|
+
* @param {Object} map A map to store the extracted JSON config keyed by placeholder ID.
|
280
|
+
* @returns {String} The modified Markdown content string with placeholders.
|
281
|
+
*/
|
282
|
+
processNeoComponentsBlocks(contentString, map) {
|
283
|
+
return contentString.replace(regexNeoComponent, (match, code) => {
|
284
|
+
const key = Neo.core.IdGenerator.getId('learn-content-component');
|
285
|
+
map[key] = JSON.parse(code);
|
286
|
+
return `<div id="${key}"></div>`
|
287
|
+
})
|
288
|
+
}
|
289
|
+
|
290
|
+
/**
|
291
|
+
* Highlights readonly code blocks using HighlightJS.
|
292
|
+
* Replaces the Markdown fenced block with the highlighted HTML <pre> tag.
|
293
|
+
* @param {String} contentString The raw Markdown content string.
|
294
|
+
* @param {String} windowId The ID of the current window for HighlightJS.
|
295
|
+
* @returns {Promise<String>} A promise that resolves to the modified Markdown string with highlighted HTML.
|
296
|
+
*/
|
297
|
+
async processReadonlyCodeBlocks(contentString, windowId) {
|
298
|
+
let replacementPromises = [],
|
299
|
+
count = 0,
|
300
|
+
replacements;
|
301
|
+
|
302
|
+
// Replace the content with tokens, and create a promise to update the corresponding content
|
303
|
+
let updatedContent = contentString.replace(regexReadonly, (match, language, code) => {
|
304
|
+
const token = `__NEO-READONLY-TOKEN-${++count}__`;
|
305
|
+
// Call HighlightJS.highlightAuto for each block.
|
306
|
+
// The result will be HTML. We'll wrap it in a <pre data-javascript> later.
|
307
|
+
replacementPromises.push(
|
308
|
+
Neo.main.addon.HighlightJS.highlightAuto({html: code, windowId})
|
309
|
+
.then(highlightedHtml => ({
|
310
|
+
after: `<pre data-javascript id="pre-readonly-${Neo.core.IdGenerator.getId()}">${highlightedHtml}</pre>`,
|
311
|
+
token: token
|
312
|
+
}))
|
313
|
+
);
|
314
|
+
|
315
|
+
return token; // Replace the original Markdown block with a temporary token
|
316
|
+
});
|
317
|
+
|
318
|
+
// Wait for all highlighting promises to resolve
|
319
|
+
replacements = await Promise.all(replacementPromises);
|
320
|
+
|
321
|
+
// Replace each token with the resolved highlighted HTML content
|
322
|
+
replacements.forEach(replacement => {
|
323
|
+
updatedContent = updatedContent.replace(replacement.token, replacement.after)
|
324
|
+
});
|
325
|
+
|
326
|
+
return updatedContent
|
327
|
+
}
|
328
|
+
|
338
329
|
/**
|
339
330
|
* Updates the contentSections VM store and replaces ## with h2 tags
|
340
331
|
* @param {String} content
|
@@ -32,12 +32,12 @@ class PageSectionsList extends List {
|
|
32
32
|
/**
|
33
33
|
* @param {Object} record
|
34
34
|
* @param {Number} index
|
35
|
-
* @returns {Object|Object[]|String} Either a config object to assign to the item, a vdom cn array or a
|
35
|
+
* @returns {Object|Object[]|String} Either a config object to assign to the item, a vdom cn array or a string.
|
36
36
|
*/
|
37
37
|
createItemContent(record, index) {
|
38
38
|
return {
|
39
39
|
cls : `neo-${record.tag}`,
|
40
|
-
|
40
|
+
text: record[this.displayField]
|
41
41
|
}
|
42
42
|
}
|
43
43
|
|
@@ -20,36 +20,36 @@ class Component extends BaseComponent {
|
|
20
20
|
*/
|
21
21
|
vdom:
|
22
22
|
{cn: [
|
23
|
-
{tag: 'h1', cls: ['neo-h1'],
|
23
|
+
{tag: 'h1', cls: ['neo-h1'], text: 'Services'},
|
24
24
|
{cls: ['info-block'], cn: [
|
25
|
-
{tag: 'h2', cls: ['neo-h2'],
|
26
|
-
{tag: 'p',
|
25
|
+
{tag: 'h2', cls: ['neo-h2'], text: 'Professional Trainings'},
|
26
|
+
{tag: 'p', text: [
|
27
27
|
'While we do have a self-study based Learning Section online, you can also hire us ',
|
28
28
|
'in case you prefer an Instructor-led Training for bringing your team up to speed.'
|
29
29
|
].join('')},
|
30
30
|
{tag: 'ul', cn: [
|
31
|
-
{tag: 'li',
|
32
|
-
{tag: 'li',
|
33
|
-
{tag: 'li',
|
34
|
-
{tag: 'li',
|
31
|
+
{tag: 'li', text: 'One week packed with 40h of intense training.'},
|
32
|
+
{tag: 'li', text: 'Including hands-on Labs'},
|
33
|
+
{tag: 'li', text: '6 - 12 attendees'},
|
34
|
+
{tag: 'li', text: 'While Remote Trainings are possible, we strongly recommend On-Site Trainings instead.'},
|
35
35
|
]},
|
36
36
|
{tag: 'p', html: [
|
37
37
|
'Feel free to send us an <a href="mailto:trainings@neomjs.com">Email</a> to plan your training timeframe.',
|
38
38
|
].join('')},
|
39
39
|
]},
|
40
40
|
{cls: ['info-block'], cn: [
|
41
|
-
{tag: 'h2', cls: ['neo-h2'],
|
42
|
-
{tag: 'p',
|
41
|
+
{tag: 'h2', cls: ['neo-h2'], text: 'Professional Services'},
|
42
|
+
{tag: 'p', text: [
|
43
43
|
'We can help you to ensure your Neo.mjs based projects run successfully.',
|
44
44
|
].join('')},
|
45
45
|
{tag: 'ul', cn: [
|
46
|
-
{tag: 'li',
|
47
|
-
{tag: 'li',
|
48
|
-
{tag: 'li',
|
49
|
-
{tag: 'li',
|
50
|
-
{tag: 'li',
|
51
|
-
{tag: 'li',
|
52
|
-
{tag: 'li',
|
46
|
+
{tag: 'li', text: 'Feasibility Analysis: Is Neo.mjs a good fit for your project needs?'},
|
47
|
+
{tag: 'li', text: 'Creating a Neo.mjs PoC which matches your specific needs'},
|
48
|
+
{tag: 'li', text: 'Code Reviews'},
|
49
|
+
{tag: 'li', text: 'Frontend-Architecture Guidance'},
|
50
|
+
{tag: 'li', text: 'Application & Framework Debugging'},
|
51
|
+
{tag: 'li', text: 'Creation of Custom Components, Design Themes & new Features'},
|
52
|
+
{tag: 'li', text: 'Hands-On Application Development Support'}
|
53
53
|
]},
|
54
54
|
{tag: 'p', html: [
|
55
55
|
'In case you need help, send us an <a href="mailto:services@neomjs.com">Email</a>.',
|
@@ -17,7 +17,7 @@ class FooterComponent extends Component {
|
|
17
17
|
_vdom:
|
18
18
|
{tag: 'footer', cn: [
|
19
19
|
{cls: ['container'], cn: [
|
20
|
-
{tag: 'a', cls: ['logo-font'], href: '#/',
|
20
|
+
{tag: 'a', cls: ['logo-font'], href: '#/', text: 'conduit'},
|
21
21
|
{tag: 'span', cls: 'attribution', html: 'An interactive learning project from <a href="https://thinkster.io">Thinkster</a>. Code & design licensed under MIT.'}
|
22
22
|
]}
|
23
23
|
]}
|
@@ -38,34 +38,34 @@ class HeaderComponent extends Component {
|
|
38
38
|
_vdom:
|
39
39
|
{tag: 'nav', cls: ['navbar navbar-light'], cn: [
|
40
40
|
{cls: ['container'], cn: [
|
41
|
-
{tag: 'a', cls: ['navbar-brand'], href: '#/',
|
41
|
+
{tag: 'a', cls: ['navbar-brand'], href: '#/', text: 'conduit'},
|
42
42
|
{tag: 'ul', cls: ['nav navbar-nav', 'pull-xs-right'], cn: [
|
43
43
|
{tag: 'li', cls: ['nav-item'], cn: [
|
44
|
-
{tag: 'a', cls: ['nav-link'], href: '#/',
|
44
|
+
{tag: 'a', cls: ['nav-link'], href: '#/', text: 'Home'}
|
45
45
|
]},
|
46
46
|
{tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
|
47
47
|
{tag: 'a', cls: ['nav-link'], href: '#/editor', cn: [
|
48
48
|
{tag: 'i', cls: 'ion-compose'},
|
49
|
-
{vtype: 'text',
|
49
|
+
{vtype: 'text', text: ' New Article'}
|
50
50
|
]}
|
51
51
|
]},
|
52
52
|
{tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
|
53
53
|
{tag: 'a', cls: ['nav-link'], href: '#/settings', cn: [
|
54
54
|
{tag: 'i', cls: 'ion-gear-a'},
|
55
|
-
{vtype: 'text',
|
55
|
+
{vtype: 'text', text: ' Settings'}
|
56
56
|
]}
|
57
57
|
]},
|
58
58
|
{tag: 'li', cls: ['nav-item'], removeDom: true, cn: [
|
59
59
|
{tag: 'a', cls : ['nav-link'], href: '#/profile', cn: [
|
60
60
|
{tag: 'img', cls: ['user-pic']},
|
61
|
-
{vtype: 'text',
|
61
|
+
{vtype: 'text', text: ' Profile'}
|
62
62
|
]}
|
63
63
|
]},
|
64
64
|
{tag: 'li', cls: ['nav-item'], cn: [
|
65
|
-
{tag : 'a', cls : ['nav-link'], href: '#/login',
|
65
|
+
{tag : 'a', cls : ['nav-link'], href: '#/login', text: 'Sign in'}
|
66
66
|
]},
|
67
67
|
{tag: 'li', cls: ['nav-item'], cn: [
|
68
|
-
{tag: 'a', cls : ['nav-link'], href: '#/register',
|
68
|
+
{tag: 'a', cls : ['nav-link'], href: '#/register', text: 'Sign up'}
|
69
69
|
]}
|
70
70
|
]}
|
71
71
|
]}
|
@@ -140,7 +140,7 @@ class HeaderComponent extends Component {
|
|
140
140
|
profileLink = me.vdom.cn[0].cn[1].cn[3].cn[0];
|
141
141
|
|
142
142
|
profileLink.href = '#/profile/' + value;
|
143
|
-
profileLink.cn[1].
|
143
|
+
profileLink.cn[1].text = ' ' + value;
|
144
144
|
|
145
145
|
me.update();
|
146
146
|
}
|
@@ -65,8 +65,8 @@ class HomeComponent extends Component {
|
|
65
65
|
{cn: [
|
66
66
|
{cls: ['banner'], cn: [
|
67
67
|
{cls: ['container'], cn: [
|
68
|
-
{tag: 'h1', cls: ['logo-font'],
|
69
|
-
{tag: 'p',
|
68
|
+
{tag: 'h1', cls: ['logo-font'], text: 'conduit'},
|
69
|
+
{tag: 'p', text: 'A place to share your knowledge.'}
|
70
70
|
]}
|
71
71
|
]},
|
72
72
|
{cls: ['container', 'page'], cn: [
|
@@ -211,7 +211,7 @@ class HomeComponent extends Component {
|
|
211
211
|
cls : ['page-link', 'prevent-click'],
|
212
212
|
id : me.getNavLinkVdomId(i),
|
213
213
|
href: '',
|
214
|
-
|
214
|
+
text: i
|
215
215
|
}]
|
216
216
|
});
|
217
217
|
}
|
@@ -274,7 +274,7 @@ class HomeComponent extends Component {
|
|
274
274
|
tag : 'a',
|
275
275
|
cls : cls,
|
276
276
|
href: '',
|
277
|
-
|
277
|
+
text: item.name,
|
278
278
|
id : me.id + '__nav-item-link_' + index,
|
279
279
|
}]
|
280
280
|
});
|
@@ -376,7 +376,7 @@ class HomeComponent extends Component {
|
|
376
376
|
opts = {};
|
377
377
|
|
378
378
|
if (!el.vdom.cls.includes('disabled')) {
|
379
|
-
switch (el.vdom.
|
379
|
+
switch (el.vdom.text) {
|
380
380
|
case 'Global Feed':
|
381
381
|
me.activeTag = null;
|
382
382
|
break;
|
@@ -387,7 +387,7 @@ class HomeComponent extends Component {
|
|
387
387
|
};
|
388
388
|
break;
|
389
389
|
default: // tag
|
390
|
-
me.activeTag = el.vdom.
|
390
|
+
me.activeTag = el.vdom.text.substring(2); // remove the '# '
|
391
391
|
break;
|
392
392
|
}
|
393
393
|
|
@@ -49,7 +49,7 @@ class CommentComponent extends Component {
|
|
49
49
|
{tag: 'a', cls : ['comment-author'], href: '', cn: [
|
50
50
|
{tag: 'img', cls: ['comment-author-img']}
|
51
51
|
]},
|
52
|
-
{vtype: 'text',
|
52
|
+
{vtype: 'text', text: ' '},
|
53
53
|
{tag: 'a', cls: ['comment-author'], href: ''},
|
54
54
|
{tag: 'span', cls : ['date-posted']},
|
55
55
|
{tag: 'span', cls : ['mod-options'], flag: 'mod-options', cn: [
|
@@ -90,7 +90,7 @@ class CommentComponent extends Component {
|
|
90
90
|
let me = this;
|
91
91
|
|
92
92
|
me.vdom.cn[1].cn[0].cn[0].src = value.image;
|
93
|
-
me.vdom.cn[1].cn[2].
|
93
|
+
me.vdom.cn[1].cn[2].text = value.username;
|
94
94
|
|
95
95
|
me.update();
|
96
96
|
me.onCurrentUserChange();
|
@@ -105,7 +105,7 @@ class CommentComponent extends Component {
|
|
105
105
|
*/
|
106
106
|
afterSetBody(value, oldValue) {
|
107
107
|
if (value) {
|
108
|
-
this.vdom.cn[0].cn[0].
|
108
|
+
this.vdom.cn[0].cn[0].text = value;
|
109
109
|
this.update();
|
110
110
|
}
|
111
111
|
}
|
@@ -118,7 +118,7 @@ class CommentComponent extends Component {
|
|
118
118
|
*/
|
119
119
|
afterSetCreatedAt(value, oldValue) {
|
120
120
|
if (value) {
|
121
|
-
this.vdom.cn[1].cn[3].
|
121
|
+
this.vdom.cn[1].cn[3].text = new Intl.DateTimeFormat('en-US', {
|
122
122
|
day : 'numeric',
|
123
123
|
month: 'long',
|
124
124
|
year : 'numeric'
|
@@ -87,19 +87,19 @@ class Component extends BaseComponent {
|
|
87
87
|
]},
|
88
88
|
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-outline-secondary', 'edit-button'], flag: 'edit-button', removeDom: true, cn: [
|
89
89
|
{tag: 'i', cls: ['ion-edit']},
|
90
|
-
{vtype: 'text',
|
90
|
+
{vtype: 'text', text: ' Edit Article'}
|
91
91
|
]},
|
92
92
|
{vtype: 'text', html: ' '},
|
93
93
|
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-outline-primary', 'favorite-button'], flag: 'favorited', cn: [
|
94
94
|
{tag: 'i', cls: ['ion-heart']},
|
95
95
|
{vtype: 'text', html: ' '},
|
96
96
|
{vtype: 'text'},
|
97
|
-
{vtype: 'text',
|
97
|
+
{vtype: 'text', text: ' Post '},
|
98
98
|
{tag: 'span', cls: ['counter'], flag: 'favoritesCount'}
|
99
99
|
]},
|
100
100
|
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-outline-danger', 'delete-button'], flag: 'delete-button', removeDom: true, cn: [
|
101
101
|
{tag: 'i', cls: ['ion-trash-a']},
|
102
|
-
{vtype: 'text',
|
102
|
+
{vtype: 'text', text: ' Delete Article'}
|
103
103
|
]}
|
104
104
|
]}
|
105
105
|
]}
|
@@ -114,7 +114,7 @@ class Component extends BaseComponent {
|
|
114
114
|
{tag: 'a', flag: 'userimage', cn: [{tag: 'img'}]},
|
115
115
|
{cls: ['info'], cn: [
|
116
116
|
{tag: 'a', cls: ['author'], flag: 'username'},
|
117
|
-
{tag: 'span', cls: ['date'],
|
117
|
+
{tag: 'span', cls: ['date'], text: 'January 20th'}
|
118
118
|
]},
|
119
119
|
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-outline-secondary', 'follow-button'], cn: [
|
120
120
|
{tag: 'i', flag: 'followIcon'},
|
@@ -126,7 +126,7 @@ class Component extends BaseComponent {
|
|
126
126
|
{tag: 'i', cls: ['ion-heart']},
|
127
127
|
{vtype: 'text', html: ' '},
|
128
128
|
{vtype: 'text'},
|
129
|
-
{vtype: 'text',
|
129
|
+
{vtype: 'text', text: ' Post '},
|
130
130
|
{tag: 'span', cls: ['counter'], flag: 'favoritesCount'}
|
131
131
|
]}
|
132
132
|
]}
|
@@ -190,7 +190,7 @@ class Component extends BaseComponent {
|
|
190
190
|
vdom = me.vdom;
|
191
191
|
|
192
192
|
VDomUtil.getFlags(vdom, 'followAuthor').forEach(node => {
|
193
|
-
node.
|
193
|
+
node.text = value.following ? ' Unfollow ' : ' Follow ';
|
194
194
|
});
|
195
195
|
|
196
196
|
VDomUtil.getFlags(vdom, 'followIcon').forEach(node => {
|
@@ -204,7 +204,7 @@ class Component extends BaseComponent {
|
|
204
204
|
|
205
205
|
VDomUtil.getFlags(vdom, 'username').forEach(node => {
|
206
206
|
node.href = '#/profile/' + value.username;
|
207
|
-
node.
|
207
|
+
node.text = value.username;
|
208
208
|
});
|
209
209
|
|
210
210
|
me.update();
|
@@ -286,7 +286,7 @@ class Component extends BaseComponent {
|
|
286
286
|
*/
|
287
287
|
afterSetCreatedAt(value, oldValue) {
|
288
288
|
if (value) {
|
289
|
-
VDomUtil.getByFlag(this.vdom, 'createdAt').
|
289
|
+
VDomUtil.getByFlag(this.vdom, 'createdAt').text = new Intl.DateTimeFormat('en-US', {
|
290
290
|
day : 'numeric',
|
291
291
|
month: 'long',
|
292
292
|
year : 'numeric'
|
@@ -306,7 +306,7 @@ class Component extends BaseComponent {
|
|
306
306
|
let me = this;
|
307
307
|
|
308
308
|
VDomUtil.getFlags(me.vdom, 'favorited').forEach(node => {
|
309
|
-
node.cn[2].
|
309
|
+
node.cn[2].text = value ? 'Unfavorite' : 'Favorite';
|
310
310
|
|
311
311
|
NeoArray.add(node.cls, value ? 'btn-primary' : 'btn-outline-primary');
|
312
312
|
NeoArray.remove(node.cls, value ? 'btn-outline-primary' : 'btn-primary');
|
@@ -331,10 +331,10 @@ class Component extends BaseComponent {
|
|
331
331
|
afterSetFavoritesCount(value, oldValue) {
|
332
332
|
if (Neo.isNumber(value)) {
|
333
333
|
VDomUtil.getFlags(this.vdom, 'favoritesCount').forEach(node => {
|
334
|
-
node.
|
334
|
+
node.text = `(${value})`;
|
335
335
|
});
|
336
336
|
|
337
|
-
this.update()
|
337
|
+
this.update()
|
338
338
|
}
|
339
339
|
}
|
340
340
|
|
@@ -360,7 +360,7 @@ class Component extends BaseComponent {
|
|
360
360
|
tagList.cn.push({
|
361
361
|
tag : 'li',
|
362
362
|
cls : ['tag-default', 'tag-pill', 'tag-outline'],
|
363
|
-
|
363
|
+
text: item
|
364
364
|
})
|
365
365
|
});
|
366
366
|
|
@@ -381,8 +381,8 @@ class Component extends BaseComponent {
|
|
381
381
|
* @protected
|
382
382
|
*/
|
383
383
|
afterSetTitle(value, oldValue) {
|
384
|
-
VDomUtil.getByFlag(this.vdom, 'title').
|
385
|
-
this.update()
|
384
|
+
VDomUtil.getByFlag(this.vdom, 'title').text = value;
|
385
|
+
this.update()
|
386
386
|
}
|
387
387
|
|
388
388
|
/**
|
@@ -35,7 +35,7 @@ class CreateCommentComponent extends Component {
|
|
35
35
|
{tag: 'img', cls: ['comment-author-img'], src: 'https://static.productionready.io/images/smiley-cyrus.jpg'}, // https://github.com/gothinkster/realworld/issues/442
|
36
36
|
{vtype: 'text', html: ' '},
|
37
37
|
{tag: 'span', cls: ['comment-author']},
|
38
|
-
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-primary'],
|
38
|
+
{tag: 'button', cls: ['btn', 'btn-sm', 'btn-primary'], text: 'Post Comment', type: 'button'}
|
39
39
|
]}
|
40
40
|
]}
|
41
41
|
}
|
@@ -86,8 +86,8 @@ class CreateCommentComponent extends Component {
|
|
86
86
|
*/
|
87
87
|
afterSetUserName(value, oldValue) {
|
88
88
|
if (value) {
|
89
|
-
this.vdom.cn[1].cn[2].
|
90
|
-
this.update()
|
89
|
+
this.vdom.cn[1].cn[2].text = value;
|
90
|
+
this.update()
|
91
91
|
}
|
92
92
|
}
|
93
93
|
|
@@ -66,7 +66,7 @@ class CreateComponent extends Component {
|
|
66
66
|
{tag: 'input', cls: ['form-control', 'field-tags'], flag: 'tags', name: 'tags', placeholder: 'Enter tags', type: 'text'},
|
67
67
|
{cls: ['tag-list'], flag: 'tag-list'}
|
68
68
|
]},
|
69
|
-
{tag: 'button', cls: ['btn', 'btn-lg', 'btn-primary', 'pull-xs-right'],
|
69
|
+
{tag: 'button', cls: ['btn', 'btn-lg', 'btn-primary', 'pull-xs-right'], text: 'Publish Article', type: 'button'}
|
70
70
|
]}
|
71
71
|
]}
|
72
72
|
]}
|
@@ -128,7 +128,7 @@ class CreateComponent extends Component {
|
|
128
128
|
Object.entries(value || {}).forEach(([key, value]) => {
|
129
129
|
list.cn.push({
|
130
130
|
tag : 'li',
|
131
|
-
|
131
|
+
text: key + ' ' + value.join(' and ')
|
132
132
|
});
|
133
133
|
});
|
134
134
|
|
@@ -159,7 +159,7 @@ class CreateComponent extends Component {
|
|
159
159
|
'data-value': value,
|
160
160
|
}, {
|
161
161
|
vtype: 'text',
|
162
|
-
|
162
|
+
text : value
|
163
163
|
}]
|
164
164
|
});
|
165
165
|
});
|