@adminforth/markdown 1.7.0 → 1.9.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/build.log CHANGED
@@ -10,5 +10,5 @@ custom/package-lock.json
10
10
  custom/package.json
11
11
  custom/tsconfig.json
12
12
 
13
- sent 29,849 bytes received 115 bytes 59,928.00 bytes/sec
14
- total size is 29,417 speedup is 0.98
13
+ sent 32,725 bytes received 115 bytes 65,680.00 bytes/sec
14
+ total size is 32,299 speedup is 0.98
@@ -229,10 +229,60 @@ function getTurndownService(): TurndownService {
229
229
  return `![${altFinal}](${src} "${escapedTitle}")`;
230
230
  },
231
231
  });
232
-
232
+ turndownService.escape = (s: string) => s;
233
233
  return turndownService;
234
234
  }
235
235
 
236
+ function toggleWrap(ed: monaco.editor.IStandaloneCodeEditor, left: string, right = left) {
237
+ const m = ed.getModel();
238
+ if (!m) return;
239
+
240
+ const selections = ed.getSelections() || [];
241
+ if (!selections.length) return;
242
+
243
+ const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
244
+ const nextSelections: monaco.Selection[] = [];
245
+
246
+ for (const sel of selections) {
247
+ const text = m.getValueInRange(sel);
248
+
249
+ if (sel.isEmpty()) {
250
+ edits.push({ range: sel, text: `${left}${right}` });
251
+ const pos = sel.getStartPosition();
252
+ const col = pos.column + left.length;
253
+ nextSelections.push(new monaco.Selection(pos.lineNumber, col, pos.lineNumber, col));
254
+ continue;
255
+ }
256
+
257
+ const isWrapped = text.startsWith(left) && text.endsWith(right) && text.length >= left.length + right.length;
258
+
259
+ if (isWrapped) {
260
+ const unwrapped = text.slice(left.length, text.length - right.length);
261
+ edits.push({ range: sel, text: unwrapped });
262
+
263
+ const start = sel.getStartPosition();
264
+ nextSelections.push(new monaco.Selection(start.lineNumber, start.column, start.lineNumber, start.column + unwrapped.length));
265
+ } else {
266
+ edits.push({ range: sel, text: `${left}${text}${right}` });
267
+
268
+ const start = sel.getStartPosition();
269
+ nextSelections.push(
270
+ new monaco.Selection(
271
+ start.lineNumber,
272
+ start.column + left.length,
273
+ start.lineNumber,
274
+ start.column + left.length + text.length,
275
+ ),
276
+ );
277
+ }
278
+ }
279
+
280
+ ed.pushUndoStop();
281
+ ed.executeEdits('md-format', edits);
282
+ ed.pushUndoStop();
283
+ ed.setSelections(nextSelections);
284
+ }
285
+
236
286
  let editor: monaco.editor.IStandaloneCodeEditor | null = null;
237
287
  let model: monaco.editor.ITextModel | null = null;
238
288
  const disposables: monaco.IDisposable[] = [];
@@ -310,13 +360,14 @@ function updateImagePreviews() {
310
360
  preview.style.display = 'inline-block';
311
361
  preview.style.borderRadius = '6px';
312
362
  preview.style.overflow = 'hidden';
313
- preview.style.maxWidth = '220px';
314
- preview.style.maxHeight = '140px';
363
+ preview.style.maxWidth = '440px';
364
+ preview.style.maxHeight = '280px';
365
+
315
366
 
316
367
  const imageEl = document.createElement('img');
317
368
  imageEl.src = img.src;
318
- imageEl.style.maxWidth = '220px';
319
- imageEl.style.maxHeight = '140px';
369
+ imageEl.style.maxWidth = '440px';
370
+ imageEl.style.maxHeight = '280px';
320
371
  imageEl.style.display = 'block';
321
372
  imageEl.style.opacity = '0.95';
322
373
 
@@ -325,7 +376,7 @@ function updateImagePreviews() {
325
376
 
326
377
  const zone: monaco.editor.IViewZone = {
327
378
  afterLineNumber: img.lineNumber,
328
- heightInPx: 160,
379
+ heightInPx: 320,
329
380
  domNode: wrapper,
330
381
  };
331
382
 
@@ -336,7 +387,7 @@ function updateImagePreviews() {
336
387
  imageEl.onload = () => {
337
388
  if (!editor) return;
338
389
  const measured = wrapper.offsetHeight;
339
- const nextHeight = Math.max(40, Math.min(200, measured || 160));
390
+ const nextHeight = Math.max(60, Math.min(520, measured || 320));
340
391
  if (zone.heightInPx !== nextHeight) {
341
392
  zone.heightInPx = nextHeight;
342
393
  editor.changeViewZones((a) => a.layoutZone(zoneId));
@@ -455,8 +506,38 @@ onMounted(async () => {
455
506
  model,
456
507
  language: 'markdown',
457
508
  automaticLayout: true,
509
+ wordWrap: 'on',
510
+ wrappingStrategy: 'advanced',
511
+ wrappingIndent: 'same',
512
+ scrollbar: {
513
+ horizontal: 'hidden',
514
+ },
515
+ scrollBeyondLastColumn: 0,
516
+ });
517
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI, () => {
518
+ toggleWrap(editor!, '*');
458
519
  });
459
520
 
521
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB, () => {
522
+ toggleWrap(editor!, '**');
523
+ });
524
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyU, () => {
525
+ toggleWrap(editor!, '<u>', '</u>');
526
+ });
527
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE, () => {
528
+ toggleWrap(editor!, '`');
529
+ });
530
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Shift | monaco.KeyCode.KeyX, () => {
531
+ toggleWrap(editor!, '~~');
532
+ });
533
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, () => {
534
+ const selection = editor!.getSelection();
535
+ if (!selection) return;
536
+ const text = model?.getValueInRange(selection) || '';
537
+ const escaped = escapeMarkdownLinkText(text);
538
+ const markdownLink = `[${escaped}](url)`;
539
+ editor!.executeEdits('insert-link', [{ range: selection, text: markdownLink, forceMoveMarkers: true }]);
540
+ });
460
541
  debug('Monaco editor created', {
461
542
  hasUploadPluginInstanceId: Boolean(props.meta?.uploadPluginInstanceId),
462
543
  });
