ssml-builder-js 2.2.0 → 2.3.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/dist/react.js CHANGED
@@ -36,7 +36,9 @@ __export(react_exports, {
36
36
  SSML_HOVER_COPY: () => SSML_HOVER_COPY,
37
37
  SSML_INSERTIONS: () => SSML_INSERTIONS,
38
38
  SsmlEditor: () => SsmlEditor,
39
- createSsmlEditorInsertionDefinition: () => createSsmlEditorInsertionDefinition
39
+ createSsmlEditorInsertionDefinition: () => createSsmlEditorInsertionDefinition,
40
+ registerSsmlCodeLens: () => registerSsmlCodeLens,
41
+ updateTagAttribute: () => updateTagAttribute
40
42
  });
41
43
  module.exports = __toCommonJS(react_exports);
42
44
 
@@ -1588,6 +1590,7 @@ var SSML_ATTRS = {
1588
1590
  STYLE: "style",
1589
1591
  STYLE_DEGREE: "styledegree",
1590
1592
  STYLE_DEGREE_CAMEL: "styleDegree",
1593
+ STYLE_DEGREE_HYPHEN: "style-degree",
1591
1594
  ROLE: "role",
1592
1595
  INTERPRET_AS: "interpret-as",
1593
1596
  FORMAT: "format",
@@ -2131,7 +2134,12 @@ function convertElement(node) {
2131
2134
  case SSML_TAGS.MSTTS_EXPRESS_AS: {
2132
2135
  const element = { type: node.name };
2133
2136
  const style = readAttribute(attributes, SSML_ATTRS.STYLE);
2134
- const styleDegree = readAttribute(attributes, SSML_ATTRS.STYLE_DEGREE, SSML_ATTRS.STYLE_DEGREE_CAMEL);
2137
+ const styleDegree = readAttribute(
2138
+ attributes,
2139
+ SSML_ATTRS.STYLE_DEGREE,
2140
+ SSML_ATTRS.STYLE_DEGREE_CAMEL,
2141
+ SSML_ATTRS.STYLE_DEGREE_HYPHEN
2142
+ );
2135
2143
  const role = readAttribute(attributes, SSML_ATTRS.ROLE);
2136
2144
  if (style !== void 0) element.style = style;
2137
2145
  if (styleDegree !== void 0) element.styleDegree = styleDegree;
@@ -3145,6 +3153,26 @@ function findTagEnd2(source, start, limit) {
3145
3153
  function getVoiceName(tag) {
3146
3154
  return tag.match(/\bname\s*=\s*(["'])([\s\S]*?)\1/i)?.[2];
3147
3155
  }
3156
+ function escapeXmlAttribute(value) {
3157
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;");
3158
+ }
3159
+ function updateTagAttribute(text, tagRange, attributeName, newValue) {
3160
+ const start = Math.max(0, Math.min(tagRange.start, text.length));
3161
+ const end = Math.max(start, Math.min(tagRange.end, text.length));
3162
+ const tag = text.slice(start, end);
3163
+ const escapedAttributeName = attributeName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3164
+ const attributePattern = new RegExp(`(\\b${escapedAttributeName}\\s*=\\s*)(["'])([\\s\\S]*?)\\2`, "i");
3165
+ const escapedValue = escapeXmlAttribute(newValue);
3166
+ const match = tag.match(attributePattern);
3167
+ if (match?.index !== void 0) {
3168
+ const valueStart = match.index + match[0].indexOf(match[2]) + 1;
3169
+ const valueEnd = valueStart + (match[3]?.length ?? 0);
3170
+ return `${text.slice(0, start)}${tag.slice(0, valueStart)}${escapedValue}${tag.slice(valueEnd)}${text.slice(end)}`;
3171
+ }
3172
+ const insertionIndex = tag.endsWith("/>") ? tag.length - 2 : tag.length - 1;
3173
+ const attribute = ` ${attributeName}="${escapedValue}"`;
3174
+ return `${text.slice(0, start)}${tag.slice(0, insertionIndex)}${attribute}${tag.slice(insertionIndex)}${text.slice(end)}`;
3175
+ }
3148
3176
  function closeElement(stack, name) {
3149
3177
  for (let index = stack.length - 1; index >= 0; index -= 1) {
3150
3178
  if (stack[index]?.name === name) {
@@ -3453,6 +3481,7 @@ function useSsmlEditorState({
3453
3481
  const [openPopoverId, setOpenPopoverId] = (0, import_react.useState)(null);
3454
3482
  const [popoverVoiceName, setPopoverVoiceName] = (0, import_react.useState)(void 0);
3455
3483
  const [popoverPosition, setPopoverPosition] = (0, import_react.useState)(null);
3484
+ const pendingCodeLensAttributeRef = (0, import_react.useRef)(null);
3456
3485
  const helpPanelId = (0, import_react.useId)();
3457
3486
  const draftDocumentRef = (0, import_react.useRef)(document2);
3458
3487
  const onSelectionChangeRef = (0, import_react.useRef)(onSelectionChange);
@@ -3478,6 +3507,7 @@ function useSsmlEditorState({
3478
3507
  setDecorationsVisible(showDecorations);
3479
3508
  }, [showDecorations]);
3480
3509
  const closePopover = (0, import_react.useCallback)((restoreFocus = false) => {
3510
+ pendingCodeLensAttributeRef.current = null;
3481
3511
  setOpenPopoverId(null);
3482
3512
  setPopoverVoiceName(void 0);
3483
3513
  setPopoverPosition(null);
@@ -3486,6 +3516,7 @@ function useSsmlEditorState({
3486
3516
  }
3487
3517
  }, []);
3488
3518
  const togglePopover = (0, import_react.useCallback)((id, trigger) => {
3519
+ pendingCodeLensAttributeRef.current = null;
3489
3520
  setOpenPopoverId((currentId) => {
3490
3521
  if (currentId === id) {
3491
3522
  setPopoverVoiceName(void 0);
@@ -3509,13 +3540,41 @@ function useSsmlEditorState({
3509
3540
  }
3510
3541
  const updatePopoverPosition = () => {
3511
3542
  const trigger = activePopoverTriggerRef.current;
3512
- if (!trigger) {
3543
+ if (trigger) {
3544
+ const triggerBounds = trigger.getBoundingClientRect();
3545
+ setPopoverPosition({
3546
+ top: triggerBounds.bottom + 4,
3547
+ left: triggerBounds.left
3548
+ });
3549
+ return;
3550
+ }
3551
+ const pending = pendingCodeLensAttributeRef.current;
3552
+ const editor = editorRef.current;
3553
+ const model = editor?.getModel();
3554
+ if (!pending || !editor || !model) {
3555
+ return;
3556
+ }
3557
+ const position = model.getPositionAt(pending.tagRange.start);
3558
+ const visiblePosition = editor.getScrolledVisiblePosition(position);
3559
+ const editorElement = editor.getDomNode();
3560
+ if (!visiblePosition || !editorElement) {
3513
3561
  return;
3514
3562
  }
3515
- const triggerBounds = trigger.getBoundingClientRect();
3563
+ const editorBounds = editorElement.getBoundingClientRect();
3564
+ const menu = activePopoverMenuRef.current;
3565
+ const margin = 8;
3516
3566
  setPopoverPosition({
3517
- top: triggerBounds.bottom + 4,
3518
- left: triggerBounds.left
3567
+ top: Math.max(
3568
+ margin,
3569
+ Math.min(
3570
+ editorBounds.top + visiblePosition.top + visiblePosition.height + 4,
3571
+ window.innerHeight - (menu?.offsetHeight ?? 0) - margin
3572
+ )
3573
+ ),
3574
+ left: Math.max(
3575
+ margin,
3576
+ Math.min(editorBounds.left + visiblePosition.left, window.innerWidth - (menu?.offsetWidth ?? 0) - margin)
3577
+ )
3519
3578
  });
3520
3579
  };
3521
3580
  const handlePointerDown = (event) => {
@@ -3580,11 +3639,48 @@ function useSsmlEditorState({
3580
3639
  );
3581
3640
  const handleInsert = (0, import_react.useCallback)(
3582
3641
  (insertion, option) => {
3583
- if (editorRef.current) {
3584
- applySsmlInsertion(editorRef.current, insertion, option);
3642
+ const editor = editorRef.current;
3643
+ const pending = pendingCodeLensAttributeRef.current;
3644
+ if (!editor) {
3645
+ return;
3585
3646
  }
3647
+ if (pending?.insertionId === insertion.id) {
3648
+ const model = editor.getModel();
3649
+ if (model && model.getVersionId() === pending.modelVersionId) {
3650
+ const source = model.getValue();
3651
+ const tagText = source.slice(pending.tagRange.start, pending.tagRange.end);
3652
+ const updatedTag = updateTagAttribute(
3653
+ tagText,
3654
+ { start: 0, end: tagText.length },
3655
+ pending.attributeName,
3656
+ option.value
3657
+ );
3658
+ const start = model.getPositionAt(pending.tagRange.start);
3659
+ const end = model.getPositionAt(pending.tagRange.end);
3660
+ editor.pushUndoStop();
3661
+ editor.executeEdits("ssml-code-lens", [
3662
+ {
3663
+ range: {
3664
+ startLineNumber: start.lineNumber,
3665
+ startColumn: start.column,
3666
+ endLineNumber: end.lineNumber,
3667
+ endColumn: end.column
3668
+ },
3669
+ text: updatedTag
3670
+ }
3671
+ ]);
3672
+ editor.pushUndoStop();
3673
+ editor.focus();
3674
+ }
3675
+ pendingCodeLensAttributeRef.current = null;
3676
+ if (!model || model.getVersionId() !== pending.modelVersionId) {
3677
+ closePopover();
3678
+ }
3679
+ return;
3680
+ }
3681
+ applySsmlInsertion(editor, insertion, option);
3586
3682
  },
3587
- []
3683
+ [closePopover]
3588
3684
  );
3589
3685
  const handleInsertBreak = (0, import_react.useCallback)(
3590
3686
  (insertion, option) => {
@@ -3650,6 +3746,54 @@ function useSsmlEditorState({
3650
3746
  []
3651
3747
  );
3652
3748
  const getOuterVoiceName = (0, import_react.useCallback)(() => getEditableRegion(draftDocumentRef.current).voiceName, []);
3749
+ const handleCodeLensAction = (0, import_react.useCallback)((action) => {
3750
+ const editor = editorRef.current;
3751
+ const model = editor?.getModel();
3752
+ if (!editor || !model) {
3753
+ return;
3754
+ }
3755
+ if (action.type === "attribute") {
3756
+ pendingCodeLensAttributeRef.current = {
3757
+ insertionId: action.insertionId,
3758
+ attributeName: action.attributeName,
3759
+ tagRange: action.tagRange,
3760
+ modelVersionId: model.getVersionId()
3761
+ };
3762
+ activePopoverTriggerRef.current = null;
3763
+ setPopoverVoiceName(getEffectiveVoiceName(editor, draftDocumentRef.current));
3764
+ setOpenPopoverId(action.insertionId);
3765
+ setPopoverPosition(null);
3766
+ return;
3767
+ }
3768
+ const source = model.getValue();
3769
+ const toEditorRange = (range) => {
3770
+ const start = model.getPositionAt(range.start);
3771
+ const end = model.getPositionAt(range.end);
3772
+ return {
3773
+ startLineNumber: start.lineNumber,
3774
+ startColumn: start.column,
3775
+ endLineNumber: end.lineNumber,
3776
+ endColumn: end.column
3777
+ };
3778
+ };
3779
+ const edits = action.type === "delete" ? [{ range: toEditorRange(action.tagRange), text: "" }] : (() => {
3780
+ const elementText = source.slice(action.elementRange.start, action.elementRange.end);
3781
+ const closingOffset = elementText.search(/<\/\s*prosody\s*>/i);
3782
+ const closingStart = closingOffset === -1 ? action.elementRange.end : action.elementRange.start + closingOffset;
3783
+ const closingEnd = closingOffset === -1 ? action.elementRange.end : source.indexOf(">", closingStart) === -1 ? action.elementRange.end : source.indexOf(">", closingStart) + 1;
3784
+ return [
3785
+ { range: toEditorRange(action.tagRange), text: "" },
3786
+ { range: toEditorRange({ start: closingStart, end: closingEnd }), text: "" }
3787
+ ];
3788
+ })();
3789
+ editor.pushUndoStop();
3790
+ editor.executeEdits("ssml-code-lens", edits);
3791
+ editor.pushUndoStop();
3792
+ pendingCodeLensAttributeRef.current = null;
3793
+ setOpenPopoverId(null);
3794
+ setPopoverPosition(null);
3795
+ editor.focus();
3796
+ }, []);
3653
3797
  return {
3654
3798
  editorRef,
3655
3799
  draftDocument,
@@ -3682,6 +3826,7 @@ function useSsmlEditorState({
3682
3826
  getCurrentLineSsml: getCurrentLineSsmlValue,
3683
3827
  getFullSsml,
3684
3828
  getOuterVoiceName,
3829
+ handleCodeLensAction,
3685
3830
  openPopoverId,
3686
3831
  popoverVoiceName,
3687
3832
  popoverPosition,
@@ -4030,6 +4175,180 @@ function registerSsmlCodeActions(monaco) {
4030
4175
  });
4031
4176
  }
4032
4177
 
4178
+ // packages/ssml-editor-react/src/ssmlCodeLens.ts
4179
+ var CODE_LENS_COMMAND = "ssml-editor.codeLens";
4180
+ function findTagEnd3(source, start) {
4181
+ let quote;
4182
+ for (let index = start + 1; index < source.length; index += 1) {
4183
+ const character = source[index];
4184
+ if (quote !== void 0) {
4185
+ if (character === quote) {
4186
+ quote = void 0;
4187
+ }
4188
+ } else if (character === '"' || character === "'") {
4189
+ quote = character;
4190
+ } else if (character === ">") {
4191
+ return index;
4192
+ }
4193
+ }
4194
+ return -1;
4195
+ }
4196
+ function getAttributeValue(tag, attributeName) {
4197
+ const escapedName = attributeName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4198
+ return tag.match(new RegExp(`\\b${escapedName}\\s*=\\s*(["'])([\\s\\S]*?)\\1`, "i"))?.[2];
4199
+ }
4200
+ function getTagRange(start, end) {
4201
+ return { start, end };
4202
+ }
4203
+ function getElementEnd(source, tagName, tagEnd) {
4204
+ const openingTag = source.slice(0, tagEnd + 1);
4205
+ if (/\/\s*>$/.test(openingTag)) {
4206
+ return tagEnd + 1;
4207
+ }
4208
+ let depth = 1;
4209
+ let index = tagEnd + 1;
4210
+ while (index < source.length) {
4211
+ const nextStart = source.indexOf("<", index);
4212
+ if (nextStart === -1) {
4213
+ break;
4214
+ }
4215
+ if (source.startsWith("<!--", nextStart)) {
4216
+ index = source.indexOf("-->", nextStart + 4);
4217
+ index = index === -1 ? source.length : index + 3;
4218
+ continue;
4219
+ }
4220
+ const nextEnd = findTagEnd3(source, nextStart);
4221
+ if (nextEnd === -1) {
4222
+ break;
4223
+ }
4224
+ const nextTag = source.slice(nextStart, nextEnd + 1);
4225
+ const closingMatch = nextTag.match(/^<\s*\/\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
4226
+ const openingMatch = nextTag.match(/^<\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
4227
+ if (closingMatch?.[1]?.toLowerCase() === tagName) {
4228
+ depth -= 1;
4229
+ if (depth === 0) {
4230
+ return nextEnd + 1;
4231
+ }
4232
+ } else if (openingMatch?.[1]?.toLowerCase() === tagName && !/\/\s*>$/.test(nextTag)) {
4233
+ depth += 1;
4234
+ }
4235
+ index = nextEnd + 1;
4236
+ }
4237
+ return tagEnd + 1;
4238
+ }
4239
+ function createLens(model, start, end, title, action) {
4240
+ const startPosition = model.getPositionAt(start);
4241
+ const endPosition = model.getPositionAt(end);
4242
+ return {
4243
+ range: {
4244
+ startLineNumber: startPosition.lineNumber,
4245
+ startColumn: startPosition.column,
4246
+ endLineNumber: endPosition.lineNumber,
4247
+ endColumn: endPosition.column
4248
+ },
4249
+ command: {
4250
+ id: CODE_LENS_COMMAND,
4251
+ title,
4252
+ arguments: [action]
4253
+ }
4254
+ };
4255
+ }
4256
+ function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
4257
+ const provider = {
4258
+ provideCodeLenses(model) {
4259
+ const source = model.getValue();
4260
+ const lenses = [];
4261
+ let index = 0;
4262
+ while (index < source.length) {
4263
+ const tagStart = source.indexOf("<", index);
4264
+ if (tagStart === -1) {
4265
+ break;
4266
+ }
4267
+ if (source.startsWith("<!--", tagStart)) {
4268
+ index = source.indexOf("-->", tagStart + 4);
4269
+ index = index === -1 ? source.length : index + 3;
4270
+ continue;
4271
+ }
4272
+ const tagEnd = findTagEnd3(source, tagStart);
4273
+ if (tagEnd === -1) {
4274
+ break;
4275
+ }
4276
+ const tag = source.slice(tagStart, tagEnd + 1);
4277
+ const tagName = tag.match(/^<\s*(prosody|break)\b/i)?.[1]?.toLowerCase();
4278
+ index = tagEnd + 1;
4279
+ if (!tagName) {
4280
+ continue;
4281
+ }
4282
+ const tagRange = getTagRange(tagStart, tagEnd + 1);
4283
+ const elementEnd = getElementEnd(source, tagName, tagEnd);
4284
+ const elementRange = { start: tagStart, end: elementEnd };
4285
+ if (tagName === "prosody") {
4286
+ lenses.push(
4287
+ createLens(
4288
+ model,
4289
+ tagStart,
4290
+ tagEnd + 1,
4291
+ `\u26A1 Rate: ${getAttributeValue(tag, "rate") ?? "default"} (Click to edit)`,
4292
+ { type: "attribute", insertionId: "rate", attributeName: "rate", tagRange }
4293
+ ),
4294
+ createLens(
4295
+ model,
4296
+ tagStart,
4297
+ tagEnd + 1,
4298
+ `\u26A1 Pitch: ${getAttributeValue(tag, "pitch") ?? "default"} (Click to edit)`,
4299
+ { type: "attribute", insertionId: "pitch", attributeName: "pitch", tagRange }
4300
+ ),
4301
+ createLens(model, tagStart, tagEnd + 1, "Unwrap", {
4302
+ type: "unwrap",
4303
+ tagRange,
4304
+ elementRange
4305
+ })
4306
+ );
4307
+ } else if (/\/\s*>$/.test(tag)) {
4308
+ lenses.push(
4309
+ createLens(
4310
+ model,
4311
+ tagStart,
4312
+ tagEnd + 1,
4313
+ `\u26A1 Time: ${getAttributeValue(tag, "time") ?? "default"} (Click to edit)`,
4314
+ { type: "attribute", insertionId: "break", attributeName: "time", tagRange }
4315
+ ),
4316
+ createLens(model, tagStart, tagEnd + 1, "Delete", {
4317
+ type: "delete",
4318
+ tagRange,
4319
+ elementRange
4320
+ })
4321
+ );
4322
+ }
4323
+ }
4324
+ return { lenses, dispose: () => void 0 };
4325
+ }
4326
+ };
4327
+ const disposable = monaco.languages.registerCodeLensProvider("xml", provider);
4328
+ const commandHandler = (_accessor, ...args) => {
4329
+ const action = args[0];
4330
+ if (action && typeof action === "object" && "type" in action) {
4331
+ onOpenPopover(action);
4332
+ }
4333
+ };
4334
+ const commandDisposable = typeof monaco.editor?.registerCommand === "function" ? monaco.editor.registerCommand(CODE_LENS_COMMAND, commandHandler) : typeof monaco.registerCommand === "function" ? monaco.registerCommand(CODE_LENS_COMMAND, commandHandler) : editor.addAction({
4335
+ id: CODE_LENS_COMMAND,
4336
+ label: "SSML CodeLens",
4337
+ run: (_editor, ...args) => {
4338
+ const action = args[0];
4339
+ if (action && typeof action === "object" && "type" in action) {
4340
+ onOpenPopover(action);
4341
+ }
4342
+ }
4343
+ });
4344
+ return {
4345
+ dispose: () => {
4346
+ commandDisposable.dispose();
4347
+ disposable.dispose();
4348
+ }
4349
+ };
4350
+ }
4351
+
4033
4352
  // packages/ssml-editor-react/src/ssmlHover.ts
4034
4353
  var {
4035
4354
  BREAK_STRENGTH_PRESETS: BREAK_STRENGTH_PRESETS2,
@@ -4379,7 +4698,7 @@ function toRange(source, token) {
4379
4698
  function containsOffset(token, offset) {
4380
4699
  return offset >= token.start && offset < token.end;
4381
4700
  }
4382
- function findTagEnd3(source, start) {
4701
+ function findTagEnd4(source, start) {
4383
4702
  let quote;
4384
4703
  for (let index = start; index < source.length; index += 1) {
4385
4704
  const character = source[index];
@@ -4510,7 +4829,7 @@ function findTagAtOffset(source, offset) {
4510
4829
  searchStart = tokenEnd2;
4511
4830
  continue;
4512
4831
  }
4513
- const tagEnd = findTagEnd3(source, start + 1);
4832
+ const tagEnd = findTagEnd4(source, start + 1);
4514
4833
  const contentEnd = tagEnd ?? source.length;
4515
4834
  const tokenEnd = tagEnd === void 0 ? source.length : tagEnd + 1;
4516
4835
  if (offset < tokenEnd) {
@@ -4726,7 +5045,9 @@ function useSsmlMonaco({
4726
5045
  language,
4727
5046
  text,
4728
5047
  decorationsVisible,
5048
+ enableCodeLens,
4729
5049
  getOuterVoiceName,
5050
+ onOpenPopover,
4730
5051
  onSelectionOverlayChange,
4731
5052
  onActiveTagsChange,
4732
5053
  onSyntaxErrorChange
@@ -4736,6 +5057,7 @@ function useSsmlMonaco({
4736
5057
  const monacoRef = (0, import_react2.useRef)(null);
4737
5058
  const completionProviderRef = (0, import_react2.useRef)(null);
4738
5059
  const codeActionProviderRef = (0, import_react2.useRef)(null);
5060
+ const codeLensProviderRef = (0, import_react2.useRef)(null);
4739
5061
  const releaseHoverProviderRef = (0, import_react2.useRef)(null);
4740
5062
  const selectionChangeRef = (0, import_react2.useRef)(null);
4741
5063
  const cursorPositionChangeRef = (0, import_react2.useRef)(null);
@@ -4745,16 +5067,20 @@ function useSsmlMonaco({
4745
5067
  const inlineDecorationIdsRef = (0, import_react2.useRef)([]);
4746
5068
  const languageRef = (0, import_react2.useRef)(language);
4747
5069
  const decorationsVisibleRef = (0, import_react2.useRef)(decorationsVisible);
5070
+ const enableCodeLensRef = (0, import_react2.useRef)(enableCodeLens);
4748
5071
  const getOuterVoiceNameRef = (0, import_react2.useRef)(getOuterVoiceName);
4749
5072
  const onSelectionOverlayChangeRef = (0, import_react2.useRef)(onSelectionOverlayChange);
4750
5073
  const onActiveTagsChangeRef = (0, import_react2.useRef)(onActiveTagsChange);
4751
5074
  const onSyntaxErrorChangeRef = (0, import_react2.useRef)(onSyntaxErrorChange);
5075
+ const onOpenPopoverRef = (0, import_react2.useRef)(onOpenPopover);
4752
5076
  languageRef.current = language;
4753
5077
  decorationsVisibleRef.current = decorationsVisible;
5078
+ enableCodeLensRef.current = enableCodeLens;
4754
5079
  getOuterVoiceNameRef.current = getOuterVoiceName;
4755
5080
  onSelectionOverlayChangeRef.current = onSelectionOverlayChange;
4756
5081
  onActiveTagsChangeRef.current = onActiveTagsChange;
4757
5082
  onSyntaxErrorChangeRef.current = onSyntaxErrorChange;
5083
+ onOpenPopoverRef.current = onOpenPopover;
4758
5084
  const runSsmlDiagnostics = (0, import_react2.useCallback)((editor, monaco) => {
4759
5085
  const model = editor.getModel();
4760
5086
  if (!model) {
@@ -4807,6 +5133,8 @@ function useSsmlMonaco({
4807
5133
  completionProviderRef.current = null;
4808
5134
  codeActionProviderRef.current?.dispose();
4809
5135
  codeActionProviderRef.current = null;
5136
+ codeLensProviderRef.current?.dispose();
5137
+ codeLensProviderRef.current = null;
4810
5138
  for (const disposable of selectionLayoutDisposablesRef.current) {
4811
5139
  disposable.dispose();
4812
5140
  }
@@ -4851,6 +5179,13 @@ function useSsmlMonaco({
4851
5179
  model: editor.getModel()
4852
5180
  });
4853
5181
  codeActionProviderRef.current = registerSsmlCodeActions(monaco);
5182
+ if (enableCodeLensRef.current) {
5183
+ codeLensProviderRef.current = registerSsmlCodeLens(
5184
+ monaco,
5185
+ editor,
5186
+ (action) => onOpenPopoverRef.current(action)
5187
+ );
5188
+ }
4854
5189
  releaseHoverProviderRef.current = acquireSsmlHoverProvider(monaco, languageRef.current);
4855
5190
  runSsmlDiagnostics(editor, monaco);
4856
5191
  const model = editor.getModel();
@@ -4868,6 +5203,15 @@ function useSsmlMonaco({
4868
5203
  },
4869
5204
  [disposeMonacoResources, editorRef, runSsmlDiagnostics, scheduleSsmlDiagnostics, syncActiveTags]
4870
5205
  );
5206
+ (0, import_react2.useEffect)(() => {
5207
+ const editor = editorRef.current;
5208
+ const monaco = monacoRef.current;
5209
+ if (!editor || !monaco) {
5210
+ return;
5211
+ }
5212
+ codeLensProviderRef.current?.dispose();
5213
+ codeLensProviderRef.current = enableCodeLens ? registerSsmlCodeLens(monaco, editor, (action) => onOpenPopoverRef.current(action)) : null;
5214
+ }, [editorRef, enableCodeLens]);
4871
5215
  (0, import_react2.useEffect)(() => {
4872
5216
  const monaco = monacoRef.current;
4873
5217
  if (!monaco) {
@@ -4908,7 +5252,7 @@ var TEXT_POPOVER_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w"
4908
5252
  function localizedText(value) {
4909
5253
  return { ja: value, en: value };
4910
5254
  }
4911
- function escapeXmlAttribute(value) {
5255
+ function escapeXmlAttribute2(value) {
4912
5256
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;");
4913
5257
  }
4914
5258
  function createSsmlEditorInsertionDefinition(definition) {
@@ -4925,7 +5269,7 @@ function createSsmlEditorInsertionDefinition(definition) {
4925
5269
  parameterDescription: definition.parameterDescription ?? localizedText(`Selects the value for the <${definition.tagName}> element.`),
4926
5270
  options: definition.options,
4927
5271
  createTemplate: (value) => {
4928
- const attributeValue = definition.attribute ? `${attribute}${escapeXmlAttribute(value)}"` : "";
5272
+ const attributeValue = definition.attribute ? `${attribute}${escapeXmlAttribute2(value)}"` : "";
4929
5273
  if (mode === "wrap") {
4930
5274
  return {
4931
5275
  prefix: `<${definition.tagName}${attributeValue}>`,
@@ -5388,6 +5732,7 @@ var SsmlEditor = (0, import_react3.forwardRef)(function SsmlEditor2({
5388
5732
  showToolbarIcons = true,
5389
5733
  showToolbarLabels = false,
5390
5734
  showDecorations = false,
5735
+ enableCodeLens = true,
5391
5736
  buttonVisibility,
5392
5737
  editorOptions,
5393
5738
  settings,
@@ -5520,6 +5865,7 @@ var SsmlEditor = (0, import_react3.forwardRef)(function SsmlEditor2({
5520
5865
  getCurrentLineSsml: getCurrentLineSsml2,
5521
5866
  getFullSsml,
5522
5867
  getOuterVoiceName,
5868
+ handleCodeLensAction,
5523
5869
  openPopoverId,
5524
5870
  popoverVoiceName,
5525
5871
  popoverPosition,
@@ -5545,7 +5891,9 @@ var SsmlEditor = (0, import_react3.forwardRef)(function SsmlEditor2({
5545
5891
  getOuterVoiceName,
5546
5892
  onSelectionOverlayChange: refreshSelectionOverlay,
5547
5893
  onActiveTagsChange: updateActiveTags,
5548
- onSyntaxErrorChange: setSyntaxError
5894
+ onSyntaxErrorChange: setSyntaxError,
5895
+ enableCodeLens,
5896
+ onOpenPopover: handleCodeLensAction
5549
5897
  });
5550
5898
  (0, import_react3.useImperativeHandle)(
5551
5899
  ref,
@@ -5824,6 +6172,8 @@ var SsmlEditor = (0, import_react3.forwardRef)(function SsmlEditor2({
5824
6172
  SSML_HOVER_COPY,
5825
6173
  SSML_INSERTIONS,
5826
6174
  SsmlEditor,
5827
- createSsmlEditorInsertionDefinition
6175
+ createSsmlEditorInsertionDefinition,
6176
+ registerSsmlCodeLens,
6177
+ updateTagAttribute
5828
6178
  });
5829
6179
  //# sourceMappingURL=react.js.map