retold-content-system 1.0.0
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/LICENSE +21 -0
- package/README.md +107 -0
- package/build-codejar-bundle.js +29 -0
- package/build-codemirror-bundle.js +29 -0
- package/codejar-entry.js +10 -0
- package/codemirror-entry.js +16 -0
- package/content/Dogs.txt.md +2 -0
- package/content/README.md +35 -0
- package/content/_sidebar.md +3 -0
- package/content/_topbar.md +1 -0
- package/content/cover.md +12 -0
- package/content/getting-started.md +73 -0
- package/css/content-system.css +42 -0
- package/css/github.css +118 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +24 -0
- package/docs/_sidebar.md +16 -0
- package/docs/_topbar.md +6 -0
- package/docs/cli.md +119 -0
- package/docs/cover.md +16 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/editor-guide.md +137 -0
- package/docs/getting-started.md +73 -0
- package/docs/index.html +39 -0
- package/docs/keyboard-shortcuts.md +40 -0
- package/docs/retold-catalog.json +81 -0
- package/docs/retold-keyword-index.json +19 -0
- package/docs/topics.md +83 -0
- package/html/codejar-bundle.js +16 -0
- package/html/codemirror-bundle.js +29982 -0
- package/html/edit.html +25 -0
- package/html/index.html +25 -0
- package/html/preview.html +19 -0
- package/package.json +70 -0
- package/server.js +43 -0
- package/source/Pict-Application-ContentEditor-Configuration.json +15 -0
- package/source/Pict-Application-ContentEditor.js +1361 -0
- package/source/Pict-Application-ContentReader-Configuration.json +15 -0
- package/source/Pict-Application-ContentReader.js +91 -0
- package/source/Pict-ContentSystem-Bundle.js +21 -0
- package/source/cli/ContentSystem-CLI-Program.js +15 -0
- package/source/cli/ContentSystem-CLI-Run.js +3 -0
- package/source/cli/ContentSystem-Server-Setup.js +405 -0
- package/source/cli/commands/ContentSystem-Command-Serve.js +104 -0
- package/source/providers/Pict-Provider-ContentEditor.js +198 -0
- package/source/views/PictView-Editor-CodeEditor.js +271 -0
- package/source/views/PictView-Editor-Layout.js +1194 -0
- package/source/views/PictView-Editor-MarkdownEditor.js +115 -0
- package/source/views/PictView-Editor-MarkdownReference.js +801 -0
- package/source/views/PictView-Editor-SettingsPanel.js +563 -0
- package/source/views/PictView-Editor-TopBar.js +366 -0
- package/source/views/PictView-Editor-Topics.js +1025 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const libPictProvider = require('pict-provider');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Content Editor Provider
|
|
5
|
+
*
|
|
6
|
+
* Handles communication with the server's REST API for content
|
|
7
|
+
* management: reading/saving markdown and uploading images.
|
|
8
|
+
* File listing is handled by pict-section-filebrowser via the FileBrowserService API.
|
|
9
|
+
*/
|
|
10
|
+
class ContentEditorProvider extends libPictProvider
|
|
11
|
+
{
|
|
12
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
13
|
+
{
|
|
14
|
+
super(pFable, pOptions, pServiceHash);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load the raw markdown content of a file.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} pFilePath - The relative file path
|
|
21
|
+
* @param {Function} fCallback - Callback receiving (error, contentString)
|
|
22
|
+
*/
|
|
23
|
+
loadFile(pFilePath, fCallback)
|
|
24
|
+
{
|
|
25
|
+
let tmpCallback = (typeof (fCallback) === 'function') ? fCallback : () => {};
|
|
26
|
+
|
|
27
|
+
if (!pFilePath)
|
|
28
|
+
{
|
|
29
|
+
return tmpCallback('No file path specified', '');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fetch('/api/content/read/' + encodeURIComponent(pFilePath))
|
|
33
|
+
.then((pResponse) =>
|
|
34
|
+
{
|
|
35
|
+
if (!pResponse.ok)
|
|
36
|
+
{
|
|
37
|
+
return tmpCallback('File not found: ' + pResponse.status, '');
|
|
38
|
+
}
|
|
39
|
+
return pResponse.json();
|
|
40
|
+
})
|
|
41
|
+
.then((pData) =>
|
|
42
|
+
{
|
|
43
|
+
if (pData && pData.Success)
|
|
44
|
+
{
|
|
45
|
+
return tmpCallback(null, pData.Content || '');
|
|
46
|
+
}
|
|
47
|
+
return tmpCallback(pData ? pData.Error : 'Unknown error', '');
|
|
48
|
+
})
|
|
49
|
+
.catch((pError) =>
|
|
50
|
+
{
|
|
51
|
+
this.log.warn(`ContentEditor: Error loading file [${pFilePath}]: ${pError}`);
|
|
52
|
+
return tmpCallback(pError.message, '');
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Save markdown content to a file.
|
|
58
|
+
*
|
|
59
|
+
* @param {string} pFilePath - The relative file path
|
|
60
|
+
* @param {string} pContent - The markdown content to save
|
|
61
|
+
* @param {Function} fCallback - Callback receiving (error)
|
|
62
|
+
*/
|
|
63
|
+
saveFile(pFilePath, pContent, fCallback)
|
|
64
|
+
{
|
|
65
|
+
let tmpCallback = (typeof (fCallback) === 'function') ? fCallback : () => {};
|
|
66
|
+
|
|
67
|
+
if (!pFilePath)
|
|
68
|
+
{
|
|
69
|
+
return tmpCallback('No file path specified');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
fetch('/api/content/save/' + encodeURIComponent(pFilePath),
|
|
73
|
+
{
|
|
74
|
+
method: 'PUT',
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify({ Content: pContent })
|
|
77
|
+
})
|
|
78
|
+
.then((pResponse) =>
|
|
79
|
+
{
|
|
80
|
+
if (!pResponse.ok)
|
|
81
|
+
{
|
|
82
|
+
return tmpCallback('Save failed: ' + pResponse.status);
|
|
83
|
+
}
|
|
84
|
+
return pResponse.json();
|
|
85
|
+
})
|
|
86
|
+
.then((pData) =>
|
|
87
|
+
{
|
|
88
|
+
if (pData && pData.Success)
|
|
89
|
+
{
|
|
90
|
+
return tmpCallback(null);
|
|
91
|
+
}
|
|
92
|
+
return tmpCallback(pData ? pData.Error : 'Unknown error');
|
|
93
|
+
})
|
|
94
|
+
.catch((pError) =>
|
|
95
|
+
{
|
|
96
|
+
this.log.warn(`ContentEditor: Error saving file [${pFilePath}]: ${pError}`);
|
|
97
|
+
return tmpCallback(pError.message);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Upload an image file to the server.
|
|
103
|
+
*
|
|
104
|
+
* The image is saved into the content folder the user is currently
|
|
105
|
+
* browsing, determined from the current file path or browse location.
|
|
106
|
+
*
|
|
107
|
+
* @param {File} pFile - The image file to upload
|
|
108
|
+
* @param {Function} fCallback - Callback receiving (error, url)
|
|
109
|
+
*/
|
|
110
|
+
uploadImage(pFile, fCallback)
|
|
111
|
+
{
|
|
112
|
+
let tmpCallback = (typeof (fCallback) === 'function') ? fCallback : () => {};
|
|
113
|
+
|
|
114
|
+
// Determine the target folder from the currently open file
|
|
115
|
+
let tmpUploadPath = '';
|
|
116
|
+
let tmpCurrentFile = this.pict.AppData.ContentEditor.CurrentFile;
|
|
117
|
+
if (tmpCurrentFile)
|
|
118
|
+
{
|
|
119
|
+
let tmpLastSlash = tmpCurrentFile.lastIndexOf('/');
|
|
120
|
+
if (tmpLastSlash > 0)
|
|
121
|
+
{
|
|
122
|
+
tmpUploadPath = tmpCurrentFile.substring(0, tmpLastSlash);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (this.pict.AppData.PictFileBrowser && this.pict.AppData.PictFileBrowser.CurrentLocation)
|
|
126
|
+
{
|
|
127
|
+
tmpUploadPath = this.pict.AppData.PictFileBrowser.CurrentLocation;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let tmpHeaders =
|
|
131
|
+
{
|
|
132
|
+
'Content-Type': pFile.type,
|
|
133
|
+
'x-filename': pFile.name
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
if (tmpUploadPath)
|
|
137
|
+
{
|
|
138
|
+
tmpHeaders['x-upload-path'] = tmpUploadPath;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
fetch('/api/content/upload-image',
|
|
142
|
+
{
|
|
143
|
+
method: 'POST',
|
|
144
|
+
body: pFile,
|
|
145
|
+
headers: tmpHeaders
|
|
146
|
+
})
|
|
147
|
+
.then((pResponse) => pResponse.json())
|
|
148
|
+
.then((pData) =>
|
|
149
|
+
{
|
|
150
|
+
if (pData && pData.Success && pData.URL)
|
|
151
|
+
{
|
|
152
|
+
return tmpCallback(null, pData.URL);
|
|
153
|
+
}
|
|
154
|
+
return tmpCallback(pData ? pData.Error : 'Upload failed');
|
|
155
|
+
})
|
|
156
|
+
.catch((pError) =>
|
|
157
|
+
{
|
|
158
|
+
this.log.warn(`ContentEditor: Image upload failed: ${pError}`);
|
|
159
|
+
return tmpCallback(pError.message);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* List uploaded images.
|
|
165
|
+
*
|
|
166
|
+
* @param {Function} fCallback - Callback receiving (error, filesArray)
|
|
167
|
+
*/
|
|
168
|
+
listUploads(fCallback)
|
|
169
|
+
{
|
|
170
|
+
let tmpCallback = (typeof (fCallback) === 'function') ? fCallback : () => {};
|
|
171
|
+
|
|
172
|
+
fetch('/api/content/uploads')
|
|
173
|
+
.then((pResponse) => pResponse.json())
|
|
174
|
+
.then((pData) =>
|
|
175
|
+
{
|
|
176
|
+
if (pData && pData.Success)
|
|
177
|
+
{
|
|
178
|
+
return tmpCallback(null, pData.Files || []);
|
|
179
|
+
}
|
|
180
|
+
return tmpCallback(pData ? pData.Error : 'Unknown error', []);
|
|
181
|
+
})
|
|
182
|
+
.catch((pError) =>
|
|
183
|
+
{
|
|
184
|
+
this.log.warn(`ContentEditor: Error listing uploads: ${pError}`);
|
|
185
|
+
return tmpCallback(pError.message, []);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = ContentEditorProvider;
|
|
191
|
+
|
|
192
|
+
module.exports.default_configuration =
|
|
193
|
+
{
|
|
194
|
+
ProviderIdentifier: "ContentEditor-Provider",
|
|
195
|
+
|
|
196
|
+
AutoInitialize: true,
|
|
197
|
+
AutoInitializeOrdinal: 0
|
|
198
|
+
};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
const libPictSectionCode = require('pict-section-code');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Map of file extensions to highlight.js language identifiers.
|
|
5
|
+
*
|
|
6
|
+
* highlight.js supports 190+ languages. This map covers the most common
|
|
7
|
+
* file extensions. For unlisted extensions, highlight.js auto-detection
|
|
8
|
+
* is used as a fallback.
|
|
9
|
+
*/
|
|
10
|
+
const _ExtensionLanguageMap =
|
|
11
|
+
{
|
|
12
|
+
'js': 'javascript',
|
|
13
|
+
'mjs': 'javascript',
|
|
14
|
+
'cjs': 'javascript',
|
|
15
|
+
'jsx': 'javascript',
|
|
16
|
+
'ts': 'typescript',
|
|
17
|
+
'tsx': 'typescript',
|
|
18
|
+
'json': 'json',
|
|
19
|
+
'html': 'xml',
|
|
20
|
+
'htm': 'xml',
|
|
21
|
+
'xml': 'xml',
|
|
22
|
+
'svg': 'xml',
|
|
23
|
+
'css': 'css',
|
|
24
|
+
'scss': 'scss',
|
|
25
|
+
'sass': 'scss',
|
|
26
|
+
'less': 'less',
|
|
27
|
+
'sql': 'sql',
|
|
28
|
+
'py': 'python',
|
|
29
|
+
'rb': 'ruby',
|
|
30
|
+
'java': 'java',
|
|
31
|
+
'kt': 'kotlin',
|
|
32
|
+
'kts': 'kotlin',
|
|
33
|
+
'go': 'go',
|
|
34
|
+
'rs': 'rust',
|
|
35
|
+
'c': 'c',
|
|
36
|
+
'h': 'c',
|
|
37
|
+
'cpp': 'cpp',
|
|
38
|
+
'cc': 'cpp',
|
|
39
|
+
'hpp': 'cpp',
|
|
40
|
+
'cs': 'csharp',
|
|
41
|
+
'swift': 'swift',
|
|
42
|
+
'php': 'php',
|
|
43
|
+
'sh': 'bash',
|
|
44
|
+
'bash': 'bash',
|
|
45
|
+
'zsh': 'bash',
|
|
46
|
+
'fish': 'bash',
|
|
47
|
+
'yml': 'yaml',
|
|
48
|
+
'yaml': 'yaml',
|
|
49
|
+
'toml': 'ini',
|
|
50
|
+
'ini': 'ini',
|
|
51
|
+
'cfg': 'ini',
|
|
52
|
+
'conf': 'ini',
|
|
53
|
+
'dockerfile': 'dockerfile',
|
|
54
|
+
'docker': 'dockerfile',
|
|
55
|
+
'makefile': 'makefile',
|
|
56
|
+
'mk': 'makefile',
|
|
57
|
+
'md': 'markdown',
|
|
58
|
+
'markdown': 'markdown',
|
|
59
|
+
'lua': 'lua',
|
|
60
|
+
'r': 'r',
|
|
61
|
+
'pl': 'perl',
|
|
62
|
+
'pm': 'perl',
|
|
63
|
+
'ex': 'elixir',
|
|
64
|
+
'exs': 'elixir',
|
|
65
|
+
'erl': 'erlang',
|
|
66
|
+
'hrl': 'erlang',
|
|
67
|
+
'hs': 'haskell',
|
|
68
|
+
'clj': 'clojure',
|
|
69
|
+
'scala': 'scala',
|
|
70
|
+
'dart': 'dart',
|
|
71
|
+
'groovy': 'groovy',
|
|
72
|
+
'gradle': 'groovy',
|
|
73
|
+
'tf': 'terraform',
|
|
74
|
+
'vim': 'vim',
|
|
75
|
+
'diff': 'diff',
|
|
76
|
+
'patch': 'diff',
|
|
77
|
+
'log': 'accesslog',
|
|
78
|
+
'txt': 'plaintext'
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const _ViewConfiguration =
|
|
82
|
+
{
|
|
83
|
+
ViewIdentifier: "ContentEditor-CodeEditor",
|
|
84
|
+
|
|
85
|
+
DefaultRenderable: "CodeEditor-Wrap",
|
|
86
|
+
DefaultDestinationAddress: "#ContentEditor-Editor-Container",
|
|
87
|
+
|
|
88
|
+
TargetElementAddress: "#ContentEditor-Editor-Container",
|
|
89
|
+
CodeDataAddress: "AppData.ContentEditor.CodeContent",
|
|
90
|
+
|
|
91
|
+
ReadOnly: false,
|
|
92
|
+
LineNumbers: true,
|
|
93
|
+
Language: "javascript",
|
|
94
|
+
Tab: "\t",
|
|
95
|
+
|
|
96
|
+
AutoRender: false,
|
|
97
|
+
|
|
98
|
+
Renderables:
|
|
99
|
+
[
|
|
100
|
+
{
|
|
101
|
+
RenderableHash: "CodeEditor-Wrap",
|
|
102
|
+
TemplateHash: "CodeEditor-Container",
|
|
103
|
+
DestinationAddress: "#ContentEditor-Editor-Container"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Content Editor Code Editor View
|
|
110
|
+
*
|
|
111
|
+
* Extends pict-section-code to integrate with the content system's
|
|
112
|
+
* server-side save and auto-dirty detection. Uses highlight.js for
|
|
113
|
+
* syntax highlighting across 190+ languages.
|
|
114
|
+
*/
|
|
115
|
+
class ContentEditorCodeEditorView extends libPictSectionCode
|
|
116
|
+
{
|
|
117
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
118
|
+
{
|
|
119
|
+
super(pFable, pOptions, pServiceHash);
|
|
120
|
+
|
|
121
|
+
// When true, the next onCodeChange call will be suppressed
|
|
122
|
+
// (used to prevent the initial marshalToView from marking dirty)
|
|
123
|
+
this._suppressNextDirty = false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Override the initial render to connect CodeJar and highlight.js
|
|
128
|
+
* before the editor is created.
|
|
129
|
+
*/
|
|
130
|
+
onAfterInitialRender()
|
|
131
|
+
{
|
|
132
|
+
// Connect CodeJar from the global bundle
|
|
133
|
+
if (typeof (window) !== 'undefined' && window.CodeJarModules && window.CodeJarModules.CodeJar)
|
|
134
|
+
{
|
|
135
|
+
this.connectCodeJarPrototype(window.CodeJarModules.CodeJar);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Set up highlight.js-based highlighting
|
|
139
|
+
if (typeof (window) !== 'undefined' && window.CodeJarModules && window.CodeJarModules.hljs)
|
|
140
|
+
{
|
|
141
|
+
let tmpHljs = window.CodeJarModules.hljs;
|
|
142
|
+
let tmpLanguage = this._language;
|
|
143
|
+
|
|
144
|
+
this._highlightFunction = function (pElement)
|
|
145
|
+
{
|
|
146
|
+
// Remove any previous hljs state
|
|
147
|
+
pElement.removeAttribute('data-highlighted');
|
|
148
|
+
delete pElement.dataset.highlighted;
|
|
149
|
+
|
|
150
|
+
// Set the language class for hljs
|
|
151
|
+
pElement.className = pElement.className.replace(/\bhljs\b/g, '').replace(/\blanguage-\S+/g, '').trim();
|
|
152
|
+
pElement.classList.add('hljs');
|
|
153
|
+
if (tmpLanguage && tmpLanguage !== 'plaintext')
|
|
154
|
+
{
|
|
155
|
+
pElement.classList.add('language-' + tmpLanguage);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
tmpHljs.highlightElement(pElement);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Now call the parent which creates the CodeJar instance
|
|
163
|
+
return super.onAfterInitialRender();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Set the language for the editor and update highlight.js integration.
|
|
168
|
+
*
|
|
169
|
+
* @param {string} pLanguage - The highlight.js language identifier
|
|
170
|
+
*/
|
|
171
|
+
setLanguage(pLanguage)
|
|
172
|
+
{
|
|
173
|
+
this._language = pLanguage;
|
|
174
|
+
|
|
175
|
+
// Rebuild the highlight function with the new language
|
|
176
|
+
if (typeof (window) !== 'undefined' && window.CodeJarModules && window.CodeJarModules.hljs)
|
|
177
|
+
{
|
|
178
|
+
let tmpHljs = window.CodeJarModules.hljs;
|
|
179
|
+
let tmpLanguage = pLanguage;
|
|
180
|
+
|
|
181
|
+
this._highlightFunction = function (pElement)
|
|
182
|
+
{
|
|
183
|
+
pElement.removeAttribute('data-highlighted');
|
|
184
|
+
delete pElement.dataset.highlighted;
|
|
185
|
+
|
|
186
|
+
pElement.className = pElement.className.replace(/\bhljs\b/g, '').replace(/\blanguage-\S+/g, '').trim();
|
|
187
|
+
pElement.classList.add('hljs');
|
|
188
|
+
if (tmpLanguage && tmpLanguage !== 'plaintext')
|
|
189
|
+
{
|
|
190
|
+
pElement.classList.add('language-' + tmpLanguage);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
tmpHljs.highlightElement(pElement);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (this._editorElement)
|
|
198
|
+
{
|
|
199
|
+
this._editorElement.className = 'pict-code-editor language-' + pLanguage;
|
|
200
|
+
if (!this.options.LineNumbers)
|
|
201
|
+
{
|
|
202
|
+
this._editorElement.className += ' pict-code-no-line-numbers';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (this.codeJar)
|
|
207
|
+
{
|
|
208
|
+
// Re-create the editor with the new highlight function
|
|
209
|
+
let tmpCode = this.codeJar.toString();
|
|
210
|
+
this.codeJar.destroy();
|
|
211
|
+
this.codeJar = this._codeJarPrototype(this._editorElement, this._highlightFunction,
|
|
212
|
+
{
|
|
213
|
+
tab: this.options.Tab,
|
|
214
|
+
catchTab: this.options.CatchTab,
|
|
215
|
+
addClosing: this.options.AddClosing
|
|
216
|
+
});
|
|
217
|
+
this.codeJar.updateCode(tmpCode);
|
|
218
|
+
this.codeJar.onUpdate((pCode) =>
|
|
219
|
+
{
|
|
220
|
+
this._updateLineNumbers();
|
|
221
|
+
this.onCodeChange(pCode);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Handle content changes — mark document as dirty.
|
|
228
|
+
*
|
|
229
|
+
* @param {string} pCode - The new code content
|
|
230
|
+
*/
|
|
231
|
+
onCodeChange(pCode)
|
|
232
|
+
{
|
|
233
|
+
// Write back to data address
|
|
234
|
+
super.onCodeChange(pCode);
|
|
235
|
+
|
|
236
|
+
// Suppress the dirty signal from the initial marshalToView call
|
|
237
|
+
if (this._suppressNextDirty)
|
|
238
|
+
{
|
|
239
|
+
this._suppressNextDirty = false;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Mark the document as dirty and update stats
|
|
244
|
+
if (this.pict.PictApplication)
|
|
245
|
+
{
|
|
246
|
+
this.pict.PictApplication.markDirty();
|
|
247
|
+
this.pict.PictApplication.updateStats();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get the highlight.js language for a file extension.
|
|
253
|
+
*
|
|
254
|
+
* @param {string} pExtension - The file extension (without dot)
|
|
255
|
+
* @returns {string} The highlight.js language identifier
|
|
256
|
+
*/
|
|
257
|
+
static getLanguageForExtension(pExtension)
|
|
258
|
+
{
|
|
259
|
+
if (!pExtension)
|
|
260
|
+
{
|
|
261
|
+
return 'plaintext';
|
|
262
|
+
}
|
|
263
|
+
let tmpExt = pExtension.toLowerCase();
|
|
264
|
+
return _ExtensionLanguageMap[tmpExt] || 'plaintext';
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
module.exports = ContentEditorCodeEditorView;
|
|
269
|
+
|
|
270
|
+
module.exports.default_configuration = _ViewConfiguration;
|
|
271
|
+
module.exports.ExtensionLanguageMap = _ExtensionLanguageMap;
|