@@ -229,10 +229,60 @@ function getTurndownService(): TurndownService {
229
229
  return `![${altFinal}](${src} "${escapedTitle}")`;
230
230
  },
231
231
  });
232
-
232
+ turndownService.escape = (s: string) => s;
233
233
  return turndownService;
234
234
  }
235
235
 
236
+ function toggleWrap(ed: monaco.editor.IStandaloneCodeEditor, left: string, right = left) {
237
+ const m = ed.getModel();
238
+ if (!m) return;
239
+
240
+ const selections = ed.getSelections() || [];
241
+ if (!selections.length) return;
242
+
243
+ const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
244
+ const nextSelections: monaco.Selection[] = [];
245
+
246
+ for (const sel of selections) {
247
+ const text = m.getValueInRange(sel);
248
+
249
+ if (sel.isEmpty()) {
250
+ edits.push({ range: sel, text: `${left}${right}` });
251
+ const pos = sel.getStartPosition();
252
+ const col = pos.column + left.length;
253
+ nextSelections.push(new monaco.Selection(pos.lineNumber, col, pos.lineNumber, col));
254
+ continue;
255
+ }
256
+
257
+ const isWrapped = text.startsWith(left) && text.endsWith(right) && text.length >= left.length + right.length;
258
+
259
+ if (isWrapped) {
260
+ const unwrapped = text.slice(left.length, text.length - right.length);
261
+ edits.push({ range: sel, text: unwrapped });
262
+
263
+ const start = sel.getStartPosition();
264
+ nextSelections.push(new monaco.Selection(start.lineNumber, start.column, start.lineNumber, start.column + unwrapped.length));
265
+ } else {
266
+ edits.push({ range: sel, text: `${left}${text}${right}` });
267
+
268
+ const start = sel.getStartPosition();
269
+ nextSelections.push(
270
+ new monaco.Selection(
271
+ start.lineNumber,
272
+ start.column + left.length,
273
+ start.lineNumber,
274
+ start.column + left.length + text.length,
275
+ ),
276
+ );
277
+ }
278
+ }
279
+
280
+ ed.pushUndoStop();
281
+ ed.executeEdits('md-format', edits);
282
+ ed.pushUndoStop();
283
+ ed.setSelections(nextSelections);
284
+ }
285
+
236
286
  let editor: monaco.editor.IStandaloneCodeEditor | null = null;
237
287
  let model: monaco.editor.ITextModel | null = null;
238
288
  const disposables: monaco.IDisposable[] = [];
@@ -310,13 +360,14 @@ function updateImagePreviews() {
310
360
  preview.style.display = 'inline-block';
311
361
  preview.style.borderRadius = '6px';
312
362
  preview.style.overflow = 'hidden';
313
- preview.style.maxWidth = '220px';
314
- preview.style.maxHeight = '140px';
363
+ preview.style.maxWidth = '440px';
364
+ preview.style.maxHeight = '280px';
365
+
315
366
 
316
367
  const imageEl = document.createElement('img');
317
368
  imageEl.src = img.src;
318
- imageEl.style.maxWidth = '220px';
319
- imageEl.style.maxHeight = '140px';
369
+ imageEl.style.maxWidth = '440px';
370
+ imageEl.style.maxHeight = '280px';
320
371
  imageEl.style.display = 'block';
321
372
  imageEl.style.opacity = '0.95';
322
373
 
@@ -325,7 +376,7 @@ function updateImagePreviews() {
325
376
 
326
377
  const zone: monaco.editor.IViewZone = {
327
378
  afterLineNumber: img.lineNumber,
328
- heightInPx: 160,
379
+ heightInPx: 320,
329
380
  domNode: wrapper,
330
381
  };
331
382
 
@@ -336,7 +387,7 @@ function updateImagePreviews() {
336
387
  imageEl.onload = () => {
337
388
  if (!editor) return;
338
389
  const measured = wrapper.offsetHeight;
339
- const nextHeight = Math.max(40, Math.min(200, measured || 160));
390
+ const nextHeight = Math.max(60, Math.min(520, measured || 320));
340
391
  if (zone.heightInPx !== nextHeight) {
341
392
  zone.heightInPx = nextHeight;
342
393
  editor.changeViewZones((a) => a.layoutZone(zoneId));
@@ -455,8 +506,38 @@ onMounted(async () => {
455
506
  model,
456
507
  language: 'markdown',
457
508
  automaticLayout: true,
509
+ wordWrap: 'on',
510
+ wrappingStrategy: 'advanced',
511
+ wrappingIndent: 'same',
512
+ scrollbar: {
513
+ horizontal: 'hidden',
514
+ },
515
+ scrollBeyondLastColumn: 0,
516
+ });
517
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI, () => {
518
+ toggleWrap(editor!, '*');
458
519
  });
459
520
 
521
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB, () => {
522
+ toggleWrap(editor!, '**');
523
+ });
524
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyU, () => {
525
+ toggleWrap(editor!, '<u>', '</u>');
526
+ });
527
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE, () => {
528
+ toggleWrap(editor!, '`');
529
+ });
530
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Shift | monaco.KeyCode.KeyX, () => {
531
+ toggleWrap(editor!, '~~');
532
+ });
533
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, () => {
534
+ const selection = editor!.getSelection();
535
+ if (!selection) return;
536
+ const text = model?.getValueInRange(selection) || '';
537
+ const escaped = escapeMarkdownLinkText(text);
538
+ const markdownLink = `[${escaped}](url)`;
539
+ editor!.executeEdits('insert-link', [{ range: selection, text: markdownLink, forceMoveMarkers: true }]);
540
+ });
460
541
  debug('Monaco editor created', {
461
542
  hasUploadPluginInstanceId: Boolean(props.meta?.uploadPluginInstanceId),
462
543
  });
package/dist/index.js CHANGED
@@ -175,6 +175,16 @@ export default class MarkdownPlugin extends AdminForthPlugin {
175
175
  existing.title = next.title;
176
176
  }
177
177
  };
178
+ const normalizeAttachmentTitleForDb = (title) => {
179
+ // we can llow to use [xx] in titles, for some meta classes - so they will nto go to attachment titles, but will be available in the ending markdown
180
+ if (title === null) {
181
+ return null;
182
+ }
183
+ const cleaned = title
184
+ .replace(/\s*(?:\([^()]*\)|\[[^\[\]]*\])\s*$/, '')
185
+ .trim();
186
+ return cleaned || null;
187
+ };
178
188
  function getAttachmentMetas(markdown) {
179
189
  var _a, _b, _c, _d, _e, _f;
180
190
  if (!markdown) {
@@ -188,7 +198,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
188
198
  for (const match of markdown.matchAll(imageRegex)) {
189
199
  const altRaw = (_a = match[1]) !== null && _a !== void 0 ? _a : '';
190
200
  const srcRaw = match[2];
191
- const titleRaw = (_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null;
201
+ const titleRaw = normalizeAttachmentTitleForDb((_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null);
192
202
  const key = getKeyFromTrackedUrl(srcRaw);
193
203
  if (!key) {
194
204
  continue;
package/index.ts CHANGED
@@ -194,6 +194,17 @@ export default class MarkdownPlugin extends AdminForthPlugin {
194
194
  }
195
195
  };
196
196
 
197
+ const normalizeAttachmentTitleForDb = (title: string | null): string | null => {
198
+ // we can llow to use [xx] in titles, for some meta classes - so they will nto go to attachment titles, but will be available in the ending markdown
199
+ if (title === null) {
200
+ return null;
201
+ }
202
+ const cleaned = title
203
+ .replace(/\s*(?:\([^()]*\)|\[[^\[\]]*\])\s*$/, '')
204
+ .trim();
205
+ return cleaned || null;
206
+ };
207
+
197
208
  function getAttachmentMetas(markdown: string): AttachmentMeta[] {
198
209
  if (!markdown) {
199
210
  return [];
@@ -209,7 +220,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
209
220
  for (const match of markdown.matchAll(imageRegex)) {
210
221
  const altRaw = match[1] ?? '';
211
222
  const srcRaw = match[2];
212
- const titleRaw = (match[3] ?? match[4]) ?? null;
223
+ const titleRaw = normalizeAttachmentTitleForDb((match[3] ?? match[4]) ?? null);
213
224
 
214
225
  const key = getKeyFromTrackedUrl(srcRaw);
215
226
  if (!key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/markdown",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Markdown plugin for adminforth",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",