@seamly/web-ui 20.4.0 → 20.5.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.
Files changed (38) hide show
  1. package/build/dist/lib/index.debug.js +35 -68
  2. package/build/dist/lib/index.debug.min.js +1 -1
  3. package/build/dist/lib/index.debug.min.js.LICENSE.txt +4 -16
  4. package/build/dist/lib/index.js +374 -3850
  5. package/build/dist/lib/index.min.js +1 -1
  6. package/build/dist/lib/index.min.js.LICENSE.txt +0 -5
  7. package/build/dist/lib/standalone.js +394 -3862
  8. package/build/dist/lib/standalone.min.js +1 -1
  9. package/build/dist/lib/style-guide.js +200 -113
  10. package/build/dist/lib/style-guide.min.js +1 -1
  11. package/package.json +2 -4
  12. package/src/javascripts/api/index.js +17 -1
  13. package/src/javascripts/domains/config/reducer.js +2 -0
  14. package/src/javascripts/domains/forms/provider.js +14 -6
  15. package/src/javascripts/domains/visibility/actions.js +2 -0
  16. package/src/javascripts/domains/visibility/hooks.js +60 -1
  17. package/src/javascripts/domains/visibility/reducer.js +5 -0
  18. package/src/javascripts/domains/visibility/selectors.js +5 -0
  19. package/src/javascripts/domains/visibility/utils.js +5 -1
  20. package/src/javascripts/style-guide/components/app.js +2 -0
  21. package/src/javascripts/style-guide/states.js +30 -50
  22. package/src/javascripts/ui/components/conversation/event/card-component.js +1 -2
  23. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -9
  24. package/src/javascripts/ui/components/conversation/event/cta.js +1 -2
  25. package/src/javascripts/ui/components/conversation/event/participant.js +2 -11
  26. package/src/javascripts/ui/components/conversation/event/splash.js +1 -3
  27. package/src/javascripts/ui/components/conversation/event/text.js +9 -9
  28. package/src/javascripts/ui/components/layout/chat.js +52 -48
  29. package/src/javascripts/ui/components/suggestions/suggestions-list.js +12 -14
  30. package/src/javascripts/ui/components/view/deprecated-view.js +16 -11
  31. package/src/javascripts/ui/components/view/inline-view.js +13 -8
  32. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +3 -2
  33. package/src/javascripts/ui/hooks/seamly-state-hooks.js +4 -3
  34. package/src/javascripts/ui/hooks/use-seamly-chat.js +41 -29
  35. package/src/javascripts/ui/hooks/use-seamly-commands.js +16 -4
  36. package/src/javascripts/ui/utils/seamly-utils.js +16 -6
  37. package/src/javascripts/lib/parse-body.js +0 -10
  38. package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +0 -35
@@ -3568,7 +3568,7 @@ Emitter.prototype.hasListeners = function(event){
3568
3568
  "use strict";
3569
3569
 
3570
3570
 
3571
- var keys = __webpack_require__(686);
3571
+ var keys = __webpack_require__(215);
3572
3572
  var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
3573
3573
 
3574
3574
  var toStr = Object.prototype.toString;
@@ -5143,7 +5143,7 @@ module.exports = keysShim;
5143
5143
 
5144
5144
  /***/ }),
5145
5145
 
5146
- /***/ 686:
5146
+ /***/ 215:
5147
5147
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
5148
5148
 
5149
5149
  "use strict";
@@ -9041,14 +9041,16 @@ const orderHistory = events => {
9041
9041
  };
9042
9042
 
9043
9043
  const mergeHistory = (stateEvents, historyEvents) => {
9044
- const newHistoryEvents = historyEvents.filter(historyEvent => // Deduplicate the event streams
9045
- !stateEvents.find(stateEvent => stateEvent.payload.id === historyEvent.payload.id) && // Remove all non displayable participant messages
9044
+ const newStateEvents = stateEvents.filter(stateEvent => // Deduplicate the event streams, giving events in historyEvents
9045
+ // precedence so the server is able to push changes to events.
9046
+ !historyEvents.some(historyEvent => historyEvent.payload.id === stateEvent.payload.id));
9047
+ const newHistoryEvents = historyEvents.filter(historyEvent => // Remove all non displayable participant messages
9046
9048
  !(historyEvent.type === 'participant' && !historyEvent.payload.participant.introduction)) // Reverse is done here because the server sends the history in the order
9047
9049
  // newest to oldest. In the case of exactly the same occurredAt timestamps
9048
9050
  // these messages will be shown in the wrong order if not reversed. For
9049
9051
  // the normal merging logic there is no added effect.
9050
9052
  .reverse();
9051
- return orderHistory([...newHistoryEvents, ...stateEvents]);
9053
+ return orderHistory([...newHistoryEvents, ...newStateEvents]);
9052
9054
  };
9053
9055
 
9054
9056
  const participantReducer = (state, action) => {
@@ -9429,8 +9431,12 @@ const seamlyStateReducer = (state, action) => {
9429
9431
  });
9430
9432
 
9431
9433
  case SET_INITIAL_STATE:
9434
+ const {
9435
+ initialState
9436
+ } = action;
9432
9437
  return seamly_utils_objectSpread(seamly_utils_objectSpread({}, state), {}, {
9433
- initialState: action.initialState
9438
+ initialState,
9439
+ unreadEvents: initialState.unreadMessageCount
9434
9440
  });
9435
9441
 
9436
9442
  case SET_SERVICE_DATA_ITEM:
@@ -9815,15 +9821,20 @@ const useEntryTextLimit = () => {
9815
9821
  entryMeta: {
9816
9822
  options: {
9817
9823
  text
9824
+ },
9825
+ optionsOverride: {
9826
+ text: overrideText
9818
9827
  }
9819
9828
  }
9820
9829
  } = useSeamlyStateContext();
9821
9830
  const {
9822
9831
  limit
9823
- } = text || {};
9832
+ } = overrideText || text || {
9833
+ limit: null
9834
+ };
9824
9835
  return {
9825
- hasLimit: limit != null,
9826
- limit: limit != null ? limit : null
9836
+ hasLimit: limit !== null,
9837
+ limit: limit !== null ? limit : null
9827
9838
  };
9828
9839
  };
9829
9840
  const useSeamlyLayoutMode = () => {
@@ -9859,7 +9870,12 @@ const calculateVisibility = ({
9859
9870
  } = config;
9860
9871
  const {
9861
9872
  visible: defaultVisibility
9862
- } = defaults || {}; // Requesting open should override the responded check.
9873
+ } = defaults || {}; // The app layout should always be open by default.
9874
+
9875
+ if (layoutMode === 'app' && !previousVisibility) {
9876
+ return visibilityStates.open;
9877
+ } // Requesting open should override the responded check.
9878
+
9863
9879
 
9864
9880
  if (layoutMode === 'window' && hideOnNoUserResponse && requestedVisibility !== visibilityStates.open) {
9865
9881
  return hasResponded ? requestedVisibility || previousVisibility || visibilityStates.open : visibilityStates.hidden;
@@ -9878,6 +9894,7 @@ const calculateVisibility = ({
9878
9894
 
9879
9895
 
9880
9896
  const selectVisibility = createSelector(visibility_utils_selectState, state => state.visibility);
9897
+ const selectShowInlineView = createSelector(visibility_utils_selectState, state => state.showInlineView);
9881
9898
 
9882
9899
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/actions.js
9883
9900
  function actions_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -9895,6 +9912,7 @@ function actions_defineProperty(obj, key, value) { if (key in obj) { Object.defi
9895
9912
  const setFromStorage = visibility_utils_createAction('setFromStorage', visibility => ({
9896
9913
  visibility
9897
9914
  }));
9915
+ const setShowInlineView = visibility_utils_createAction('setShowInlineView');
9898
9916
  const validVisibilityStates = [visibilityStates.open, visibilityStates.minimized, visibilityStates.hidden];
9899
9917
  const actions_setVisibility = visibility_utils_createThunk('set', (requestedVisibility, {
9900
9918
  getState,
@@ -10173,6 +10191,7 @@ function reducer_defineProperty(obj, key, value) { if (key in obj) { Object.defi
10173
10191
 
10174
10192
  const initialState = reducer_objectSpread(reducer_objectSpread({}, defaultConfig), {}, {
10175
10193
  hideOnNoUserResponse: false,
10194
+ connectWhenInView: true,
10176
10195
  showDisclaimer: false,
10177
10196
  showFaq: false,
10178
10197
  customComponents: {},
@@ -10180,7 +10199,7 @@ const initialState = reducer_objectSpread(reducer_objectSpread({}, defaultConfig
10180
10199
  preChatEvents: []
10181
10200
  });
10182
10201
 
10183
- const configKeys = ['hideOnNoUserResponse', 'showDisclaimer', 'showFaq', 'namespace', 'customComponents', 'defaults', 'layoutMode', 'api', 'zIndex', 'context', 'appContainerClassNames', 'messages', 'visible', 'visibilityCallback', 'errorCallback', 'agentParticipant', 'userParticipant', 'startChatIcon'];
10202
+ const configKeys = ['hideOnNoUserResponse', 'connectWhenInView', 'showDisclaimer', 'showFaq', 'namespace', 'customComponents', 'defaults', 'layoutMode', 'api', 'zIndex', 'context', 'appContainerClassNames', 'messages', 'visible', 'visibilityCallback', 'errorCallback', 'agentParticipant', 'userParticipant', 'startChatIcon'];
10184
10203
 
10185
10204
  const updateState = (state, {
10186
10205
  config
@@ -10228,6 +10247,8 @@ const updateState = (state, {
10228
10247
 
10229
10248
 
10230
10249
 
10250
+ ;// CONCATENATED MODULE: external "preact/compat"
10251
+ const compat_namespaceObject = require("preact/compat");
10231
10252
  ;// CONCATENATED MODULE: ./src/javascripts/lib/css.js
10232
10253
 
10233
10254
  /**
@@ -11487,6 +11508,7 @@ function useUserHasResponded() {
11487
11508
 
11488
11509
 
11489
11510
 
11511
+
11490
11512
  const useVisibility = () => {
11491
11513
  const dispatch = useStoreDispatch();
11492
11514
  const visible = hooks_useSelector(selectVisibility);
@@ -11502,6 +11524,69 @@ const useVisibility = () => {
11502
11524
  setVisibility
11503
11525
  };
11504
11526
  };
11527
+ /**
11528
+ * Custom hook which enables initializing of IntersectionObserver on any node ref.
11529
+ * @param {object} options Hook options.
11530
+ * @param {boolean=} options.freezeOnceVisible Stops observing when the root element is visible.
11531
+ * @param {boolean=} options.enabled Determines if useIntersect is enabled.
11532
+ */
11533
+
11534
+ const useIntersect = ({
11535
+ freezeOnceVisible = false,
11536
+ enabled = true
11537
+ }) => {
11538
+ const [entry, setEntry] = (0,hooks_namespaceObject.useState)(null);
11539
+ const containerRef = (0,hooks_namespaceObject.useRef)(null);
11540
+ const isVisible = !!entry?.isIntersecting || !enabled;
11541
+ const frozen = isVisible && freezeOnceVisible;
11542
+
11543
+ const observerCallback = ([updatedEntry]) => setEntry(updatedEntry);
11544
+
11545
+ (0,hooks_namespaceObject.useEffect)(() => {
11546
+ const node = containerRef?.current;
11547
+ const hasIOSupport = !!window.IntersectionObserver;
11548
+
11549
+ if (!node && "production" === 'development') {} // Return an arrow function to have a consistent return value
11550
+
11551
+
11552
+ if (!hasIOSupport || frozen || !node || !enabled) return () => undefined;
11553
+ const observerOptions = {
11554
+ threshold: 0,
11555
+ root: null,
11556
+ rootMargin: '0%'
11557
+ };
11558
+ const observer = new IntersectionObserver(observerCallback, observerOptions);
11559
+ observer.observe(node);
11560
+ return () => observer.disconnect();
11561
+ }, [enabled, frozen]);
11562
+ return {
11563
+ isVisible,
11564
+ containerRef
11565
+ };
11566
+ };
11567
+
11568
+ const useShowInlineView = () => {
11569
+ const dispatch = useStoreDispatch();
11570
+ const {
11571
+ connectWhenInView
11572
+ } = useConfig();
11573
+ const showInlineView = hooks_useSelector(selectShowInlineView);
11574
+ const {
11575
+ containerRef,
11576
+ isVisible
11577
+ } = useIntersect({
11578
+ enabled: connectWhenInView,
11579
+ freezeOnceVisible: true
11580
+ });
11581
+ (0,hooks_namespaceObject.useEffect)(() => {
11582
+ if (!isVisible) return;
11583
+ dispatch(setShowInlineView());
11584
+ }, [dispatch, isVisible]);
11585
+ return {
11586
+ containerRef,
11587
+ showInlineView
11588
+ };
11589
+ };
11505
11590
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/reducer.js
11506
11591
  function visibility_reducer_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11507
11592
 
@@ -11513,7 +11598,8 @@ function visibility_reducer_defineProperty(obj, key, value) { if (key in obj) {
11513
11598
 
11514
11599
 
11515
11600
  const visibility_reducer_initialState = {
11516
- visibility: visibilityStates.initialize
11601
+ visibility: visibilityStates.initialize,
11602
+ showInlineView: false
11517
11603
  };
11518
11604
  /* harmony default export */ const visibility_reducer = (visibility_utils_createReducer({
11519
11605
  [setFromStorage]: (state, {
@@ -11525,7 +11611,10 @@ const visibility_reducer_initialState = {
11525
11611
  payload: visibility
11526
11612
  }) => visibility ? visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
11527
11613
  visibility
11528
- }) : state
11614
+ }) : state,
11615
+ [setShowInlineView]: state => visibility_reducer_objectSpread(visibility_reducer_objectSpread({}, state), {}, {
11616
+ showInlineView: true
11617
+ })
11529
11618
  }, visibility_reducer_initialState));
11530
11619
  ;// CONCATENATED MODULE: ./src/javascripts/domains/visibility/index.js
11531
11620
 
@@ -11596,7 +11685,8 @@ const useSeamlyCommands = () => {
11596
11685
  const hasResponded = useUserHasResponded();
11597
11686
  const hasConversation = useSeamlyHasConversation();
11598
11687
  const {
11599
- visible: visibility
11688
+ visible: visibility,
11689
+ setVisibility
11600
11690
  } = useVisibility();
11601
11691
  const unreadMessageCount = useSeamlyUnreadCount();
11602
11692
  const emitEvent = (0,hooks_namespaceObject.useCallback)((...args) => {
@@ -11654,7 +11744,9 @@ const useSeamlyCommands = () => {
11654
11744
  type: use_seamly_commands_ADD_EVENT,
11655
11745
  event: {
11656
11746
  type: 'message',
11657
- payload: message
11747
+ payload: use_seamly_commands_objectSpread(use_seamly_commands_objectSpread({}, message), {}, {
11748
+ optimisticallyInjected: true
11749
+ })
11658
11750
  }
11659
11751
  });
11660
11752
  }, [api, dispatch, emitEvent, getTextMessageBase]);
@@ -11752,11 +11844,16 @@ const useSeamlyCommands = () => {
11752
11844
  type: use_seamly_commands_SET_INITIAL_STATE,
11753
11845
  initialState
11754
11846
  });
11847
+
11848
+ if (initialState.userResponded) {
11849
+ dispatch(setHasResponded(initialState.userResponded));
11850
+ setVisibility(visibilityStates.open);
11851
+ }
11755
11852
  }
11756
11853
  }).catch(error => {
11757
11854
  dispatch(set(error));
11758
11855
  });
11759
- }, [api, dispatch]);
11856
+ }, [api, dispatch, setVisibility]);
11760
11857
  return {
11761
11858
  connect,
11762
11859
  start,
@@ -11769,6 +11866,7 @@ const useSeamlyCommands = () => {
11769
11866
  addMessageBubble,
11770
11867
  addUploadBubble,
11771
11868
  addDivider,
11869
+ apiConnected: api.connected,
11772
11870
  apiConfigReady: api.configReady
11773
11871
  };
11774
11872
  };
@@ -11898,11 +11996,12 @@ const useSeamlyEntry = () => {
11898
11996
  default: defaultEntry,
11899
11997
  active,
11900
11998
  userSelected,
11901
- options: entryOptions
11999
+ options: entryOptions,
12000
+ optionsOverride: entryOptionsOverride
11902
12001
  } = useSeamlyStateContext().entryMeta;
11903
12002
  const dispatch = use_seamly_dispatch();
11904
12003
  const activeEntry = userSelected || active || defaultEntry;
11905
- const activeEntryOptions = entryOptions[activeEntry] || {};
12004
+ const activeEntryOptions = entryOptionsOverride[activeEntry] || entryOptions[activeEntry] || {};
11906
12005
  const setBlockAutoEntrySwitch = (0,hooks_namespaceObject.useCallback)(value => {
11907
12006
  dispatch({
11908
12007
  type: seamly_entry_hooks_SET_BLOCK_AUTO_ENTRY_SWITCH,
@@ -11948,6 +12047,7 @@ const useSeamlyEntry = () => {
11948
12047
 
11949
12048
 
11950
12049
 
12050
+
11951
12051
  const {
11952
12052
  SET_IS_LOADING: use_seamly_chat_SET_IS_LOADING
11953
12053
  } = seamlyActions;
@@ -11957,28 +12057,31 @@ const useSeamlyChat = () => {
11957
12057
  t
11958
12058
  } = useI18n();
11959
12059
  const {
11960
- layoutMode
11961
- } = useConfig();
12060
+ isInline,
12061
+ isWindow
12062
+ } = useSeamlyLayoutMode();
11962
12063
  const {
11963
12064
  isOpen,
11964
12065
  isVisible,
11965
12066
  setVisibility
11966
12067
  } = useVisibility();
12068
+ const showInlineView = hooks_useSelector(selectShowInlineView);
11967
12069
  const dispatch = use_seamly_dispatch();
11968
12070
  const events = useEvents();
11969
12071
  const spinnerTimeout = (0,hooks_namespaceObject.useRef)(null);
11970
12072
  const {
11971
12073
  start,
11972
12074
  connect,
11973
- apiConfigReady
12075
+ apiConfigReady,
12076
+ apiConnected
11974
12077
  } = use_seamly_commands();
11975
12078
  const hasConversation = useSeamlyHasConversation();
11976
12079
  const prevIsOpen = (0,hooks_namespaceObject.useRef)(null);
11977
12080
  const prevIsVisible = (0,hooks_namespaceObject.useRef)(null);
12081
+ const startCalled = (0,hooks_namespaceObject.useRef)(false);
11978
12082
  const {
11979
12083
  sendAssertive
11980
12084
  } = useLiveRegion();
11981
- const connectCalled = (0,hooks_namespaceObject.useRef)(false);
11982
12085
  const hasEvents = events.length > 0;
11983
12086
  (0,hooks_namespaceObject.useEffect)(() => {
11984
12087
  if (isVisible) {
@@ -12027,22 +12130,34 @@ const useSeamlyChat = () => {
12027
12130
  }
12028
12131
  }, [hasEvents, dispatch]);
12029
12132
  (0,hooks_namespaceObject.useEffect)(() => {
12030
- // This is needed to reset the ref to allow connect to happen again.
12133
+ // This is needed to reset the ref to allow connect and start to happen again.
12031
12134
  // Mostly due to Interrupt situations and a reset being called.
12032
- if (!hasConversation || !apiConfigReady) {
12033
- connectCalled.current = false;
12135
+ if (!apiConfigReady || !apiConnected) {
12136
+ startCalled.current = false;
12137
+ }
12138
+ }, [apiConfigReady, apiConnected]);
12139
+ const connectAndStart = (0,hooks_namespaceObject.useCallback)(async () => {
12140
+ // We don't connect if we are already connected to the api to avoid multiple in-flight connection processes.
12141
+ if (!apiConnected) {
12142
+ await connect();
12143
+ } // We only start a conversation when the chat interface is either 'open' or if using the inline view if it's 'open' or 'minimized'.
12144
+
12145
+
12146
+ if (isOpen || isVisible && isInline) {
12147
+ start();
12148
+ startCalled.current = true;
12034
12149
  }
12035
- }, [hasConversation, apiConfigReady]);
12150
+ }, [apiConnected, connect, isInline, isOpen, isVisible, start]);
12036
12151
  (0,hooks_namespaceObject.useEffect)(() => {
12037
- // We don't connect minimised or hidden window interfaces unless
12038
- // they had been connected before.
12039
- // We also keep track of whether connect was called before to avoid
12040
- // multiple in-flight connection processes.
12041
- if (layoutMode === 'window' && !isOpen && !hasConversation || connectCalled.current || !apiConfigReady) {
12152
+ // We dont't connect or start when the apiConfig is not ready yet.
12153
+ // We also keep track of whether start has been called to avoid multiple in-flight connection processes.
12154
+ // We check if the window view is not open and no conversation is started yet.
12155
+ // Lastly we check if the inline view is not scrolled in to view.
12156
+ if (!apiConfigReady || startCalled.current || isWindow && !isOpen && !hasConversation || isInline && !showInlineView) {
12042
12157
  return;
12043
12158
  }
12044
12159
 
12045
- if (hasConversation) {
12160
+ if (hasConversation && isOpen) {
12046
12161
  // We deactivate the extra startup loading spinner when a conversation is available
12047
12162
  // We also stop setting the loading indicator in the first place to avoid a flash.
12048
12163
  clearTimeout(spinnerTimeout.current);
@@ -12052,11 +12167,8 @@ const useSeamlyChat = () => {
12052
12167
  });
12053
12168
  }
12054
12169
 
12055
- connect().then(() => {
12056
- start();
12057
- });
12058
- connectCalled.current = true;
12059
- }, [isOpen, hasConversation, apiConfigReady, start, connect, dispatch, layoutMode]);
12170
+ connectAndStart();
12171
+ }, [apiConfigReady, connectAndStart, dispatch, hasConversation, isInline, isOpen, isWindow, showInlineView]);
12060
12172
 
12061
12173
  const openChat = () => {
12062
12174
  setVisibility(visibilityStates.open);
@@ -13055,6 +13167,7 @@ function provider_objectWithoutPropertiesLoose(source, excluded) { if (source ==
13055
13167
 
13056
13168
 
13057
13169
 
13170
+
13058
13171
  function FormProvider(_ref) {
13059
13172
  let {
13060
13173
  children,
@@ -13110,13 +13223,13 @@ function FormProvider(_ref) {
13110
13223
  setIsSubmitted(!ariaDisabled);
13111
13224
 
13112
13225
  if (!ariaDisabled && validationIsValid) {
13226
+ dispatch(setHasResponded(true));
13113
13227
  onSubmit(values, {
13114
13228
  updateControlValue,
13115
13229
  setError
13116
13230
  });
13117
13231
  }
13118
- }, [validationIsValid, onSubmit, values, updateControlValue, setError]); //
13119
-
13232
+ }, [validationIsValid, dispatch, onSubmit, values, updateControlValue, setError]);
13120
13233
  (0,hooks_namespaceObject.useEffect)(() => {
13121
13234
  if (onError) {
13122
13235
  onError({
@@ -14014,15 +14127,13 @@ const SuggestionsList = ({
14014
14127
  suggestions = [],
14015
14128
  onClickSuggestion,
14016
14129
  hasIcon = true
14017
- }) => {
14018
- return (0,jsx_runtime_namespaceObject.jsx)("ul", {
14019
- className: css_className('suggestions__list', givenClassName),
14020
- children: suggestions.map(suggestion => (0,jsx_runtime_namespaceObject.jsx)(suggestions_item, suggestions_list_objectSpread({
14021
- hasIcon: hasIcon,
14022
- onClick: onClickSuggestion
14023
- }, suggestion), suggestion.id))
14024
- });
14025
- };
14130
+ }) => (0,jsx_runtime_namespaceObject.jsx)("ul", {
14131
+ className: css_className('suggestions__list', givenClassName),
14132
+ children: suggestions.map(suggestion => (0,jsx_runtime_namespaceObject.jsx)(suggestions_item, suggestions_list_objectSpread({
14133
+ hasIcon: hasIcon,
14134
+ onClick: onClickSuggestion
14135
+ }, suggestion), suggestion.id))
14136
+ });
14026
14137
 
14027
14138
  /* harmony default export */ const suggestions_list = (SuggestionsList);
14028
14139
  ;// CONCATENATED MODULE: ./src/javascripts/ui/components/suggestions/index.js
@@ -14195,10 +14306,10 @@ const Suggestions = ({
14195
14306
 
14196
14307
 
14197
14308
 
14198
- const Chat = ({
14309
+ const Chat = (0,compat_namespaceObject.forwardRef)(({
14199
14310
  children,
14200
14311
  className: givenClassName = ''
14201
- }) => {
14312
+ }, forwardedRef) => {
14202
14313
  const {
14203
14314
  isOpen,
14204
14315
  isVisible,
@@ -14237,6 +14348,7 @@ const Chat = ({
14237
14348
  className: css_className(classNames),
14238
14349
  onKeyDown: onKeyDownHandler,
14239
14350
  tabIndex: "-1",
14351
+ ref: forwardedRef,
14240
14352
  "aria-label": t('chat.srLabel'),
14241
14353
  children: [(0,jsx_runtime_namespaceObject.jsx)("div", {
14242
14354
  className: css_className('chat-wrapper'),
@@ -14245,8 +14357,7 @@ const Chat = ({
14245
14357
  isAside: true
14246
14358
  })]
14247
14359
  });
14248
- };
14249
-
14360
+ });
14250
14361
  /* harmony default export */ const chat = (Chat);
14251
14362
  ;// CONCATENATED MODULE: ./src/javascripts/ui/components/layout/interrupt.js
14252
14363
 
@@ -14760,3797 +14871,190 @@ function MessageContainer(_ref) {
14760
14871
  children: t(isTranslated ? 'translations.toggle.hideButtonText' : 'translations.toggle.showButtonText')
14761
14872
  })
14762
14873
  })]
14763
- }))
14764
- });
14765
- }
14766
-
14767
- /* harmony default export */ const message_container = (MessageContainer);
14768
- ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/choice-prompt.js
14769
- const choice_prompt_excluded = ["event", "children"];
14770
-
14771
- function choice_prompt_objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = choice_prompt_objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
14772
-
14773
- function choice_prompt_objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
14774
-
14775
- function choice_prompt_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
14776
-
14777
- function choice_prompt_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? choice_prompt_ownKeys(Object(source), !0).forEach(function (key) { choice_prompt_defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : choice_prompt_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
14778
-
14779
- function choice_prompt_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
14780
-
14781
-
14782
-
14783
-
14784
-
14785
-
14786
-
14787
-
14788
-
14789
-
14790
-
14791
-
14792
-
14793
- const useChoicePrompt = event => {
14794
- const {
14795
- payload
14796
- } = event;
14797
- const [showOptions, setShowOptions] = (0,hooks_namespaceObject.useState)(false);
14798
- const {
14799
- sendAction,
14800
- addMessageBubble,
14801
- addDivider
14802
- } = use_seamly_commands();
14803
- const {
14804
- activeServiceSessionId
14805
- } = useSeamlyServiceInfo();
14806
- const lastEventId = useLastMessageEventId();
14807
- const [body] = useTranslatedEventData(event);
14808
- const {
14809
- service
14810
- } = payload;
14811
- const subEvent = (0,hooks_namespaceObject.useMemo)(() => {
14812
- return choice_prompt_objectSpread(choice_prompt_objectSpread({}, event), {}, {
14813
- payload: choice_prompt_objectSpread(choice_prompt_objectSpread({}, event.payload), {}, {
14814
- body: event.payload.body?.prompt,
14815
- translatedBody: event.payload.translatedBody && choice_prompt_objectSpread(choice_prompt_objectSpread({}, event.payload.translatedBody), {}, {
14816
- data: event.payload.translatedBody.data.prompt
14817
- })
14818
- })
14819
- });
14820
- }, [event]);
14821
- const chooseAgain = body.chooseAgain && activeServiceSessionId === service.serviceSessionId && payload.id !== lastEventId;
14822
- (0,hooks_namespaceObject.useEffect)(() => {
14823
- setShowOptions(payload.id === lastEventId);
14824
- }, [payload, lastEventId]);
14825
-
14826
- const onChoiceClickHandler = choice => {
14827
- if (chooseAgain) {
14828
- addDivider('new_topic');
14829
- }
14830
-
14831
- addMessageBubble(choice.text);
14832
- sendAction({
14833
- type: actionTypes.pickChoice,
14834
- originMessage: payload.id,
14835
- choice: {
14836
- id: choice.id,
14837
- text: choice.text,
14838
- chooseAgain
14839
- }
14840
- });
14841
- setShowOptions(false);
14842
- };
14843
-
14844
- const onChooseAgainClickHandler = () => {
14845
- setShowOptions(s => !s);
14846
- };
14847
-
14848
- return {
14849
- body,
14850
- subEvent,
14851
- showOptions,
14852
- chooseAgain,
14853
- onChoiceClickHandler,
14854
- onChooseAgainClickHandler
14855
- };
14856
- };
14857
-
14858
- const ChoicePrompt = _ref => {
14859
- let {
14860
- event,
14861
- children
14862
- } = _ref,
14863
- props = choice_prompt_objectWithoutProperties(_ref, choice_prompt_excluded);
14864
-
14865
- const {
14866
- t
14867
- } = useI18n();
14868
- const descriptorId = useGeneratedId();
14869
- const {
14870
- body,
14871
- subEvent,
14872
- showOptions,
14873
- chooseAgain,
14874
- onChoiceClickHandler,
14875
- onChooseAgainClickHandler
14876
- } = useChoicePrompt(event);
14877
- return (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
14878
- children: [(0,external_preact_namespaceObject.toChildArray)(children).map(child => {
14879
- child.props = choice_prompt_objectSpread(choice_prompt_objectSpread({}, child.props), {}, {
14880
- event: subEvent,
14881
- descriptorId,
14882
- showTranslationToggle: false
14883
- });
14884
- return child;
14885
- }), chooseAgain && (0,jsx_runtime_namespaceObject.jsxs)("button", {
14886
- type: "button",
14887
- className: css_className('button', 'button--secondary', 'button--choose-again'),
14888
- "aria-expanded": showOptions ? 'true' : 'false',
14889
- onClick: onChooseAgainClickHandler,
14890
- "aria-describedby": descriptorId,
14891
- children: [showOptions ? t('message.choicePrompts.cancelChooseAgain') : t('message.choicePrompts.chooseAgain'), (0,jsx_runtime_namespaceObject.jsx)(icon, {
14892
- name: "chevronDown",
14893
- size: "8"
14894
- })]
14895
- }), showOptions && (0,jsx_runtime_namespaceObject.jsx)(message_container, choice_prompt_objectSpread(choice_prompt_objectSpread({
14896
- type: "choice-prompt",
14897
- showParticipant: false,
14898
- event: event
14899
- }, props), {}, {
14900
- children: (0,jsx_runtime_namespaceObject.jsx)("ul", {
14901
- className: css_className('choice-prompt', 'choice-prompt--many'),
14902
- children: body.choices.map(choice => (0,jsx_runtime_namespaceObject.jsx)("li", {
14903
- className: css_className('choice-prompt__item', {
14904
- [`choice-prompt__item--${choice.category}`]: choice.category
14905
- }),
14906
- children: (0,jsx_runtime_namespaceObject.jsx)("button", {
14907
- type: "button",
14908
- className: css_className('button', 'button--primary'),
14909
- onClick: () => {
14910
- onChoiceClickHandler(choice);
14911
- },
14912
- children: choice.text
14913
- })
14914
- }, choice.id))
14915
- })
14916
- }))]
14917
- });
14918
- };
14919
-
14920
- /* harmony default export */ const choice_prompt = (ChoicePrompt);
14921
- ;// CONCATENATED MODULE: ./node_modules/marked/lib/marked.esm.js
14922
- /**
14923
- * marked - a markdown parser
14924
- * Copyright (c) 2011-2022, Christopher Jeffrey. (MIT Licensed)
14925
- * https://github.com/markedjs/marked
14926
- */
14927
-
14928
- /**
14929
- * DO NOT EDIT THIS FILE
14930
- * The code in this file is generated from files in ./src/
14931
- */
14932
-
14933
- function getDefaults() {
14934
- return {
14935
- baseUrl: null,
14936
- breaks: false,
14937
- extensions: null,
14938
- gfm: true,
14939
- headerIds: true,
14940
- headerPrefix: '',
14941
- highlight: null,
14942
- langPrefix: 'language-',
14943
- mangle: true,
14944
- pedantic: false,
14945
- renderer: null,
14946
- sanitize: false,
14947
- sanitizer: null,
14948
- silent: false,
14949
- smartLists: false,
14950
- smartypants: false,
14951
- tokenizer: null,
14952
- walkTokens: null,
14953
- xhtml: false
14954
- };
14955
- }
14956
-
14957
- let defaults = getDefaults();
14958
-
14959
- function changeDefaults(newDefaults) {
14960
- defaults = newDefaults;
14961
- }
14962
-
14963
- /**
14964
- * Helpers
14965
- */
14966
- const escapeTest = /[&<>"']/;
14967
- const escapeReplace = /[&<>"']/g;
14968
- const escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
14969
- const escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
14970
- const escapeReplacements = {
14971
- '&': '&amp;',
14972
- '<': '&lt;',
14973
- '>': '&gt;',
14974
- '"': '&quot;',
14975
- "'": '&#39;'
14976
- };
14977
- const getEscapeReplacement = (ch) => escapeReplacements[ch];
14978
- function marked_esm_escape(html, encode) {
14979
- if (encode) {
14980
- if (escapeTest.test(html)) {
14981
- return html.replace(escapeReplace, getEscapeReplacement);
14982
- }
14983
- } else {
14984
- if (escapeTestNoEncode.test(html)) {
14985
- return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
14986
- }
14987
- }
14988
-
14989
- return html;
14990
- }
14991
-
14992
- const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
14993
-
14994
- /**
14995
- * @param {string} html
14996
- */
14997
- function marked_esm_unescape(html) {
14998
- // explicitly match decimal, hex, and named HTML entities
14999
- return html.replace(unescapeTest, (_, n) => {
15000
- n = n.toLowerCase();
15001
- if (n === 'colon') return ':';
15002
- if (n.charAt(0) === '#') {
15003
- return n.charAt(1) === 'x'
15004
- ? String.fromCharCode(parseInt(n.substring(2), 16))
15005
- : String.fromCharCode(+n.substring(1));
15006
- }
15007
- return '';
15008
- });
15009
- }
15010
-
15011
- const caret = /(^|[^\[])\^/g;
15012
-
15013
- /**
15014
- * @param {string | RegExp} regex
15015
- * @param {string} opt
15016
- */
15017
- function edit(regex, opt) {
15018
- regex = typeof regex === 'string' ? regex : regex.source;
15019
- opt = opt || '';
15020
- const obj = {
15021
- replace: (name, val) => {
15022
- val = val.source || val;
15023
- val = val.replace(caret, '$1');
15024
- regex = regex.replace(name, val);
15025
- return obj;
15026
- },
15027
- getRegex: () => {
15028
- return new RegExp(regex, opt);
15029
- }
15030
- };
15031
- return obj;
15032
- }
15033
-
15034
- const nonWordAndColonTest = /[^\w:]/g;
15035
- const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
15036
-
15037
- /**
15038
- * @param {boolean} sanitize
15039
- * @param {string} base
15040
- * @param {string} href
15041
- */
15042
- function cleanUrl(sanitize, base, href) {
15043
- if (sanitize) {
15044
- let prot;
15045
- try {
15046
- prot = decodeURIComponent(marked_esm_unescape(href))
15047
- .replace(nonWordAndColonTest, '')
15048
- .toLowerCase();
15049
- } catch (e) {
15050
- return null;
15051
- }
15052
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
15053
- return null;
15054
- }
15055
- }
15056
- if (base && !originIndependentUrl.test(href)) {
15057
- href = resolveUrl(base, href);
15058
- }
15059
- try {
15060
- href = encodeURI(href).replace(/%25/g, '%');
15061
- } catch (e) {
15062
- return null;
15063
- }
15064
- return href;
15065
- }
15066
-
15067
- const baseUrls = {};
15068
- const justDomain = /^[^:]+:\/*[^/]*$/;
15069
- const protocol = /^([^:]+:)[\s\S]*$/;
15070
- const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
15071
-
15072
- /**
15073
- * @param {string} base
15074
- * @param {string} href
15075
- */
15076
- function resolveUrl(base, href) {
15077
- if (!baseUrls[' ' + base]) {
15078
- // we can ignore everything in base after the last slash of its path component,
15079
- // but we might need to add _that_
15080
- // https://tools.ietf.org/html/rfc3986#section-3
15081
- if (justDomain.test(base)) {
15082
- baseUrls[' ' + base] = base + '/';
15083
- } else {
15084
- baseUrls[' ' + base] = rtrim(base, '/', true);
15085
- }
15086
- }
15087
- base = baseUrls[' ' + base];
15088
- const relativeBase = base.indexOf(':') === -1;
15089
-
15090
- if (href.substring(0, 2) === '//') {
15091
- if (relativeBase) {
15092
- return href;
15093
- }
15094
- return base.replace(protocol, '$1') + href;
15095
- } else if (href.charAt(0) === '/') {
15096
- if (relativeBase) {
15097
- return href;
15098
- }
15099
- return base.replace(domain, '$1') + href;
15100
- } else {
15101
- return base + href;
15102
- }
15103
- }
15104
-
15105
- const noopTest = { exec: function noopTest() {} };
15106
-
15107
- function merge(obj) {
15108
- let i = 1,
15109
- target,
15110
- key;
15111
-
15112
- for (; i < arguments.length; i++) {
15113
- target = arguments[i];
15114
- for (key in target) {
15115
- if (Object.prototype.hasOwnProperty.call(target, key)) {
15116
- obj[key] = target[key];
15117
- }
15118
- }
15119
- }
15120
-
15121
- return obj;
15122
- }
15123
-
15124
- function splitCells(tableRow, count) {
15125
- // ensure that every cell-delimiting pipe has a space
15126
- // before it to distinguish it from an escaped pipe
15127
- const row = tableRow.replace(/\|/g, (match, offset, str) => {
15128
- let escaped = false,
15129
- curr = offset;
15130
- while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
15131
- if (escaped) {
15132
- // odd number of slashes means | is escaped
15133
- // so we leave it alone
15134
- return '|';
15135
- } else {
15136
- // add space before unescaped |
15137
- return ' |';
15138
- }
15139
- }),
15140
- cells = row.split(/ \|/);
15141
- let i = 0;
15142
-
15143
- // First/last cell in a row cannot be empty if it has no leading/trailing pipe
15144
- if (!cells[0].trim()) { cells.shift(); }
15145
- if (cells.length > 0 && !cells[cells.length - 1].trim()) { cells.pop(); }
15146
-
15147
- if (cells.length > count) {
15148
- cells.splice(count);
15149
- } else {
15150
- while (cells.length < count) cells.push('');
15151
- }
15152
-
15153
- for (; i < cells.length; i++) {
15154
- // leading or trailing whitespace is ignored per the gfm spec
15155
- cells[i] = cells[i].trim().replace(/\\\|/g, '|');
15156
- }
15157
- return cells;
15158
- }
15159
-
15160
- /**
15161
- * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
15162
- * /c*$/ is vulnerable to REDOS.
15163
- *
15164
- * @param {string} str
15165
- * @param {string} c
15166
- * @param {boolean} invert Remove suffix of non-c chars instead. Default falsey.
15167
- */
15168
- function rtrim(str, c, invert) {
15169
- const l = str.length;
15170
- if (l === 0) {
15171
- return '';
15172
- }
15173
-
15174
- // Length of suffix matching the invert condition.
15175
- let suffLen = 0;
15176
-
15177
- // Step left until we fail to match the invert condition.
15178
- while (suffLen < l) {
15179
- const currChar = str.charAt(l - suffLen - 1);
15180
- if (currChar === c && !invert) {
15181
- suffLen++;
15182
- } else if (currChar !== c && invert) {
15183
- suffLen++;
15184
- } else {
15185
- break;
15186
- }
15187
- }
15188
-
15189
- return str.slice(0, l - suffLen);
15190
- }
15191
-
15192
- function marked_esm_findClosingBracket(str, b) {
15193
- if (str.indexOf(b[1]) === -1) {
15194
- return -1;
15195
- }
15196
- const l = str.length;
15197
- let level = 0,
15198
- i = 0;
15199
- for (; i < l; i++) {
15200
- if (str[i] === '\\') {
15201
- i++;
15202
- } else if (str[i] === b[0]) {
15203
- level++;
15204
- } else if (str[i] === b[1]) {
15205
- level--;
15206
- if (level < 0) {
15207
- return i;
15208
- }
15209
- }
15210
- }
15211
- return -1;
15212
- }
15213
-
15214
- function checkSanitizeDeprecation(opt) {
15215
- if (opt && opt.sanitize && !opt.silent) {
15216
- console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
15217
- }
15218
- }
15219
-
15220
- // copied from https://stackoverflow.com/a/5450113/806777
15221
- /**
15222
- * @param {string} pattern
15223
- * @param {number} count
15224
- */
15225
- function repeatString(pattern, count) {
15226
- if (count < 1) {
15227
- return '';
15228
- }
15229
- let result = '';
15230
- while (count > 1) {
15231
- if (count & 1) {
15232
- result += pattern;
15233
- }
15234
- count >>= 1;
15235
- pattern += pattern;
15236
- }
15237
- return result + pattern;
15238
- }
15239
-
15240
- function outputLink(cap, link, raw, lexer) {
15241
- const href = link.href;
15242
- const title = link.title ? marked_esm_escape(link.title) : null;
15243
- const text = cap[1].replace(/\\([\[\]])/g, '$1');
15244
-
15245
- if (cap[0].charAt(0) !== '!') {
15246
- lexer.state.inLink = true;
15247
- const token = {
15248
- type: 'link',
15249
- raw,
15250
- href,
15251
- title,
15252
- text,
15253
- tokens: lexer.inlineTokens(text, [])
15254
- };
15255
- lexer.state.inLink = false;
15256
- return token;
15257
- }
15258
- return {
15259
- type: 'image',
15260
- raw,
15261
- href,
15262
- title,
15263
- text: marked_esm_escape(text)
15264
- };
15265
- }
15266
-
15267
- function indentCodeCompensation(raw, text) {
15268
- const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
15269
-
15270
- if (matchIndentToCode === null) {
15271
- return text;
15272
- }
15273
-
15274
- const indentToCode = matchIndentToCode[1];
15275
-
15276
- return text
15277
- .split('\n')
15278
- .map(node => {
15279
- const matchIndentInNode = node.match(/^\s+/);
15280
- if (matchIndentInNode === null) {
15281
- return node;
15282
- }
15283
-
15284
- const [indentInNode] = matchIndentInNode;
15285
-
15286
- if (indentInNode.length >= indentToCode.length) {
15287
- return node.slice(indentToCode.length);
15288
- }
15289
-
15290
- return node;
15291
- })
15292
- .join('\n');
15293
- }
15294
-
15295
- /**
15296
- * Tokenizer
15297
- */
15298
- class Tokenizer {
15299
- constructor(options) {
15300
- this.options = options || defaults;
15301
- }
15302
-
15303
- space(src) {
15304
- const cap = this.rules.block.newline.exec(src);
15305
- if (cap && cap[0].length > 0) {
15306
- return {
15307
- type: 'space',
15308
- raw: cap[0]
15309
- };
15310
- }
15311
- }
15312
-
15313
- code(src) {
15314
- const cap = this.rules.block.code.exec(src);
15315
- if (cap) {
15316
- const text = cap[0].replace(/^ {1,4}/gm, '');
15317
- return {
15318
- type: 'code',
15319
- raw: cap[0],
15320
- codeBlockStyle: 'indented',
15321
- text: !this.options.pedantic
15322
- ? rtrim(text, '\n')
15323
- : text
15324
- };
15325
- }
15326
- }
15327
-
15328
- fences(src) {
15329
- const cap = this.rules.block.fences.exec(src);
15330
- if (cap) {
15331
- const raw = cap[0];
15332
- const text = indentCodeCompensation(raw, cap[3] || '');
15333
-
15334
- return {
15335
- type: 'code',
15336
- raw,
15337
- lang: cap[2] ? cap[2].trim() : cap[2],
15338
- text
15339
- };
15340
- }
15341
- }
15342
-
15343
- heading(src) {
15344
- const cap = this.rules.block.heading.exec(src);
15345
- if (cap) {
15346
- let text = cap[2].trim();
15347
-
15348
- // remove trailing #s
15349
- if (/#$/.test(text)) {
15350
- const trimmed = rtrim(text, '#');
15351
- if (this.options.pedantic) {
15352
- text = trimmed.trim();
15353
- } else if (!trimmed || / $/.test(trimmed)) {
15354
- // CommonMark requires space before trailing #s
15355
- text = trimmed.trim();
15356
- }
15357
- }
15358
-
15359
- const token = {
15360
- type: 'heading',
15361
- raw: cap[0],
15362
- depth: cap[1].length,
15363
- text,
15364
- tokens: []
15365
- };
15366
- this.lexer.inline(token.text, token.tokens);
15367
- return token;
15368
- }
15369
- }
15370
-
15371
- hr(src) {
15372
- const cap = this.rules.block.hr.exec(src);
15373
- if (cap) {
15374
- return {
15375
- type: 'hr',
15376
- raw: cap[0]
15377
- };
15378
- }
15379
- }
15380
-
15381
- blockquote(src) {
15382
- const cap = this.rules.block.blockquote.exec(src);
15383
- if (cap) {
15384
- const text = cap[0].replace(/^ *>[ \t]?/gm, '');
15385
-
15386
- return {
15387
- type: 'blockquote',
15388
- raw: cap[0],
15389
- tokens: this.lexer.blockTokens(text, []),
15390
- text
15391
- };
15392
- }
15393
- }
15394
-
15395
- list(src) {
15396
- let cap = this.rules.block.list.exec(src);
15397
- if (cap) {
15398
- let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine,
15399
- line, nextLine, rawLine, itemContents, endEarly;
15400
-
15401
- let bull = cap[1].trim();
15402
- const isordered = bull.length > 1;
15403
-
15404
- const list = {
15405
- type: 'list',
15406
- raw: '',
15407
- ordered: isordered,
15408
- start: isordered ? +bull.slice(0, -1) : '',
15409
- loose: false,
15410
- items: []
15411
- };
15412
-
15413
- bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
15414
-
15415
- if (this.options.pedantic) {
15416
- bull = isordered ? bull : '[*+-]';
15417
- }
15418
-
15419
- // Get next list item
15420
- const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
15421
-
15422
- // Check if current bullet point can start a new List Item
15423
- while (src) {
15424
- endEarly = false;
15425
- if (!(cap = itemRegex.exec(src))) {
15426
- break;
15427
- }
15428
-
15429
- if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)
15430
- break;
15431
- }
15432
-
15433
- raw = cap[0];
15434
- src = src.substring(raw.length);
15435
-
15436
- line = cap[2].split('\n', 1)[0];
15437
- nextLine = src.split('\n', 1)[0];
15438
-
15439
- if (this.options.pedantic) {
15440
- indent = 2;
15441
- itemContents = line.trimLeft();
15442
- } else {
15443
- indent = cap[2].search(/[^ ]/); // Find first non-space char
15444
- indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
15445
- itemContents = line.slice(indent);
15446
- indent += cap[1].length;
15447
- }
15448
-
15449
- blankLine = false;
15450
-
15451
- if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
15452
- raw += nextLine + '\n';
15453
- src = src.substring(nextLine.length + 1);
15454
- endEarly = true;
15455
- }
15456
-
15457
- if (!endEarly) {
15458
- const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?: [^\\n]*)?(?:\\n|$))`);
15459
- const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
15460
- const fencesBeginRegex = new RegExp(`^( {0,${Math.min(3, indent - 1)}})(\`\`\`|~~~)`);
15461
-
15462
- // Check if following lines should be included in List Item
15463
- while (src) {
15464
- rawLine = src.split('\n', 1)[0];
15465
- line = rawLine;
15466
-
15467
- // Re-align to follow commonmark nesting rules
15468
- if (this.options.pedantic) {
15469
- line = line.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
15470
- }
15471
-
15472
- // End list item if found code fences
15473
- if (fencesBeginRegex.test(line)) {
15474
- break;
15475
- }
15476
-
15477
- // End list item if found start of new heading
15478
- if (this.rules.block.heading.test(line)) {
15479
- break;
15480
- }
15481
-
15482
- // End list item if found start of new bullet
15483
- if (nextBulletRegex.test(line)) {
15484
- break;
15485
- }
15486
-
15487
- // Horizontal rule found
15488
- if (hrRegex.test(src)) {
15489
- break;
15490
- }
15491
-
15492
- if (line.search(/[^ ]/) >= indent || !line.trim()) { // Dedent if possible
15493
- itemContents += '\n' + line.slice(indent);
15494
- } else if (!blankLine) { // Until blank line, item doesn't need indentation
15495
- itemContents += '\n' + line;
15496
- } else { // Otherwise, improper indentation ends this item
15497
- break;
15498
- }
15499
-
15500
- if (!blankLine && !line.trim()) { // Check if current line is blank
15501
- blankLine = true;
15502
- }
15503
-
15504
- raw += rawLine + '\n';
15505
- src = src.substring(rawLine.length + 1);
15506
- }
15507
- }
15508
-
15509
- if (!list.loose) {
15510
- // If the previous item ended with a blank line, the list is loose
15511
- if (endsWithBlankLine) {
15512
- list.loose = true;
15513
- } else if (/\n *\n *$/.test(raw)) {
15514
- endsWithBlankLine = true;
15515
- }
15516
- }
15517
-
15518
- // Check for task list items
15519
- if (this.options.gfm) {
15520
- istask = /^\[[ xX]\] /.exec(itemContents);
15521
- if (istask) {
15522
- ischecked = istask[0] !== '[ ] ';
15523
- itemContents = itemContents.replace(/^\[[ xX]\] +/, '');
15524
- }
15525
- }
15526
-
15527
- list.items.push({
15528
- type: 'list_item',
15529
- raw,
15530
- task: !!istask,
15531
- checked: ischecked,
15532
- loose: false,
15533
- text: itemContents
15534
- });
15535
-
15536
- list.raw += raw;
15537
- }
15538
-
15539
- // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
15540
- list.items[list.items.length - 1].raw = raw.trimRight();
15541
- list.items[list.items.length - 1].text = itemContents.trimRight();
15542
- list.raw = list.raw.trimRight();
15543
-
15544
- const l = list.items.length;
15545
-
15546
- // Item child tokens handled here at end because we needed to have the final item to trim it first
15547
- for (i = 0; i < l; i++) {
15548
- this.lexer.state.top = false;
15549
- list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
15550
- const spacers = list.items[i].tokens.filter(t => t.type === 'space');
15551
- const hasMultipleLineBreaks = spacers.every(t => {
15552
- const chars = t.raw.split('');
15553
- let lineBreaks = 0;
15554
- for (const char of chars) {
15555
- if (char === '\n') {
15556
- lineBreaks += 1;
15557
- }
15558
- if (lineBreaks > 1) {
15559
- return true;
15560
- }
15561
- }
15562
-
15563
- return false;
15564
- });
15565
-
15566
- if (!list.loose && spacers.length && hasMultipleLineBreaks) {
15567
- // Having a single line break doesn't mean a list is loose. A single line break is terminating the last list item
15568
- list.loose = true;
15569
- list.items[i].loose = true;
15570
- }
15571
- }
15572
-
15573
- return list;
15574
- }
15575
- }
15576
-
15577
- html(src) {
15578
- const cap = this.rules.block.html.exec(src);
15579
- if (cap) {
15580
- const token = {
15581
- type: 'html',
15582
- raw: cap[0],
15583
- pre: !this.options.sanitizer
15584
- && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
15585
- text: cap[0]
15586
- };
15587
- if (this.options.sanitize) {
15588
- token.type = 'paragraph';
15589
- token.text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : marked_esm_escape(cap[0]);
15590
- token.tokens = [];
15591
- this.lexer.inline(token.text, token.tokens);
15592
- }
15593
- return token;
15594
- }
15595
- }
15596
-
15597
- def(src) {
15598
- const cap = this.rules.block.def.exec(src);
15599
- if (cap) {
15600
- if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
15601
- const tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
15602
- return {
15603
- type: 'def',
15604
- tag,
15605
- raw: cap[0],
15606
- href: cap[2],
15607
- title: cap[3]
15608
- };
15609
- }
15610
- }
15611
-
15612
- table(src) {
15613
- const cap = this.rules.block.table.exec(src);
15614
- if (cap) {
15615
- const item = {
15616
- type: 'table',
15617
- header: splitCells(cap[1]).map(c => { return { text: c }; }),
15618
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
15619
- rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : []
15620
- };
15621
-
15622
- if (item.header.length === item.align.length) {
15623
- item.raw = cap[0];
15624
-
15625
- let l = item.align.length;
15626
- let i, j, k, row;
15627
- for (i = 0; i < l; i++) {
15628
- if (/^ *-+: *$/.test(item.align[i])) {
15629
- item.align[i] = 'right';
15630
- } else if (/^ *:-+: *$/.test(item.align[i])) {
15631
- item.align[i] = 'center';
15632
- } else if (/^ *:-+ *$/.test(item.align[i])) {
15633
- item.align[i] = 'left';
15634
- } else {
15635
- item.align[i] = null;
15636
- }
15637
- }
15638
-
15639
- l = item.rows.length;
15640
- for (i = 0; i < l; i++) {
15641
- item.rows[i] = splitCells(item.rows[i], item.header.length).map(c => { return { text: c }; });
15642
- }
15643
-
15644
- // parse child tokens inside headers and cells
15645
-
15646
- // header child tokens
15647
- l = item.header.length;
15648
- for (j = 0; j < l; j++) {
15649
- item.header[j].tokens = [];
15650
- this.lexer.inline(item.header[j].text, item.header[j].tokens);
15651
- }
15652
-
15653
- // cell child tokens
15654
- l = item.rows.length;
15655
- for (j = 0; j < l; j++) {
15656
- row = item.rows[j];
15657
- for (k = 0; k < row.length; k++) {
15658
- row[k].tokens = [];
15659
- this.lexer.inline(row[k].text, row[k].tokens);
15660
- }
15661
- }
15662
-
15663
- return item;
15664
- }
15665
- }
15666
- }
15667
-
15668
- lheading(src) {
15669
- const cap = this.rules.block.lheading.exec(src);
15670
- if (cap) {
15671
- const token = {
15672
- type: 'heading',
15673
- raw: cap[0],
15674
- depth: cap[2].charAt(0) === '=' ? 1 : 2,
15675
- text: cap[1],
15676
- tokens: []
15677
- };
15678
- this.lexer.inline(token.text, token.tokens);
15679
- return token;
15680
- }
15681
- }
15682
-
15683
- paragraph(src) {
15684
- const cap = this.rules.block.paragraph.exec(src);
15685
- if (cap) {
15686
- const token = {
15687
- type: 'paragraph',
15688
- raw: cap[0],
15689
- text: cap[1].charAt(cap[1].length - 1) === '\n'
15690
- ? cap[1].slice(0, -1)
15691
- : cap[1],
15692
- tokens: []
15693
- };
15694
- this.lexer.inline(token.text, token.tokens);
15695
- return token;
15696
- }
15697
- }
15698
-
15699
- text(src) {
15700
- const cap = this.rules.block.text.exec(src);
15701
- if (cap) {
15702
- const token = {
15703
- type: 'text',
15704
- raw: cap[0],
15705
- text: cap[0],
15706
- tokens: []
15707
- };
15708
- this.lexer.inline(token.text, token.tokens);
15709
- return token;
15710
- }
15711
- }
15712
-
15713
- escape(src) {
15714
- const cap = this.rules.inline.escape.exec(src);
15715
- if (cap) {
15716
- return {
15717
- type: 'escape',
15718
- raw: cap[0],
15719
- text: marked_esm_escape(cap[1])
15720
- };
15721
- }
15722
- }
15723
-
15724
- tag(src) {
15725
- const cap = this.rules.inline.tag.exec(src);
15726
- if (cap) {
15727
- if (!this.lexer.state.inLink && /^<a /i.test(cap[0])) {
15728
- this.lexer.state.inLink = true;
15729
- } else if (this.lexer.state.inLink && /^<\/a>/i.test(cap[0])) {
15730
- this.lexer.state.inLink = false;
15731
- }
15732
- if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
15733
- this.lexer.state.inRawBlock = true;
15734
- } else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
15735
- this.lexer.state.inRawBlock = false;
15736
- }
15737
-
15738
- return {
15739
- type: this.options.sanitize
15740
- ? 'text'
15741
- : 'html',
15742
- raw: cap[0],
15743
- inLink: this.lexer.state.inLink,
15744
- inRawBlock: this.lexer.state.inRawBlock,
15745
- text: this.options.sanitize
15746
- ? (this.options.sanitizer
15747
- ? this.options.sanitizer(cap[0])
15748
- : marked_esm_escape(cap[0]))
15749
- : cap[0]
15750
- };
15751
- }
15752
- }
15753
-
15754
- link(src) {
15755
- const cap = this.rules.inline.link.exec(src);
15756
- if (cap) {
15757
- const trimmedUrl = cap[2].trim();
15758
- if (!this.options.pedantic && /^</.test(trimmedUrl)) {
15759
- // commonmark requires matching angle brackets
15760
- if (!(/>$/.test(trimmedUrl))) {
15761
- return;
15762
- }
15763
-
15764
- // ending angle bracket cannot be escaped
15765
- const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
15766
- if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
15767
- return;
15768
- }
15769
- } else {
15770
- // find closing parenthesis
15771
- const lastParenIndex = marked_esm_findClosingBracket(cap[2], '()');
15772
- if (lastParenIndex > -1) {
15773
- const start = cap[0].indexOf('!') === 0 ? 5 : 4;
15774
- const linkLen = start + cap[1].length + lastParenIndex;
15775
- cap[2] = cap[2].substring(0, lastParenIndex);
15776
- cap[0] = cap[0].substring(0, linkLen).trim();
15777
- cap[3] = '';
15778
- }
15779
- }
15780
- let href = cap[2];
15781
- let title = '';
15782
- if (this.options.pedantic) {
15783
- // split pedantic href and title
15784
- const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
15785
-
15786
- if (link) {
15787
- href = link[1];
15788
- title = link[3];
15789
- }
15790
- } else {
15791
- title = cap[3] ? cap[3].slice(1, -1) : '';
15792
- }
15793
-
15794
- href = href.trim();
15795
- if (/^</.test(href)) {
15796
- if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {
15797
- // pedantic allows starting angle bracket without ending angle bracket
15798
- href = href.slice(1);
15799
- } else {
15800
- href = href.slice(1, -1);
15801
- }
15802
- }
15803
- return outputLink(cap, {
15804
- href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
15805
- title: title ? title.replace(this.rules.inline._escapes, '$1') : title
15806
- }, cap[0], this.lexer);
15807
- }
15808
- }
15809
-
15810
- reflink(src, links) {
15811
- let cap;
15812
- if ((cap = this.rules.inline.reflink.exec(src))
15813
- || (cap = this.rules.inline.nolink.exec(src))) {
15814
- let link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
15815
- link = links[link.toLowerCase()];
15816
- if (!link || !link.href) {
15817
- const text = cap[0].charAt(0);
15818
- return {
15819
- type: 'text',
15820
- raw: text,
15821
- text
15822
- };
15823
- }
15824
- return outputLink(cap, link, cap[0], this.lexer);
15825
- }
15826
- }
15827
-
15828
- emStrong(src, maskedSrc, prevChar = '') {
15829
- let match = this.rules.inline.emStrong.lDelim.exec(src);
15830
- if (!match) return;
15831
-
15832
- // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
15833
- if (match[3] && prevChar.match(/[\p{L}\p{N}]/u)) return;
15834
-
15835
- const nextChar = match[1] || match[2] || '';
15836
-
15837
- if (!nextChar || (nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar)))) {
15838
- const lLength = match[0].length - 1;
15839
- let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
15840
-
15841
- const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
15842
- endReg.lastIndex = 0;
15843
-
15844
- // Clip maskedSrc to same section of string as src (move to lexer?)
15845
- maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
15846
-
15847
- while ((match = endReg.exec(maskedSrc)) != null) {
15848
- rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
15849
-
15850
- if (!rDelim) continue; // skip single * in __abc*abc__
15851
-
15852
- rLength = rDelim.length;
15853
-
15854
- if (match[3] || match[4]) { // found another Left Delim
15855
- delimTotal += rLength;
15856
- continue;
15857
- } else if (match[5] || match[6]) { // either Left or Right Delim
15858
- if (lLength % 3 && !((lLength + rLength) % 3)) {
15859
- midDelimTotal += rLength;
15860
- continue; // CommonMark Emphasis Rules 9-10
15861
- }
15862
- }
15863
-
15864
- delimTotal -= rLength;
15865
-
15866
- if (delimTotal > 0) continue; // Haven't found enough closing delimiters
15867
-
15868
- // Remove extra characters. *a*** -> *a*
15869
- rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
15870
-
15871
- // Create `em` if smallest delimiter has odd char count. *a***
15872
- if (Math.min(lLength, rLength) % 2) {
15873
- const text = src.slice(1, lLength + match.index + rLength);
15874
- return {
15875
- type: 'em',
15876
- raw: src.slice(0, lLength + match.index + rLength + 1),
15877
- text,
15878
- tokens: this.lexer.inlineTokens(text, [])
15879
- };
15880
- }
15881
-
15882
- // Create 'strong' if smallest delimiter has even char count. **a***
15883
- const text = src.slice(2, lLength + match.index + rLength - 1);
15884
- return {
15885
- type: 'strong',
15886
- raw: src.slice(0, lLength + match.index + rLength + 1),
15887
- text,
15888
- tokens: this.lexer.inlineTokens(text, [])
15889
- };
15890
- }
15891
- }
15892
- }
15893
-
15894
- codespan(src) {
15895
- const cap = this.rules.inline.code.exec(src);
15896
- if (cap) {
15897
- let text = cap[2].replace(/\n/g, ' ');
15898
- const hasNonSpaceChars = /[^ ]/.test(text);
15899
- const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
15900
- if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
15901
- text = text.substring(1, text.length - 1);
15902
- }
15903
- text = marked_esm_escape(text, true);
15904
- return {
15905
- type: 'codespan',
15906
- raw: cap[0],
15907
- text
15908
- };
15909
- }
15910
- }
15911
-
15912
- br(src) {
15913
- const cap = this.rules.inline.br.exec(src);
15914
- if (cap) {
15915
- return {
15916
- type: 'br',
15917
- raw: cap[0]
15918
- };
15919
- }
15920
- }
15921
-
15922
- del(src) {
15923
- const cap = this.rules.inline.del.exec(src);
15924
- if (cap) {
15925
- return {
15926
- type: 'del',
15927
- raw: cap[0],
15928
- text: cap[2],
15929
- tokens: this.lexer.inlineTokens(cap[2], [])
15930
- };
15931
- }
15932
- }
15933
-
15934
- autolink(src, mangle) {
15935
- const cap = this.rules.inline.autolink.exec(src);
15936
- if (cap) {
15937
- let text, href;
15938
- if (cap[2] === '@') {
15939
- text = marked_esm_escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
15940
- href = 'mailto:' + text;
15941
- } else {
15942
- text = marked_esm_escape(cap[1]);
15943
- href = text;
15944
- }
15945
-
15946
- return {
15947
- type: 'link',
15948
- raw: cap[0],
15949
- text,
15950
- href,
15951
- tokens: [
15952
- {
15953
- type: 'text',
15954
- raw: text,
15955
- text
15956
- }
15957
- ]
15958
- };
15959
- }
15960
- }
15961
-
15962
- url(src, mangle) {
15963
- let cap;
15964
- if (cap = this.rules.inline.url.exec(src)) {
15965
- let text, href;
15966
- if (cap[2] === '@') {
15967
- text = marked_esm_escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
15968
- href = 'mailto:' + text;
15969
- } else {
15970
- // do extended autolink path validation
15971
- let prevCapZero;
15972
- do {
15973
- prevCapZero = cap[0];
15974
- cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
15975
- } while (prevCapZero !== cap[0]);
15976
- text = marked_esm_escape(cap[0]);
15977
- if (cap[1] === 'www.') {
15978
- href = 'http://' + text;
15979
- } else {
15980
- href = text;
15981
- }
15982
- }
15983
- return {
15984
- type: 'link',
15985
- raw: cap[0],
15986
- text,
15987
- href,
15988
- tokens: [
15989
- {
15990
- type: 'text',
15991
- raw: text,
15992
- text
15993
- }
15994
- ]
15995
- };
15996
- }
15997
- }
15998
-
15999
- inlineText(src, smartypants) {
16000
- const cap = this.rules.inline.text.exec(src);
16001
- if (cap) {
16002
- let text;
16003
- if (this.lexer.state.inRawBlock) {
16004
- text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : marked_esm_escape(cap[0])) : cap[0];
16005
- } else {
16006
- text = marked_esm_escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
16007
- }
16008
- return {
16009
- type: 'text',
16010
- raw: cap[0],
16011
- text
16012
- };
16013
- }
16014
- }
16015
- }
16016
-
16017
- /**
16018
- * Block-Level Grammar
16019
- */
16020
- const block = {
16021
- newline: /^(?: *(?:\n|$))+/,
16022
- code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
16023
- fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
16024
- hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
16025
- heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
16026
- blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
16027
- list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
16028
- html: '^ {0,3}(?:' // optional indentation
16029
- + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
16030
- + '|comment[^\\n]*(\\n+|$)' // (2)
16031
- + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
16032
- + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
16033
- + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
16034
- + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
16035
- + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
16036
- + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
16037
- + ')',
16038
- def: /^ {0,3}\[(label)\]: *(?:\n *)?<?([^\s>]+)>?(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
16039
- table: noopTest,
16040
- lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
16041
- // regex template, placeholders will be replaced according to different paragraph
16042
- // interruption rules of commonmark and the original markdown spec:
16043
- _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
16044
- text: /^[^\n]+/
16045
- };
16046
-
16047
- block._label = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
16048
- block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
16049
- block.def = edit(block.def)
16050
- .replace('label', block._label)
16051
- .replace('title', block._title)
16052
- .getRegex();
16053
-
16054
- block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
16055
- block.listItemStart = edit(/^( *)(bull) */)
16056
- .replace('bull', block.bullet)
16057
- .getRegex();
16058
-
16059
- block.list = edit(block.list)
16060
- .replace(/bull/g, block.bullet)
16061
- .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
16062
- .replace('def', '\\n+(?=' + block.def.source + ')')
16063
- .getRegex();
16064
-
16065
- block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
16066
- + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
16067
- + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
16068
- + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
16069
- + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
16070
- + '|track|ul';
16071
- block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
16072
- block.html = edit(block.html, 'i')
16073
- .replace('comment', block._comment)
16074
- .replace('tag', block._tag)
16075
- .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
16076
- .getRegex();
16077
-
16078
- block.paragraph = edit(block._paragraph)
16079
- .replace('hr', block.hr)
16080
- .replace('heading', ' {0,3}#{1,6} ')
16081
- .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
16082
- .replace('|table', '')
16083
- .replace('blockquote', ' {0,3}>')
16084
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
16085
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
16086
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
16087
- .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
16088
- .getRegex();
16089
-
16090
- block.blockquote = edit(block.blockquote)
16091
- .replace('paragraph', block.paragraph)
16092
- .getRegex();
16093
-
16094
- /**
16095
- * Normal Block Grammar
16096
- */
16097
-
16098
- block.normal = merge({}, block);
16099
-
16100
- /**
16101
- * GFM Block Grammar
16102
- */
16103
-
16104
- block.gfm = merge({}, block.normal, {
16105
- table: '^ *([^\\n ].*\\|.*)\\n' // Header
16106
- + ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' // Align
16107
- + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
16108
- });
16109
-
16110
- block.gfm.table = edit(block.gfm.table)
16111
- .replace('hr', block.hr)
16112
- .replace('heading', ' {0,3}#{1,6} ')
16113
- .replace('blockquote', ' {0,3}>')
16114
- .replace('code', ' {4}[^\\n]')
16115
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
16116
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
16117
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
16118
- .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
16119
- .getRegex();
16120
-
16121
- block.gfm.paragraph = edit(block._paragraph)
16122
- .replace('hr', block.hr)
16123
- .replace('heading', ' {0,3}#{1,6} ')
16124
- .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
16125
- .replace('table', block.gfm.table) // interrupt paragraphs with table
16126
- .replace('blockquote', ' {0,3}>')
16127
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
16128
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
16129
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
16130
- .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
16131
- .getRegex();
16132
- /**
16133
- * Pedantic grammar (original John Gruber's loose markdown specification)
16134
- */
16135
-
16136
- block.pedantic = merge({}, block.normal, {
16137
- html: edit(
16138
- '^ *(?:comment *(?:\\n|\\s*$)'
16139
- + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
16140
- + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
16141
- .replace('comment', block._comment)
16142
- .replace(/tag/g, '(?!(?:'
16143
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
16144
- + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
16145
- + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
16146
- .getRegex(),
16147
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
16148
- heading: /^(#{1,6})(.*)(?:\n+|$)/,
16149
- fences: noopTest, // fences not supported
16150
- paragraph: edit(block.normal._paragraph)
16151
- .replace('hr', block.hr)
16152
- .replace('heading', ' *#{1,6} *[^\n]')
16153
- .replace('lheading', block.lheading)
16154
- .replace('blockquote', ' {0,3}>')
16155
- .replace('|fences', '')
16156
- .replace('|list', '')
16157
- .replace('|html', '')
16158
- .getRegex()
16159
- });
16160
-
16161
- /**
16162
- * Inline-Level Grammar
16163
- */
16164
- const inline = {
16165
- escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
16166
- autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
16167
- url: noopTest,
16168
- tag: '^comment'
16169
- + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
16170
- + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
16171
- + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
16172
- + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
16173
- + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
16174
- link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
16175
- reflink: /^!?\[(label)\]\[(ref)\]/,
16176
- nolink: /^!?\[(ref)\](?:\[\])?/,
16177
- reflinkSearch: 'reflink|nolink(?!\\()',
16178
- emStrong: {
16179
- lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
16180
- // (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right.
16181
- // () Skip orphan inside strong () Consume to delim (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
16182
- rDelimAst: /^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[^*]+(?=[^*])|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
16183
- rDelimUnd: /^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
16184
- },
16185
- code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
16186
- br: /^( {2,}|\\)\n(?!\s*$)/,
16187
- del: noopTest,
16188
- text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
16189
- punctuation: /^([\spunctuation])/
16190
- };
16191
-
16192
- // list of punctuation marks from CommonMark spec
16193
- // without * and _ to handle the different emphasis markers * and _
16194
- inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
16195
- inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
16196
-
16197
- // sequences em should skip over [title](link), `code`, <html>
16198
- inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
16199
- inline.escapedEmSt = /\\\*|\\_/g;
16200
-
16201
- inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex();
16202
-
16203
- inline.emStrong.lDelim = edit(inline.emStrong.lDelim)
16204
- .replace(/punct/g, inline._punctuation)
16205
- .getRegex();
16206
-
16207
- inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'g')
16208
- .replace(/punct/g, inline._punctuation)
16209
- .getRegex();
16210
-
16211
- inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'g')
16212
- .replace(/punct/g, inline._punctuation)
16213
- .getRegex();
16214
-
16215
- inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
16216
-
16217
- inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
16218
- inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
16219
- inline.autolink = edit(inline.autolink)
16220
- .replace('scheme', inline._scheme)
16221
- .replace('email', inline._email)
16222
- .getRegex();
16223
-
16224
- inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
16225
-
16226
- inline.tag = edit(inline.tag)
16227
- .replace('comment', inline._comment)
16228
- .replace('attribute', inline._attribute)
16229
- .getRegex();
16230
-
16231
- inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
16232
- inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
16233
- inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
16234
-
16235
- inline.link = edit(inline.link)
16236
- .replace('label', inline._label)
16237
- .replace('href', inline._href)
16238
- .replace('title', inline._title)
16239
- .getRegex();
16240
-
16241
- inline.reflink = edit(inline.reflink)
16242
- .replace('label', inline._label)
16243
- .replace('ref', block._label)
16244
- .getRegex();
16245
-
16246
- inline.nolink = edit(inline.nolink)
16247
- .replace('ref', block._label)
16248
- .getRegex();
16249
-
16250
- inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
16251
- .replace('reflink', inline.reflink)
16252
- .replace('nolink', inline.nolink)
16253
- .getRegex();
16254
-
16255
- /**
16256
- * Normal Inline Grammar
16257
- */
16258
-
16259
- inline.normal = merge({}, inline);
16260
-
16261
- /**
16262
- * Pedantic Inline Grammar
16263
- */
16264
-
16265
- inline.pedantic = merge({}, inline.normal, {
16266
- strong: {
16267
- start: /^__|\*\*/,
16268
- middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
16269
- endAst: /\*\*(?!\*)/g,
16270
- endUnd: /__(?!_)/g
16271
- },
16272
- em: {
16273
- start: /^_|\*/,
16274
- middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
16275
- endAst: /\*(?!\*)/g,
16276
- endUnd: /_(?!_)/g
16277
- },
16278
- link: edit(/^!?\[(label)\]\((.*?)\)/)
16279
- .replace('label', inline._label)
16280
- .getRegex(),
16281
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
16282
- .replace('label', inline._label)
16283
- .getRegex()
16284
- });
16285
-
16286
- /**
16287
- * GFM Inline Grammar
16288
- */
16289
-
16290
- inline.gfm = merge({}, inline.normal, {
16291
- escape: edit(inline.escape).replace('])', '~|])').getRegex(),
16292
- _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
16293
- url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
16294
- _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
16295
- del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
16296
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
16297
- });
16298
-
16299
- inline.gfm.url = edit(inline.gfm.url, 'i')
16300
- .replace('email', inline.gfm._extended_email)
16301
- .getRegex();
16302
- /**
16303
- * GFM + Line Breaks Inline Grammar
16304
- */
16305
-
16306
- inline.breaks = merge({}, inline.gfm, {
16307
- br: edit(inline.br).replace('{2,}', '*').getRegex(),
16308
- text: edit(inline.gfm.text)
16309
- .replace('\\b_', '\\b_| {2,}\\n')
16310
- .replace(/\{2,\}/g, '*')
16311
- .getRegex()
16312
- });
16313
-
16314
- /**
16315
- * smartypants text replacement
16316
- * @param {string} text
16317
- */
16318
- function smartypants(text) {
16319
- return text
16320
- // em-dashes
16321
- .replace(/---/g, '\u2014')
16322
- // en-dashes
16323
- .replace(/--/g, '\u2013')
16324
- // opening singles
16325
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
16326
- // closing singles & apostrophes
16327
- .replace(/'/g, '\u2019')
16328
- // opening doubles
16329
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
16330
- // closing doubles
16331
- .replace(/"/g, '\u201d')
16332
- // ellipses
16333
- .replace(/\.{3}/g, '\u2026');
16334
- }
16335
-
16336
- /**
16337
- * mangle email addresses
16338
- * @param {string} text
16339
- */
16340
- function mangle(text) {
16341
- let out = '',
16342
- i,
16343
- ch;
16344
-
16345
- const l = text.length;
16346
- for (i = 0; i < l; i++) {
16347
- ch = text.charCodeAt(i);
16348
- if (Math.random() > 0.5) {
16349
- ch = 'x' + ch.toString(16);
16350
- }
16351
- out += '&#' + ch + ';';
16352
- }
16353
-
16354
- return out;
16355
- }
16356
-
16357
- /**
16358
- * Block Lexer
16359
- */
16360
- class Lexer {
16361
- constructor(options) {
16362
- this.tokens = [];
16363
- this.tokens.links = Object.create(null);
16364
- this.options = options || defaults;
16365
- this.options.tokenizer = this.options.tokenizer || new Tokenizer();
16366
- this.tokenizer = this.options.tokenizer;
16367
- this.tokenizer.options = this.options;
16368
- this.tokenizer.lexer = this;
16369
- this.inlineQueue = [];
16370
- this.state = {
16371
- inLink: false,
16372
- inRawBlock: false,
16373
- top: true
16374
- };
16375
-
16376
- const rules = {
16377
- block: block.normal,
16378
- inline: inline.normal
16379
- };
16380
-
16381
- if (this.options.pedantic) {
16382
- rules.block = block.pedantic;
16383
- rules.inline = inline.pedantic;
16384
- } else if (this.options.gfm) {
16385
- rules.block = block.gfm;
16386
- if (this.options.breaks) {
16387
- rules.inline = inline.breaks;
16388
- } else {
16389
- rules.inline = inline.gfm;
16390
- }
16391
- }
16392
- this.tokenizer.rules = rules;
16393
- }
16394
-
16395
- /**
16396
- * Expose Rules
16397
- */
16398
- static get rules() {
16399
- return {
16400
- block,
16401
- inline
16402
- };
16403
- }
16404
-
16405
- /**
16406
- * Static Lex Method
16407
- */
16408
- static lex(src, options) {
16409
- const lexer = new Lexer(options);
16410
- return lexer.lex(src);
16411
- }
16412
-
16413
- /**
16414
- * Static Lex Inline Method
16415
- */
16416
- static lexInline(src, options) {
16417
- const lexer = new Lexer(options);
16418
- return lexer.inlineTokens(src);
16419
- }
16420
-
16421
- /**
16422
- * Preprocessing
16423
- */
16424
- lex(src) {
16425
- src = src
16426
- .replace(/\r\n|\r/g, '\n');
16427
-
16428
- this.blockTokens(src, this.tokens);
16429
-
16430
- let next;
16431
- while (next = this.inlineQueue.shift()) {
16432
- this.inlineTokens(next.src, next.tokens);
16433
- }
16434
-
16435
- return this.tokens;
16436
- }
16437
-
16438
- /**
16439
- * Lexing
16440
- */
16441
- blockTokens(src, tokens = []) {
16442
- if (this.options.pedantic) {
16443
- src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
16444
- } else {
16445
- src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
16446
- return leading + ' '.repeat(tabs.length);
16447
- });
16448
- }
16449
-
16450
- let token, lastToken, cutSrc, lastParagraphClipped;
16451
-
16452
- while (src) {
16453
- if (this.options.extensions
16454
- && this.options.extensions.block
16455
- && this.options.extensions.block.some((extTokenizer) => {
16456
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
16457
- src = src.substring(token.raw.length);
16458
- tokens.push(token);
16459
- return true;
16460
- }
16461
- return false;
16462
- })) {
16463
- continue;
16464
- }
16465
-
16466
- // newline
16467
- if (token = this.tokenizer.space(src)) {
16468
- src = src.substring(token.raw.length);
16469
- if (token.raw.length === 1 && tokens.length > 0) {
16470
- // if there's a single \n as a spacer, it's terminating the last line,
16471
- // so move it there so that we don't get unecessary paragraph tags
16472
- tokens[tokens.length - 1].raw += '\n';
16473
- } else {
16474
- tokens.push(token);
16475
- }
16476
- continue;
16477
- }
16478
-
16479
- // code
16480
- if (token = this.tokenizer.code(src)) {
16481
- src = src.substring(token.raw.length);
16482
- lastToken = tokens[tokens.length - 1];
16483
- // An indented code block cannot interrupt a paragraph.
16484
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
16485
- lastToken.raw += '\n' + token.raw;
16486
- lastToken.text += '\n' + token.text;
16487
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
16488
- } else {
16489
- tokens.push(token);
16490
- }
16491
- continue;
16492
- }
16493
-
16494
- // fences
16495
- if (token = this.tokenizer.fences(src)) {
16496
- src = src.substring(token.raw.length);
16497
- tokens.push(token);
16498
- continue;
16499
- }
16500
-
16501
- // heading
16502
- if (token = this.tokenizer.heading(src)) {
16503
- src = src.substring(token.raw.length);
16504
- tokens.push(token);
16505
- continue;
16506
- }
16507
-
16508
- // hr
16509
- if (token = this.tokenizer.hr(src)) {
16510
- src = src.substring(token.raw.length);
16511
- tokens.push(token);
16512
- continue;
16513
- }
16514
-
16515
- // blockquote
16516
- if (token = this.tokenizer.blockquote(src)) {
16517
- src = src.substring(token.raw.length);
16518
- tokens.push(token);
16519
- continue;
16520
- }
16521
-
16522
- // list
16523
- if (token = this.tokenizer.list(src)) {
16524
- src = src.substring(token.raw.length);
16525
- tokens.push(token);
16526
- continue;
16527
- }
16528
-
16529
- // html
16530
- if (token = this.tokenizer.html(src)) {
16531
- src = src.substring(token.raw.length);
16532
- tokens.push(token);
16533
- continue;
16534
- }
16535
-
16536
- // def
16537
- if (token = this.tokenizer.def(src)) {
16538
- src = src.substring(token.raw.length);
16539
- lastToken = tokens[tokens.length - 1];
16540
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
16541
- lastToken.raw += '\n' + token.raw;
16542
- lastToken.text += '\n' + token.raw;
16543
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
16544
- } else if (!this.tokens.links[token.tag]) {
16545
- this.tokens.links[token.tag] = {
16546
- href: token.href,
16547
- title: token.title
16548
- };
16549
- }
16550
- continue;
16551
- }
16552
-
16553
- // table (gfm)
16554
- if (token = this.tokenizer.table(src)) {
16555
- src = src.substring(token.raw.length);
16556
- tokens.push(token);
16557
- continue;
16558
- }
16559
-
16560
- // lheading
16561
- if (token = this.tokenizer.lheading(src)) {
16562
- src = src.substring(token.raw.length);
16563
- tokens.push(token);
16564
- continue;
16565
- }
16566
-
16567
- // top-level paragraph
16568
- // prevent paragraph consuming extensions by clipping 'src' to extension start
16569
- cutSrc = src;
16570
- if (this.options.extensions && this.options.extensions.startBlock) {
16571
- let startIndex = Infinity;
16572
- const tempSrc = src.slice(1);
16573
- let tempStart;
16574
- this.options.extensions.startBlock.forEach(function(getStartIndex) {
16575
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
16576
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
16577
- });
16578
- if (startIndex < Infinity && startIndex >= 0) {
16579
- cutSrc = src.substring(0, startIndex + 1);
16580
- }
16581
- }
16582
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
16583
- lastToken = tokens[tokens.length - 1];
16584
- if (lastParagraphClipped && lastToken.type === 'paragraph') {
16585
- lastToken.raw += '\n' + token.raw;
16586
- lastToken.text += '\n' + token.text;
16587
- this.inlineQueue.pop();
16588
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
16589
- } else {
16590
- tokens.push(token);
16591
- }
16592
- lastParagraphClipped = (cutSrc.length !== src.length);
16593
- src = src.substring(token.raw.length);
16594
- continue;
16595
- }
16596
-
16597
- // text
16598
- if (token = this.tokenizer.text(src)) {
16599
- src = src.substring(token.raw.length);
16600
- lastToken = tokens[tokens.length - 1];
16601
- if (lastToken && lastToken.type === 'text') {
16602
- lastToken.raw += '\n' + token.raw;
16603
- lastToken.text += '\n' + token.text;
16604
- this.inlineQueue.pop();
16605
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
16606
- } else {
16607
- tokens.push(token);
16608
- }
16609
- continue;
16610
- }
16611
-
16612
- if (src) {
16613
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
16614
- if (this.options.silent) {
16615
- console.error(errMsg);
16616
- break;
16617
- } else {
16618
- throw new Error(errMsg);
16619
- }
16620
- }
16621
- }
16622
-
16623
- this.state.top = true;
16624
- return tokens;
16625
- }
16626
-
16627
- inline(src, tokens) {
16628
- this.inlineQueue.push({ src, tokens });
16629
- }
16630
-
16631
- /**
16632
- * Lexing/Compiling
16633
- */
16634
- inlineTokens(src, tokens = []) {
16635
- let token, lastToken, cutSrc;
16636
-
16637
- // String with links masked to avoid interference with em and strong
16638
- let maskedSrc = src;
16639
- let match;
16640
- let keepPrevChar, prevChar;
16641
-
16642
- // Mask out reflinks
16643
- if (this.tokens.links) {
16644
- const links = Object.keys(this.tokens.links);
16645
- if (links.length > 0) {
16646
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
16647
- if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
16648
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
16649
- }
16650
- }
16651
- }
16652
- }
16653
- // Mask out other blocks
16654
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
16655
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
16656
- }
16657
-
16658
- // Mask out escaped em & strong delimiters
16659
- while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
16660
- maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
16661
- }
16662
-
16663
- while (src) {
16664
- if (!keepPrevChar) {
16665
- prevChar = '';
16666
- }
16667
- keepPrevChar = false;
16668
-
16669
- // extensions
16670
- if (this.options.extensions
16671
- && this.options.extensions.inline
16672
- && this.options.extensions.inline.some((extTokenizer) => {
16673
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
16674
- src = src.substring(token.raw.length);
16675
- tokens.push(token);
16676
- return true;
16677
- }
16678
- return false;
16679
- })) {
16680
- continue;
16681
- }
16682
-
16683
- // escape
16684
- if (token = this.tokenizer.escape(src)) {
16685
- src = src.substring(token.raw.length);
16686
- tokens.push(token);
16687
- continue;
16688
- }
16689
-
16690
- // tag
16691
- if (token = this.tokenizer.tag(src)) {
16692
- src = src.substring(token.raw.length);
16693
- lastToken = tokens[tokens.length - 1];
16694
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
16695
- lastToken.raw += token.raw;
16696
- lastToken.text += token.text;
16697
- } else {
16698
- tokens.push(token);
16699
- }
16700
- continue;
16701
- }
16702
-
16703
- // link
16704
- if (token = this.tokenizer.link(src)) {
16705
- src = src.substring(token.raw.length);
16706
- tokens.push(token);
16707
- continue;
16708
- }
16709
-
16710
- // reflink, nolink
16711
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
16712
- src = src.substring(token.raw.length);
16713
- lastToken = tokens[tokens.length - 1];
16714
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
16715
- lastToken.raw += token.raw;
16716
- lastToken.text += token.text;
16717
- } else {
16718
- tokens.push(token);
16719
- }
16720
- continue;
16721
- }
16722
-
16723
- // em & strong
16724
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
16725
- src = src.substring(token.raw.length);
16726
- tokens.push(token);
16727
- continue;
16728
- }
16729
-
16730
- // code
16731
- if (token = this.tokenizer.codespan(src)) {
16732
- src = src.substring(token.raw.length);
16733
- tokens.push(token);
16734
- continue;
16735
- }
16736
-
16737
- // br
16738
- if (token = this.tokenizer.br(src)) {
16739
- src = src.substring(token.raw.length);
16740
- tokens.push(token);
16741
- continue;
16742
- }
16743
-
16744
- // del (gfm)
16745
- if (token = this.tokenizer.del(src)) {
16746
- src = src.substring(token.raw.length);
16747
- tokens.push(token);
16748
- continue;
16749
- }
16750
-
16751
- // autolink
16752
- if (token = this.tokenizer.autolink(src, mangle)) {
16753
- src = src.substring(token.raw.length);
16754
- tokens.push(token);
16755
- continue;
16756
- }
16757
-
16758
- // url (gfm)
16759
- if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
16760
- src = src.substring(token.raw.length);
16761
- tokens.push(token);
16762
- continue;
16763
- }
16764
-
16765
- // text
16766
- // prevent inlineText consuming extensions by clipping 'src' to extension start
16767
- cutSrc = src;
16768
- if (this.options.extensions && this.options.extensions.startInline) {
16769
- let startIndex = Infinity;
16770
- const tempSrc = src.slice(1);
16771
- let tempStart;
16772
- this.options.extensions.startInline.forEach(function(getStartIndex) {
16773
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
16774
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
16775
- });
16776
- if (startIndex < Infinity && startIndex >= 0) {
16777
- cutSrc = src.substring(0, startIndex + 1);
16778
- }
16779
- }
16780
- if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
16781
- src = src.substring(token.raw.length);
16782
- if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
16783
- prevChar = token.raw.slice(-1);
16784
- }
16785
- keepPrevChar = true;
16786
- lastToken = tokens[tokens.length - 1];
16787
- if (lastToken && lastToken.type === 'text') {
16788
- lastToken.raw += token.raw;
16789
- lastToken.text += token.text;
16790
- } else {
16791
- tokens.push(token);
16792
- }
16793
- continue;
16794
- }
16795
-
16796
- if (src) {
16797
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
16798
- if (this.options.silent) {
16799
- console.error(errMsg);
16800
- break;
16801
- } else {
16802
- throw new Error(errMsg);
16803
- }
16804
- }
16805
- }
16806
-
16807
- return tokens;
16808
- }
16809
- }
16810
-
16811
- /**
16812
- * Renderer
16813
- */
16814
- class Renderer {
16815
- constructor(options) {
16816
- this.options = options || defaults;
16817
- }
16818
-
16819
- code(code, infostring, escaped) {
16820
- const lang = (infostring || '').match(/\S*/)[0];
16821
- if (this.options.highlight) {
16822
- const out = this.options.highlight(code, lang);
16823
- if (out != null && out !== code) {
16824
- escaped = true;
16825
- code = out;
16826
- }
16827
- }
16828
-
16829
- code = code.replace(/\n$/, '') + '\n';
16830
-
16831
- if (!lang) {
16832
- return '<pre><code>'
16833
- + (escaped ? code : marked_esm_escape(code, true))
16834
- + '</code></pre>\n';
16835
- }
16836
-
16837
- return '<pre><code class="'
16838
- + this.options.langPrefix
16839
- + marked_esm_escape(lang, true)
16840
- + '">'
16841
- + (escaped ? code : marked_esm_escape(code, true))
16842
- + '</code></pre>\n';
16843
- }
16844
-
16845
- /**
16846
- * @param {string} quote
16847
- */
16848
- blockquote(quote) {
16849
- return `<blockquote>\n${quote}</blockquote>\n`;
16850
- }
16851
-
16852
- html(html) {
16853
- return html;
16854
- }
16855
-
16856
- /**
16857
- * @param {string} text
16858
- * @param {string} level
16859
- * @param {string} raw
16860
- * @param {any} slugger
16861
- */
16862
- heading(text, level, raw, slugger) {
16863
- if (this.options.headerIds) {
16864
- const id = this.options.headerPrefix + slugger.slug(raw);
16865
- return `<h${level} id="${id}">${text}</h${level}>\n`;
16866
- }
16867
-
16868
- // ignore IDs
16869
- return `<h${level}>${text}</h${level}>\n`;
16870
- }
16871
-
16872
- hr() {
16873
- return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
16874
- }
16875
-
16876
- list(body, ordered, start) {
16877
- const type = ordered ? 'ol' : 'ul',
16878
- startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
16879
- return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
16880
- }
16881
-
16882
- /**
16883
- * @param {string} text
16884
- */
16885
- listitem(text) {
16886
- return `<li>${text}</li>\n`;
16887
- }
16888
-
16889
- checkbox(checked) {
16890
- return '<input '
16891
- + (checked ? 'checked="" ' : '')
16892
- + 'disabled="" type="checkbox"'
16893
- + (this.options.xhtml ? ' /' : '')
16894
- + '> ';
16895
- }
16896
-
16897
- /**
16898
- * @param {string} text
16899
- */
16900
- paragraph(text) {
16901
- return `<p>${text}</p>\n`;
16902
- }
16903
-
16904
- /**
16905
- * @param {string} header
16906
- * @param {string} body
16907
- */
16908
- table(header, body) {
16909
- if (body) body = `<tbody>${body}</tbody>`;
16910
-
16911
- return '<table>\n'
16912
- + '<thead>\n'
16913
- + header
16914
- + '</thead>\n'
16915
- + body
16916
- + '</table>\n';
16917
- }
16918
-
16919
- /**
16920
- * @param {string} content
16921
- */
16922
- tablerow(content) {
16923
- return `<tr>\n${content}</tr>\n`;
16924
- }
16925
-
16926
- tablecell(content, flags) {
16927
- const type = flags.header ? 'th' : 'td';
16928
- const tag = flags.align
16929
- ? `<${type} align="${flags.align}">`
16930
- : `<${type}>`;
16931
- return tag + content + `</${type}>\n`;
16932
- }
16933
-
16934
- /**
16935
- * span level renderer
16936
- * @param {string} text
16937
- */
16938
- strong(text) {
16939
- return `<strong>${text}</strong>`;
16940
- }
16941
-
16942
- /**
16943
- * @param {string} text
16944
- */
16945
- em(text) {
16946
- return `<em>${text}</em>`;
16947
- }
16948
-
16949
- /**
16950
- * @param {string} text
16951
- */
16952
- codespan(text) {
16953
- return `<code>${text}</code>`;
16954
- }
16955
-
16956
- br() {
16957
- return this.options.xhtml ? '<br/>' : '<br>';
16958
- }
16959
-
16960
- /**
16961
- * @param {string} text
16962
- */
16963
- del(text) {
16964
- return `<del>${text}</del>`;
16965
- }
16966
-
16967
- /**
16968
- * @param {string} href
16969
- * @param {string} title
16970
- * @param {string} text
16971
- */
16972
- link(href, title, text) {
16973
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
16974
- if (href === null) {
16975
- return text;
16976
- }
16977
- let out = '<a href="' + marked_esm_escape(href) + '"';
16978
- if (title) {
16979
- out += ' title="' + title + '"';
16980
- }
16981
- out += '>' + text + '</a>';
16982
- return out;
16983
- }
16984
-
16985
- /**
16986
- * @param {string} href
16987
- * @param {string} title
16988
- * @param {string} text
16989
- */
16990
- image(href, title, text) {
16991
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
16992
- if (href === null) {
16993
- return text;
16994
- }
16995
-
16996
- let out = `<img src="${href}" alt="${text}"`;
16997
- if (title) {
16998
- out += ` title="${title}"`;
16999
- }
17000
- out += this.options.xhtml ? '/>' : '>';
17001
- return out;
17002
- }
17003
-
17004
- text(text) {
17005
- return text;
17006
- }
17007
- }
17008
-
17009
- /**
17010
- * TextRenderer
17011
- * returns only the textual part of the token
17012
- */
17013
- class TextRenderer {
17014
- // no need for block level renderers
17015
- strong(text) {
17016
- return text;
17017
- }
17018
-
17019
- em(text) {
17020
- return text;
17021
- }
17022
-
17023
- codespan(text) {
17024
- return text;
17025
- }
17026
-
17027
- del(text) {
17028
- return text;
17029
- }
17030
-
17031
- html(text) {
17032
- return text;
17033
- }
17034
-
17035
- text(text) {
17036
- return text;
17037
- }
17038
-
17039
- link(href, title, text) {
17040
- return '' + text;
17041
- }
17042
-
17043
- image(href, title, text) {
17044
- return '' + text;
17045
- }
17046
-
17047
- br() {
17048
- return '';
17049
- }
17050
- }
17051
-
17052
- /**
17053
- * Slugger generates header id
17054
- */
17055
- class Slugger {
17056
- constructor() {
17057
- this.seen = {};
17058
- }
17059
-
17060
- /**
17061
- * @param {string} value
17062
- */
17063
- serialize(value) {
17064
- return value
17065
- .toLowerCase()
17066
- .trim()
17067
- // remove html tags
17068
- .replace(/<[!\/a-z].*?>/ig, '')
17069
- // remove unwanted chars
17070
- .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
17071
- .replace(/\s/g, '-');
17072
- }
17073
-
17074
- /**
17075
- * Finds the next safe (unique) slug to use
17076
- * @param {string} originalSlug
17077
- * @param {boolean} isDryRun
17078
- */
17079
- getNextSafeSlug(originalSlug, isDryRun) {
17080
- let slug = originalSlug;
17081
- let occurenceAccumulator = 0;
17082
- if (this.seen.hasOwnProperty(slug)) {
17083
- occurenceAccumulator = this.seen[originalSlug];
17084
- do {
17085
- occurenceAccumulator++;
17086
- slug = originalSlug + '-' + occurenceAccumulator;
17087
- } while (this.seen.hasOwnProperty(slug));
17088
- }
17089
- if (!isDryRun) {
17090
- this.seen[originalSlug] = occurenceAccumulator;
17091
- this.seen[slug] = 0;
17092
- }
17093
- return slug;
17094
- }
17095
-
17096
- /**
17097
- * Convert string to unique id
17098
- * @param {object} [options]
17099
- * @param {boolean} [options.dryrun] Generates the next unique slug without
17100
- * updating the internal accumulator.
17101
- */
17102
- slug(value, options = {}) {
17103
- const slug = this.serialize(value);
17104
- return this.getNextSafeSlug(slug, options.dryrun);
17105
- }
17106
- }
17107
-
17108
- /**
17109
- * Parsing & Compiling
17110
- */
17111
- class Parser {
17112
- constructor(options) {
17113
- this.options = options || defaults;
17114
- this.options.renderer = this.options.renderer || new Renderer();
17115
- this.renderer = this.options.renderer;
17116
- this.renderer.options = this.options;
17117
- this.textRenderer = new TextRenderer();
17118
- this.slugger = new Slugger();
17119
- }
17120
-
17121
- /**
17122
- * Static Parse Method
17123
- */
17124
- static parse(tokens, options) {
17125
- const parser = new Parser(options);
17126
- return parser.parse(tokens);
17127
- }
17128
-
17129
- /**
17130
- * Static Parse Inline Method
17131
- */
17132
- static parseInline(tokens, options) {
17133
- const parser = new Parser(options);
17134
- return parser.parseInline(tokens);
17135
- }
17136
-
17137
- /**
17138
- * Parse Loop
17139
- */
17140
- parse(tokens, top = true) {
17141
- let out = '',
17142
- i,
17143
- j,
17144
- k,
17145
- l2,
17146
- l3,
17147
- row,
17148
- cell,
17149
- header,
17150
- body,
17151
- token,
17152
- ordered,
17153
- start,
17154
- loose,
17155
- itemBody,
17156
- item,
17157
- checked,
17158
- task,
17159
- checkbox,
17160
- ret;
17161
-
17162
- const l = tokens.length;
17163
- for (i = 0; i < l; i++) {
17164
- token = tokens[i];
17165
-
17166
- // Run any renderer extensions
17167
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
17168
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
17169
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
17170
- out += ret || '';
17171
- continue;
17172
- }
17173
- }
17174
-
17175
- switch (token.type) {
17176
- case 'space': {
17177
- continue;
17178
- }
17179
- case 'hr': {
17180
- out += this.renderer.hr();
17181
- continue;
17182
- }
17183
- case 'heading': {
17184
- out += this.renderer.heading(
17185
- this.parseInline(token.tokens),
17186
- token.depth,
17187
- marked_esm_unescape(this.parseInline(token.tokens, this.textRenderer)),
17188
- this.slugger);
17189
- continue;
17190
- }
17191
- case 'code': {
17192
- out += this.renderer.code(token.text,
17193
- token.lang,
17194
- token.escaped);
17195
- continue;
17196
- }
17197
- case 'table': {
17198
- header = '';
17199
-
17200
- // header
17201
- cell = '';
17202
- l2 = token.header.length;
17203
- for (j = 0; j < l2; j++) {
17204
- cell += this.renderer.tablecell(
17205
- this.parseInline(token.header[j].tokens),
17206
- { header: true, align: token.align[j] }
17207
- );
17208
- }
17209
- header += this.renderer.tablerow(cell);
17210
-
17211
- body = '';
17212
- l2 = token.rows.length;
17213
- for (j = 0; j < l2; j++) {
17214
- row = token.rows[j];
17215
-
17216
- cell = '';
17217
- l3 = row.length;
17218
- for (k = 0; k < l3; k++) {
17219
- cell += this.renderer.tablecell(
17220
- this.parseInline(row[k].tokens),
17221
- { header: false, align: token.align[k] }
17222
- );
17223
- }
17224
-
17225
- body += this.renderer.tablerow(cell);
17226
- }
17227
- out += this.renderer.table(header, body);
17228
- continue;
17229
- }
17230
- case 'blockquote': {
17231
- body = this.parse(token.tokens);
17232
- out += this.renderer.blockquote(body);
17233
- continue;
17234
- }
17235
- case 'list': {
17236
- ordered = token.ordered;
17237
- start = token.start;
17238
- loose = token.loose;
17239
- l2 = token.items.length;
17240
-
17241
- body = '';
17242
- for (j = 0; j < l2; j++) {
17243
- item = token.items[j];
17244
- checked = item.checked;
17245
- task = item.task;
17246
-
17247
- itemBody = '';
17248
- if (item.task) {
17249
- checkbox = this.renderer.checkbox(checked);
17250
- if (loose) {
17251
- if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
17252
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
17253
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
17254
- item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
17255
- }
17256
- } else {
17257
- item.tokens.unshift({
17258
- type: 'text',
17259
- text: checkbox
17260
- });
17261
- }
17262
- } else {
17263
- itemBody += checkbox;
17264
- }
17265
- }
17266
-
17267
- itemBody += this.parse(item.tokens, loose);
17268
- body += this.renderer.listitem(itemBody, task, checked);
17269
- }
17270
-
17271
- out += this.renderer.list(body, ordered, start);
17272
- continue;
17273
- }
17274
- case 'html': {
17275
- // TODO parse inline content if parameter markdown=1
17276
- out += this.renderer.html(token.text);
17277
- continue;
17278
- }
17279
- case 'paragraph': {
17280
- out += this.renderer.paragraph(this.parseInline(token.tokens));
17281
- continue;
17282
- }
17283
- case 'text': {
17284
- body = token.tokens ? this.parseInline(token.tokens) : token.text;
17285
- while (i + 1 < l && tokens[i + 1].type === 'text') {
17286
- token = tokens[++i];
17287
- body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
17288
- }
17289
- out += top ? this.renderer.paragraph(body) : body;
17290
- continue;
17291
- }
17292
-
17293
- default: {
17294
- const errMsg = 'Token with "' + token.type + '" type was not found.';
17295
- if (this.options.silent) {
17296
- console.error(errMsg);
17297
- return;
17298
- } else {
17299
- throw new Error(errMsg);
17300
- }
17301
- }
17302
- }
17303
- }
17304
-
17305
- return out;
17306
- }
17307
-
17308
- /**
17309
- * Parse Inline Tokens
17310
- */
17311
- parseInline(tokens, renderer) {
17312
- renderer = renderer || this.renderer;
17313
- let out = '',
17314
- i,
17315
- token,
17316
- ret;
17317
-
17318
- const l = tokens.length;
17319
- for (i = 0; i < l; i++) {
17320
- token = tokens[i];
17321
-
17322
- // Run any renderer extensions
17323
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
17324
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
17325
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
17326
- out += ret || '';
17327
- continue;
17328
- }
17329
- }
17330
-
17331
- switch (token.type) {
17332
- case 'escape': {
17333
- out += renderer.text(token.text);
17334
- break;
17335
- }
17336
- case 'html': {
17337
- out += renderer.html(token.text);
17338
- break;
17339
- }
17340
- case 'link': {
17341
- out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
17342
- break;
17343
- }
17344
- case 'image': {
17345
- out += renderer.image(token.href, token.title, token.text);
17346
- break;
17347
- }
17348
- case 'strong': {
17349
- out += renderer.strong(this.parseInline(token.tokens, renderer));
17350
- break;
17351
- }
17352
- case 'em': {
17353
- out += renderer.em(this.parseInline(token.tokens, renderer));
17354
- break;
17355
- }
17356
- case 'codespan': {
17357
- out += renderer.codespan(token.text);
17358
- break;
17359
- }
17360
- case 'br': {
17361
- out += renderer.br();
17362
- break;
17363
- }
17364
- case 'del': {
17365
- out += renderer.del(this.parseInline(token.tokens, renderer));
17366
- break;
17367
- }
17368
- case 'text': {
17369
- out += renderer.text(token.text);
17370
- break;
17371
- }
17372
- default: {
17373
- const errMsg = 'Token with "' + token.type + '" type was not found.';
17374
- if (this.options.silent) {
17375
- console.error(errMsg);
17376
- return;
17377
- } else {
17378
- throw new Error(errMsg);
17379
- }
17380
- }
17381
- }
17382
- }
17383
- return out;
17384
- }
17385
- }
17386
-
17387
- /**
17388
- * Marked
17389
- */
17390
- function marked(src, opt, callback) {
17391
- // throw error in case of non string input
17392
- if (typeof src === 'undefined' || src === null) {
17393
- throw new Error('marked(): input parameter is undefined or null');
17394
- }
17395
- if (typeof src !== 'string') {
17396
- throw new Error('marked(): input parameter is of type '
17397
- + Object.prototype.toString.call(src) + ', string expected');
17398
- }
17399
-
17400
- if (typeof opt === 'function') {
17401
- callback = opt;
17402
- opt = null;
17403
- }
17404
-
17405
- opt = merge({}, marked.defaults, opt || {});
17406
- checkSanitizeDeprecation(opt);
17407
-
17408
- if (callback) {
17409
- const highlight = opt.highlight;
17410
- let tokens;
17411
-
17412
- try {
17413
- tokens = Lexer.lex(src, opt);
17414
- } catch (e) {
17415
- return callback(e);
17416
- }
17417
-
17418
- const done = function(err) {
17419
- let out;
17420
-
17421
- if (!err) {
17422
- try {
17423
- if (opt.walkTokens) {
17424
- marked.walkTokens(tokens, opt.walkTokens);
17425
- }
17426
- out = Parser.parse(tokens, opt);
17427
- } catch (e) {
17428
- err = e;
17429
- }
17430
- }
17431
-
17432
- opt.highlight = highlight;
17433
-
17434
- return err
17435
- ? callback(err)
17436
- : callback(null, out);
17437
- };
17438
-
17439
- if (!highlight || highlight.length < 3) {
17440
- return done();
17441
- }
17442
-
17443
- delete opt.highlight;
17444
-
17445
- if (!tokens.length) return done();
17446
-
17447
- let pending = 0;
17448
- marked.walkTokens(tokens, function(token) {
17449
- if (token.type === 'code') {
17450
- pending++;
17451
- setTimeout(() => {
17452
- highlight(token.text, token.lang, function(err, code) {
17453
- if (err) {
17454
- return done(err);
17455
- }
17456
- if (code != null && code !== token.text) {
17457
- token.text = code;
17458
- token.escaped = true;
17459
- }
17460
-
17461
- pending--;
17462
- if (pending === 0) {
17463
- done();
17464
- }
17465
- });
17466
- }, 0);
17467
- }
17468
- });
17469
-
17470
- if (pending === 0) {
17471
- done();
17472
- }
17473
-
17474
- return;
17475
- }
17476
-
17477
- try {
17478
- const tokens = Lexer.lex(src, opt);
17479
- if (opt.walkTokens) {
17480
- marked.walkTokens(tokens, opt.walkTokens);
17481
- }
17482
- return Parser.parse(tokens, opt);
17483
- } catch (e) {
17484
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
17485
- if (opt.silent) {
17486
- return '<p>An error occurred:</p><pre>'
17487
- + marked_esm_escape(e.message + '', true)
17488
- + '</pre>';
17489
- }
17490
- throw e;
17491
- }
17492
- }
17493
-
17494
- /**
17495
- * Options
17496
- */
17497
-
17498
- marked.options =
17499
- marked.setOptions = function(opt) {
17500
- merge(marked.defaults, opt);
17501
- changeDefaults(marked.defaults);
17502
- return marked;
17503
- };
17504
-
17505
- marked.getDefaults = getDefaults;
17506
-
17507
- marked.defaults = defaults;
17508
-
17509
- /**
17510
- * Use Extension
17511
- */
17512
-
17513
- marked.use = function(...args) {
17514
- const opts = merge({}, ...args);
17515
- const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
17516
- let hasExtensions;
17517
-
17518
- args.forEach((pack) => {
17519
- // ==-- Parse "addon" extensions --== //
17520
- if (pack.extensions) {
17521
- hasExtensions = true;
17522
- pack.extensions.forEach((ext) => {
17523
- if (!ext.name) {
17524
- throw new Error('extension name required');
17525
- }
17526
- if (ext.renderer) { // Renderer extensions
17527
- const prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;
17528
- if (prevRenderer) {
17529
- // Replace extension with func to run new extension but fall back if false
17530
- extensions.renderers[ext.name] = function(...args) {
17531
- let ret = ext.renderer.apply(this, args);
17532
- if (ret === false) {
17533
- ret = prevRenderer.apply(this, args);
17534
- }
17535
- return ret;
17536
- };
17537
- } else {
17538
- extensions.renderers[ext.name] = ext.renderer;
17539
- }
17540
- }
17541
- if (ext.tokenizer) { // Tokenizer Extensions
17542
- if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
17543
- throw new Error("extension level must be 'block' or 'inline'");
17544
- }
17545
- if (extensions[ext.level]) {
17546
- extensions[ext.level].unshift(ext.tokenizer);
17547
- } else {
17548
- extensions[ext.level] = [ext.tokenizer];
17549
- }
17550
- if (ext.start) { // Function to check for start of token
17551
- if (ext.level === 'block') {
17552
- if (extensions.startBlock) {
17553
- extensions.startBlock.push(ext.start);
17554
- } else {
17555
- extensions.startBlock = [ext.start];
17556
- }
17557
- } else if (ext.level === 'inline') {
17558
- if (extensions.startInline) {
17559
- extensions.startInline.push(ext.start);
17560
- } else {
17561
- extensions.startInline = [ext.start];
17562
- }
17563
- }
17564
- }
17565
- }
17566
- if (ext.childTokens) { // Child tokens to be visited by walkTokens
17567
- extensions.childTokens[ext.name] = ext.childTokens;
17568
- }
17569
- });
17570
- }
17571
-
17572
- // ==-- Parse "overwrite" extensions --== //
17573
- if (pack.renderer) {
17574
- const renderer = marked.defaults.renderer || new Renderer();
17575
- for (const prop in pack.renderer) {
17576
- const prevRenderer = renderer[prop];
17577
- // Replace renderer with func to run extension, but fall back if false
17578
- renderer[prop] = (...args) => {
17579
- let ret = pack.renderer[prop].apply(renderer, args);
17580
- if (ret === false) {
17581
- ret = prevRenderer.apply(renderer, args);
17582
- }
17583
- return ret;
17584
- };
17585
- }
17586
- opts.renderer = renderer;
17587
- }
17588
- if (pack.tokenizer) {
17589
- const tokenizer = marked.defaults.tokenizer || new Tokenizer();
17590
- for (const prop in pack.tokenizer) {
17591
- const prevTokenizer = tokenizer[prop];
17592
- // Replace tokenizer with func to run extension, but fall back if false
17593
- tokenizer[prop] = (...args) => {
17594
- let ret = pack.tokenizer[prop].apply(tokenizer, args);
17595
- if (ret === false) {
17596
- ret = prevTokenizer.apply(tokenizer, args);
17597
- }
17598
- return ret;
17599
- };
17600
- }
17601
- opts.tokenizer = tokenizer;
17602
- }
17603
-
17604
- // ==-- Parse WalkTokens extensions --== //
17605
- if (pack.walkTokens) {
17606
- const walkTokens = marked.defaults.walkTokens;
17607
- opts.walkTokens = function(token) {
17608
- pack.walkTokens.call(this, token);
17609
- if (walkTokens) {
17610
- walkTokens.call(this, token);
17611
- }
17612
- };
17613
- }
17614
-
17615
- if (hasExtensions) {
17616
- opts.extensions = extensions;
17617
- }
17618
-
17619
- marked.setOptions(opts);
17620
- });
17621
- };
17622
-
17623
- /**
17624
- * Run callback for every token
17625
- */
17626
-
17627
- marked.walkTokens = function(tokens, callback) {
17628
- for (const token of tokens) {
17629
- callback.call(marked, token);
17630
- switch (token.type) {
17631
- case 'table': {
17632
- for (const cell of token.header) {
17633
- marked.walkTokens(cell.tokens, callback);
17634
- }
17635
- for (const row of token.rows) {
17636
- for (const cell of row) {
17637
- marked.walkTokens(cell.tokens, callback);
17638
- }
17639
- }
17640
- break;
17641
- }
17642
- case 'list': {
17643
- marked.walkTokens(token.items, callback);
17644
- break;
17645
- }
17646
- default: {
17647
- if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { // Walk any extensions
17648
- marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
17649
- marked.walkTokens(token[childTokens], callback);
17650
- });
17651
- } else if (token.tokens) {
17652
- marked.walkTokens(token.tokens, callback);
17653
- }
17654
- }
17655
- }
17656
- }
17657
- };
17658
-
17659
- /**
17660
- * Parse Inline
17661
- * @param {string} src
17662
- */
17663
- marked.parseInline = function(src, opt) {
17664
- // throw error in case of non string input
17665
- if (typeof src === 'undefined' || src === null) {
17666
- throw new Error('marked.parseInline(): input parameter is undefined or null');
17667
- }
17668
- if (typeof src !== 'string') {
17669
- throw new Error('marked.parseInline(): input parameter is of type '
17670
- + Object.prototype.toString.call(src) + ', string expected');
17671
- }
17672
-
17673
- opt = merge({}, marked.defaults, opt || {});
17674
- checkSanitizeDeprecation(opt);
17675
-
17676
- try {
17677
- const tokens = Lexer.lexInline(src, opt);
17678
- if (opt.walkTokens) {
17679
- marked.walkTokens(tokens, opt.walkTokens);
17680
- }
17681
- return Parser.parseInline(tokens, opt);
17682
- } catch (e) {
17683
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
17684
- if (opt.silent) {
17685
- return '<p>An error occurred:</p><pre>'
17686
- + marked_esm_escape(e.message + '', true)
17687
- + '</pre>';
17688
- }
17689
- throw e;
17690
- }
17691
- };
17692
-
17693
- /**
17694
- * Expose
17695
- */
17696
- marked.Parser = Parser;
17697
- marked.parser = Parser.parse;
17698
- marked.Renderer = Renderer;
17699
- marked.TextRenderer = TextRenderer;
17700
- marked.Lexer = Lexer;
17701
- marked.lexer = Lexer.lex;
17702
- marked.Tokenizer = Tokenizer;
17703
- marked.Slugger = Slugger;
17704
- marked.parse = marked;
17705
-
17706
- const options = marked.options;
17707
- const setOptions = marked.setOptions;
17708
- const use = marked.use;
17709
- const walkTokens = marked.walkTokens;
17710
- const parseInline = marked.parseInline;
17711
- const parse = (/* unused pure expression or super */ null && (marked));
17712
- const parser = Parser.parse;
17713
- const lexer = Lexer.lex;
17714
-
17715
-
17716
-
17717
- ;// CONCATENATED MODULE: ./src/javascripts/lib/parse-body.js
17718
-
17719
- /* harmony default export */ const parse_body = (body => {
17720
- try {
17721
- return marked(body);
17722
- } catch (e) {
17723
- console.log('Could not parse message', body, e);
17724
- return '';
17725
- }
17726
- });
17727
- ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js
17728
-
17729
-
17730
-
17731
- const useEventLinkClickHandler = eventId => {
17732
- const {
17733
- sendAction
17734
- } = use_seamly_commands();
17735
-
17736
- const eventClick = e => {
17737
- if (e.target && e.target.dataset.linkId) {
17738
- sendAction({
17739
- type: actionTypes.navigate,
17740
- originMessage: eventId,
17741
- link: {
17742
- id: e.target.dataset.linkId,
17743
- url: e.target.getAttribute('href')
17744
- }
17745
- });
17746
- }
17747
- };
17748
-
17749
- return eventClick;
17750
- };
17751
-
17752
- /* harmony default export */ const use_event_link_click_handler = (useEventLinkClickHandler);
17753
- ;// CONCATENATED MODULE: ./node_modules/mustache/mustache.mjs
17754
- /*!
17755
- * mustache.js - Logic-less {{mustache}} templates with JavaScript
17756
- * http://github.com/janl/mustache.js
17757
- */
17758
-
17759
- var objectToString = Object.prototype.toString;
17760
- var isArray = Array.isArray || function isArrayPolyfill (object) {
17761
- return objectToString.call(object) === '[object Array]';
17762
- };
17763
-
17764
- function isFunction (object) {
17765
- return typeof object === 'function';
17766
- }
17767
-
17768
- /**
17769
- * More correct typeof string handling array
17770
- * which normally returns typeof 'object'
17771
- */
17772
- function typeStr (obj) {
17773
- return isArray(obj) ? 'array' : typeof obj;
17774
- }
17775
-
17776
- function escapeRegExp (string) {
17777
- return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
17778
- }
17779
-
17780
- /**
17781
- * Null safe way of checking whether or not an object,
17782
- * including its prototype, has a given property
17783
- */
17784
- function hasProperty (obj, propName) {
17785
- return obj != null && typeof obj === 'object' && (propName in obj);
17786
- }
17787
-
17788
- /**
17789
- * Safe way of detecting whether or not the given thing is a primitive and
17790
- * whether it has the given property
17791
- */
17792
- function primitiveHasOwnProperty (primitive, propName) {
17793
- return (
17794
- primitive != null
17795
- && typeof primitive !== 'object'
17796
- && primitive.hasOwnProperty
17797
- && primitive.hasOwnProperty(propName)
17798
- );
17799
- }
17800
-
17801
- // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
17802
- // See https://github.com/janl/mustache.js/issues/189
17803
- var regExpTest = RegExp.prototype.test;
17804
- function testRegExp (re, string) {
17805
- return regExpTest.call(re, string);
17806
- }
17807
-
17808
- var nonSpaceRe = /\S/;
17809
- function isWhitespace (string) {
17810
- return !testRegExp(nonSpaceRe, string);
17811
- }
17812
-
17813
- var entityMap = {
17814
- '&': '&amp;',
17815
- '<': '&lt;',
17816
- '>': '&gt;',
17817
- '"': '&quot;',
17818
- "'": '&#39;',
17819
- '/': '&#x2F;',
17820
- '`': '&#x60;',
17821
- '=': '&#x3D;'
17822
- };
17823
-
17824
- function escapeHtml (string) {
17825
- return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
17826
- return entityMap[s];
17827
- });
17828
- }
17829
-
17830
- var whiteRe = /\s*/;
17831
- var spaceRe = /\s+/;
17832
- var equalsRe = /\s*=/;
17833
- var curlyRe = /\s*\}/;
17834
- var tagRe = /#|\^|\/|>|\{|&|=|!/;
17835
-
17836
- /**
17837
- * Breaks up the given `template` string into a tree of tokens. If the `tags`
17838
- * argument is given here it must be an array with two string values: the
17839
- * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
17840
- * course, the default is to use mustaches (i.e. mustache.tags).
17841
- *
17842
- * A token is an array with at least 4 elements. The first element is the
17843
- * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
17844
- * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
17845
- * all text that appears outside a symbol this element is "text".
17846
- *
17847
- * The second element of a token is its "value". For mustache tags this is
17848
- * whatever else was inside the tag besides the opening symbol. For text tokens
17849
- * this is the text itself.
17850
- *
17851
- * The third and fourth elements of the token are the start and end indices,
17852
- * respectively, of the token in the original template.
17853
- *
17854
- * Tokens that are the root node of a subtree contain two more elements: 1) an
17855
- * array of tokens in the subtree and 2) the index in the original template at
17856
- * which the closing tag for that section begins.
17857
- *
17858
- * Tokens for partials also contain two more elements: 1) a string value of
17859
- * indendation prior to that tag and 2) the index of that tag on that line -
17860
- * eg a value of 2 indicates the partial is the third tag on this line.
17861
- */
17862
- function parseTemplate (template, tags) {
17863
- if (!template)
17864
- return [];
17865
- var lineHasNonSpace = false;
17866
- var sections = []; // Stack to hold section tokens
17867
- var tokens = []; // Buffer to hold the tokens
17868
- var spaces = []; // Indices of whitespace tokens on the current line
17869
- var hasTag = false; // Is there a {{tag}} on the current line?
17870
- var nonSpace = false; // Is there a non-space char on the current line?
17871
- var indentation = ''; // Tracks indentation for tags that use it
17872
- var tagIndex = 0; // Stores a count of number of tags encountered on a line
17873
-
17874
- // Strips all whitespace tokens array for the current line
17875
- // if there was a {{#tag}} on it and otherwise only space.
17876
- function stripSpace () {
17877
- if (hasTag && !nonSpace) {
17878
- while (spaces.length)
17879
- delete tokens[spaces.pop()];
17880
- } else {
17881
- spaces = [];
17882
- }
17883
-
17884
- hasTag = false;
17885
- nonSpace = false;
17886
- }
17887
-
17888
- var openingTagRe, closingTagRe, closingCurlyRe;
17889
- function compileTags (tagsToCompile) {
17890
- if (typeof tagsToCompile === 'string')
17891
- tagsToCompile = tagsToCompile.split(spaceRe, 2);
17892
-
17893
- if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
17894
- throw new Error('Invalid tags: ' + tagsToCompile);
17895
-
17896
- openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
17897
- closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
17898
- closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
17899
- }
17900
-
17901
- compileTags(tags || mustache.tags);
17902
-
17903
- var scanner = new Scanner(template);
17904
-
17905
- var start, type, value, chr, token, openSection;
17906
- while (!scanner.eos()) {
17907
- start = scanner.pos;
17908
-
17909
- // Match any text between tags.
17910
- value = scanner.scanUntil(openingTagRe);
17911
-
17912
- if (value) {
17913
- for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
17914
- chr = value.charAt(i);
17915
-
17916
- if (isWhitespace(chr)) {
17917
- spaces.push(tokens.length);
17918
- indentation += chr;
17919
- } else {
17920
- nonSpace = true;
17921
- lineHasNonSpace = true;
17922
- indentation += ' ';
17923
- }
17924
-
17925
- tokens.push([ 'text', chr, start, start + 1 ]);
17926
- start += 1;
17927
-
17928
- // Check for whitespace on the current line.
17929
- if (chr === '\n') {
17930
- stripSpace();
17931
- indentation = '';
17932
- tagIndex = 0;
17933
- lineHasNonSpace = false;
17934
- }
17935
- }
17936
- }
17937
-
17938
- // Match the opening tag.
17939
- if (!scanner.scan(openingTagRe))
17940
- break;
17941
-
17942
- hasTag = true;
17943
-
17944
- // Get the tag type.
17945
- type = scanner.scan(tagRe) || 'name';
17946
- scanner.scan(whiteRe);
17947
-
17948
- // Get the tag value.
17949
- if (type === '=') {
17950
- value = scanner.scanUntil(equalsRe);
17951
- scanner.scan(equalsRe);
17952
- scanner.scanUntil(closingTagRe);
17953
- } else if (type === '{') {
17954
- value = scanner.scanUntil(closingCurlyRe);
17955
- scanner.scan(curlyRe);
17956
- scanner.scanUntil(closingTagRe);
17957
- type = '&';
17958
- } else {
17959
- value = scanner.scanUntil(closingTagRe);
17960
- }
17961
-
17962
- // Match the closing tag.
17963
- if (!scanner.scan(closingTagRe))
17964
- throw new Error('Unclosed tag at ' + scanner.pos);
17965
-
17966
- if (type == '>') {
17967
- token = [ type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace ];
17968
- } else {
17969
- token = [ type, value, start, scanner.pos ];
17970
- }
17971
- tagIndex++;
17972
- tokens.push(token);
17973
-
17974
- if (type === '#' || type === '^') {
17975
- sections.push(token);
17976
- } else if (type === '/') {
17977
- // Check section nesting.
17978
- openSection = sections.pop();
17979
-
17980
- if (!openSection)
17981
- throw new Error('Unopened section "' + value + '" at ' + start);
17982
-
17983
- if (openSection[1] !== value)
17984
- throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
17985
- } else if (type === 'name' || type === '{' || type === '&') {
17986
- nonSpace = true;
17987
- } else if (type === '=') {
17988
- // Set the tags for the next time around.
17989
- compileTags(value);
17990
- }
17991
- }
17992
-
17993
- stripSpace();
17994
-
17995
- // Make sure there are no open sections when we're done.
17996
- openSection = sections.pop();
17997
-
17998
- if (openSection)
17999
- throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
18000
-
18001
- return nestTokens(squashTokens(tokens));
18002
- }
18003
-
18004
- /**
18005
- * Combines the values of consecutive text tokens in the given `tokens` array
18006
- * to a single token.
18007
- */
18008
- function squashTokens (tokens) {
18009
- var squashedTokens = [];
18010
-
18011
- var token, lastToken;
18012
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
18013
- token = tokens[i];
18014
-
18015
- if (token) {
18016
- if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
18017
- lastToken[1] += token[1];
18018
- lastToken[3] = token[3];
18019
- } else {
18020
- squashedTokens.push(token);
18021
- lastToken = token;
18022
- }
18023
- }
18024
- }
18025
-
18026
- return squashedTokens;
18027
- }
18028
-
18029
- /**
18030
- * Forms the given array of `tokens` into a nested tree structure where
18031
- * tokens that represent a section have two additional items: 1) an array of
18032
- * all tokens that appear in that section and 2) the index in the original
18033
- * template that represents the end of that section.
18034
- */
18035
- function nestTokens (tokens) {
18036
- var nestedTokens = [];
18037
- var collector = nestedTokens;
18038
- var sections = [];
18039
-
18040
- var token, section;
18041
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
18042
- token = tokens[i];
18043
-
18044
- switch (token[0]) {
18045
- case '#':
18046
- case '^':
18047
- collector.push(token);
18048
- sections.push(token);
18049
- collector = token[4] = [];
18050
- break;
18051
- case '/':
18052
- section = sections.pop();
18053
- section[5] = token[2];
18054
- collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
18055
- break;
18056
- default:
18057
- collector.push(token);
18058
- }
18059
- }
18060
-
18061
- return nestedTokens;
18062
- }
18063
-
18064
- /**
18065
- * A simple string scanner that is used by the template parser to find
18066
- * tokens in template strings.
18067
- */
18068
- function Scanner (string) {
18069
- this.string = string;
18070
- this.tail = string;
18071
- this.pos = 0;
18072
- }
18073
-
18074
- /**
18075
- * Returns `true` if the tail is empty (end of string).
18076
- */
18077
- Scanner.prototype.eos = function eos () {
18078
- return this.tail === '';
18079
- };
18080
-
18081
- /**
18082
- * Tries to match the given regular expression at the current position.
18083
- * Returns the matched text if it can match, the empty string otherwise.
18084
- */
18085
- Scanner.prototype.scan = function scan (re) {
18086
- var match = this.tail.match(re);
18087
-
18088
- if (!match || match.index !== 0)
18089
- return '';
18090
-
18091
- var string = match[0];
18092
-
18093
- this.tail = this.tail.substring(string.length);
18094
- this.pos += string.length;
18095
-
18096
- return string;
18097
- };
18098
-
18099
- /**
18100
- * Skips all text until the given regular expression can be matched. Returns
18101
- * the skipped string, which is the entire tail if no match can be made.
18102
- */
18103
- Scanner.prototype.scanUntil = function scanUntil (re) {
18104
- var index = this.tail.search(re), match;
18105
-
18106
- switch (index) {
18107
- case -1:
18108
- match = this.tail;
18109
- this.tail = '';
18110
- break;
18111
- case 0:
18112
- match = '';
18113
- break;
18114
- default:
18115
- match = this.tail.substring(0, index);
18116
- this.tail = this.tail.substring(index);
18117
- }
18118
-
18119
- this.pos += match.length;
18120
-
18121
- return match;
18122
- };
18123
-
18124
- /**
18125
- * Represents a rendering context by wrapping a view object and
18126
- * maintaining a reference to the parent context.
18127
- */
18128
- function Context (view, parentContext) {
18129
- this.view = view;
18130
- this.cache = { '.': this.view };
18131
- this.parent = parentContext;
18132
- }
18133
-
18134
- /**
18135
- * Creates a new context using the given view with this context
18136
- * as the parent.
18137
- */
18138
- Context.prototype.push = function push (view) {
18139
- return new Context(view, this);
18140
- };
18141
-
18142
- /**
18143
- * Returns the value of the given name in this context, traversing
18144
- * up the context hierarchy if the value is absent in this context's view.
18145
- */
18146
- Context.prototype.lookup = function lookup (name) {
18147
- var cache = this.cache;
18148
-
18149
- var value;
18150
- if (cache.hasOwnProperty(name)) {
18151
- value = cache[name];
18152
- } else {
18153
- var context = this, intermediateValue, names, index, lookupHit = false;
18154
-
18155
- while (context) {
18156
- if (name.indexOf('.') > 0) {
18157
- intermediateValue = context.view;
18158
- names = name.split('.');
18159
- index = 0;
18160
-
18161
- /**
18162
- * Using the dot notion path in `name`, we descend through the
18163
- * nested objects.
18164
- *
18165
- * To be certain that the lookup has been successful, we have to
18166
- * check if the last object in the path actually has the property
18167
- * we are looking for. We store the result in `lookupHit`.
18168
- *
18169
- * This is specially necessary for when the value has been set to
18170
- * `undefined` and we want to avoid looking up parent contexts.
18171
- *
18172
- * In the case where dot notation is used, we consider the lookup
18173
- * to be successful even if the last "object" in the path is
18174
- * not actually an object but a primitive (e.g., a string, or an
18175
- * integer), because it is sometimes useful to access a property
18176
- * of an autoboxed primitive, such as the length of a string.
18177
- **/
18178
- while (intermediateValue != null && index < names.length) {
18179
- if (index === names.length - 1)
18180
- lookupHit = (
18181
- hasProperty(intermediateValue, names[index])
18182
- || primitiveHasOwnProperty(intermediateValue, names[index])
18183
- );
18184
-
18185
- intermediateValue = intermediateValue[names[index++]];
18186
- }
18187
- } else {
18188
- intermediateValue = context.view[name];
18189
-
18190
- /**
18191
- * Only checking against `hasProperty`, which always returns `false` if
18192
- * `context.view` is not an object. Deliberately omitting the check
18193
- * against `primitiveHasOwnProperty` if dot notation is not used.
18194
- *
18195
- * Consider this example:
18196
- * ```
18197
- * Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"})
18198
- * ```
18199
- *
18200
- * If we were to check also against `primitiveHasOwnProperty`, as we do
18201
- * in the dot notation case, then render call would return:
18202
- *
18203
- * "The length of a football field is 9."
18204
- *
18205
- * rather than the expected:
18206
- *
18207
- * "The length of a football field is 100 yards."
18208
- **/
18209
- lookupHit = hasProperty(context.view, name);
18210
- }
18211
-
18212
- if (lookupHit) {
18213
- value = intermediateValue;
18214
- break;
18215
- }
18216
-
18217
- context = context.parent;
18218
- }
18219
-
18220
- cache[name] = value;
18221
- }
18222
-
18223
- if (isFunction(value))
18224
- value = value.call(this.view);
18225
-
18226
- return value;
18227
- };
18228
-
18229
- /**
18230
- * A Writer knows how to take a stream of tokens and render them to a
18231
- * string, given a context. It also maintains a cache of templates to
18232
- * avoid the need to parse the same template twice.
18233
- */
18234
- function Writer () {
18235
- this.templateCache = {
18236
- _cache: {},
18237
- set: function set (key, value) {
18238
- this._cache[key] = value;
18239
- },
18240
- get: function get (key) {
18241
- return this._cache[key];
18242
- },
18243
- clear: function clear () {
18244
- this._cache = {};
18245
- }
18246
- };
14874
+ }))
14875
+ });
18247
14876
  }
18248
14877
 
18249
- /**
18250
- * Clears all cached templates in this writer.
18251
- */
18252
- Writer.prototype.clearCache = function clearCache () {
18253
- if (typeof this.templateCache !== 'undefined') {
18254
- this.templateCache.clear();
18255
- }
18256
- };
14878
+ /* harmony default export */ const message_container = (MessageContainer);
14879
+ ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/choice-prompt.js
14880
+ const choice_prompt_excluded = ["event", "children"];
18257
14881
 
18258
- /**
18259
- * Parses and caches the given `template` according to the given `tags` or
18260
- * `mustache.tags` if `tags` is omitted, and returns the array of tokens
18261
- * that is generated from the parse.
18262
- */
18263
- Writer.prototype.parse = function parse (template, tags) {
18264
- var cache = this.templateCache;
18265
- var cacheKey = template + ':' + (tags || mustache.tags).join(':');
18266
- var isCacheEnabled = typeof cache !== 'undefined';
18267
- var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined;
14882
+ function choice_prompt_objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = choice_prompt_objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
18268
14883
 
18269
- if (tokens == undefined) {
18270
- tokens = parseTemplate(template, tags);
18271
- isCacheEnabled && cache.set(cacheKey, tokens);
18272
- }
18273
- return tokens;
18274
- };
14884
+ function choice_prompt_objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
18275
14885
 
18276
- /**
18277
- * High-level method that is used to render the given `template` with
18278
- * the given `view`.
18279
- *
18280
- * The optional `partials` argument may be an object that contains the
18281
- * names and templates of partials that are used in the template. It may
18282
- * also be a function that is used to load partial templates on the fly
18283
- * that takes a single argument: the name of the partial.
18284
- *
18285
- * If the optional `config` argument is given here, then it should be an
18286
- * object with a `tags` attribute or an `escape` attribute or both.
18287
- * If an array is passed, then it will be interpreted the same way as
18288
- * a `tags` attribute on a `config` object.
18289
- *
18290
- * The `tags` attribute of a `config` object must be an array with two
18291
- * string values: the opening and closing tags used in the template (e.g.
18292
- * [ "<%", "%>" ]). The default is to mustache.tags.
18293
- *
18294
- * The `escape` attribute of a `config` object must be a function which
18295
- * accepts a string as input and outputs a safely escaped string.
18296
- * If an `escape` function is not provided, then an HTML-safe string
18297
- * escaping function is used as the default.
18298
- */
18299
- Writer.prototype.render = function render (template, view, partials, config) {
18300
- var tags = this.getConfigTags(config);
18301
- var tokens = this.parse(template, tags);
18302
- var context = (view instanceof Context) ? view : new Context(view, undefined);
18303
- return this.renderTokens(tokens, context, partials, template, config);
18304
- };
14886
+ function choice_prompt_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
18305
14887
 
18306
- /**
18307
- * Low-level method that renders the given array of `tokens` using
18308
- * the given `context` and `partials`.
18309
- *
18310
- * Note: The `originalTemplate` is only ever used to extract the portion
18311
- * of the original template that was contained in a higher-order section.
18312
- * If the template doesn't use higher-order sections, this argument may
18313
- * be omitted.
18314
- */
18315
- Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, config) {
18316
- var buffer = '';
14888
+ function choice_prompt_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? choice_prompt_ownKeys(Object(source), !0).forEach(function (key) { choice_prompt_defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : choice_prompt_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
18317
14889
 
18318
- var token, symbol, value;
18319
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
18320
- value = undefined;
18321
- token = tokens[i];
18322
- symbol = token[0];
14890
+ function choice_prompt_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18323
14891
 
18324
- if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate, config);
18325
- else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate, config);
18326
- else if (symbol === '>') value = this.renderPartial(token, context, partials, config);
18327
- else if (symbol === '&') value = this.unescapedValue(token, context);
18328
- else if (symbol === 'name') value = this.escapedValue(token, context, config);
18329
- else if (symbol === 'text') value = this.rawValue(token);
18330
14892
 
18331
- if (value !== undefined)
18332
- buffer += value;
18333
- }
18334
14893
 
18335
- return buffer;
18336
- };
18337
14894
 
18338
- Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate, config) {
18339
- var self = this;
18340
- var buffer = '';
18341
- var value = context.lookup(token[1]);
18342
14895
 
18343
- // This function is used to render an arbitrary template
18344
- // in the current context by higher-order sections.
18345
- function subRender (template) {
18346
- return self.render(template, context, partials, config);
18347
- }
18348
14896
 
18349
- if (!value) return;
18350
14897
 
18351
- if (isArray(value)) {
18352
- for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
18353
- buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config);
18354
- }
18355
- } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
18356
- buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config);
18357
- } else if (isFunction(value)) {
18358
- if (typeof originalTemplate !== 'string')
18359
- throw new Error('Cannot use higher-order sections without the original template');
18360
14898
 
18361
- // Extract the portion of the original template that the section contains.
18362
- value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
18363
14899
 
18364
- if (value != null)
18365
- buffer += value;
18366
- } else {
18367
- buffer += this.renderTokens(token[4], context, partials, originalTemplate, config);
18368
- }
18369
- return buffer;
18370
- };
18371
14900
 
18372
- Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate, config) {
18373
- var value = context.lookup(token[1]);
18374
14901
 
18375
- // Use JavaScript's definition of falsy. Include empty arrays.
18376
- // See https://github.com/janl/mustache.js/issues/186
18377
- if (!value || (isArray(value) && value.length === 0))
18378
- return this.renderTokens(token[4], context, partials, originalTemplate, config);
18379
- };
18380
14902
 
18381
- Writer.prototype.indentPartial = function indentPartial (partial, indentation, lineHasNonSpace) {
18382
- var filteredIndentation = indentation.replace(/[^ \t]/g, '');
18383
- var partialByNl = partial.split('\n');
18384
- for (var i = 0; i < partialByNl.length; i++) {
18385
- if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) {
18386
- partialByNl[i] = filteredIndentation + partialByNl[i];
18387
- }
18388
- }
18389
- return partialByNl.join('\n');
18390
- };
18391
14903
 
18392
- Writer.prototype.renderPartial = function renderPartial (token, context, partials, config) {
18393
- if (!partials) return;
18394
- var tags = this.getConfigTags(config);
14904
+ const useChoicePrompt = event => {
14905
+ const {
14906
+ payload
14907
+ } = event;
14908
+ const [showOptions, setShowOptions] = (0,hooks_namespaceObject.useState)(false);
14909
+ const {
14910
+ sendAction,
14911
+ addMessageBubble,
14912
+ addDivider
14913
+ } = use_seamly_commands();
14914
+ const {
14915
+ activeServiceSessionId
14916
+ } = useSeamlyServiceInfo();
14917
+ const lastEventId = useLastMessageEventId();
14918
+ const [body] = useTranslatedEventData(event);
14919
+ const {
14920
+ service
14921
+ } = payload;
14922
+ const subEvent = (0,hooks_namespaceObject.useMemo)(() => {
14923
+ return choice_prompt_objectSpread(choice_prompt_objectSpread({}, event), {}, {
14924
+ payload: choice_prompt_objectSpread(choice_prompt_objectSpread({}, event.payload), {}, {
14925
+ body: event.payload.body?.prompt,
14926
+ translatedBody: event.payload.translatedBody && choice_prompt_objectSpread(choice_prompt_objectSpread({}, event.payload.translatedBody), {}, {
14927
+ data: event.payload.translatedBody.data.prompt
14928
+ })
14929
+ })
14930
+ });
14931
+ }, [event]);
14932
+ const chooseAgain = body.chooseAgain && activeServiceSessionId === service.serviceSessionId && payload.id !== lastEventId;
14933
+ (0,hooks_namespaceObject.useEffect)(() => {
14934
+ setShowOptions(payload.id === lastEventId);
14935
+ }, [payload, lastEventId]);
18395
14936
 
18396
- var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
18397
- if (value != null) {
18398
- var lineHasNonSpace = token[6];
18399
- var tagIndex = token[5];
18400
- var indentation = token[4];
18401
- var indentedValue = value;
18402
- if (tagIndex == 0 && indentation) {
18403
- indentedValue = this.indentPartial(value, indentation, lineHasNonSpace);
14937
+ const onChoiceClickHandler = choice => {
14938
+ if (chooseAgain) {
14939
+ addDivider('new_topic');
18404
14940
  }
18405
- var tokens = this.parse(indentedValue, tags);
18406
- return this.renderTokens(tokens, context, partials, indentedValue, config);
18407
- }
18408
- };
18409
-
18410
- Writer.prototype.unescapedValue = function unescapedValue (token, context) {
18411
- var value = context.lookup(token[1]);
18412
- if (value != null)
18413
- return value;
18414
- };
18415
-
18416
- Writer.prototype.escapedValue = function escapedValue (token, context, config) {
18417
- var escape = this.getConfigEscape(config) || mustache.escape;
18418
- var value = context.lookup(token[1]);
18419
- if (value != null)
18420
- return (typeof value === 'number' && escape === mustache.escape) ? String(value) : escape(value);
18421
- };
18422
-
18423
- Writer.prototype.rawValue = function rawValue (token) {
18424
- return token[1];
18425
- };
18426
-
18427
- Writer.prototype.getConfigTags = function getConfigTags (config) {
18428
- if (isArray(config)) {
18429
- return config;
18430
- }
18431
- else if (config && typeof config === 'object') {
18432
- return config.tags;
18433
- }
18434
- else {
18435
- return undefined;
18436
- }
18437
- };
18438
-
18439
- Writer.prototype.getConfigEscape = function getConfigEscape (config) {
18440
- if (config && typeof config === 'object' && !isArray(config)) {
18441
- return config.escape;
18442
- }
18443
- else {
18444
- return undefined;
18445
- }
18446
- };
18447
-
18448
- var mustache = {
18449
- name: 'mustache.js',
18450
- version: '4.2.0',
18451
- tags: [ '{{', '}}' ],
18452
- clearCache: undefined,
18453
- escape: undefined,
18454
- parse: undefined,
18455
- render: undefined,
18456
- Scanner: undefined,
18457
- Context: undefined,
18458
- Writer: undefined,
18459
- /**
18460
- * Allows a user to override the default caching strategy, by providing an
18461
- * object with set, get and clear methods. This can also be used to disable
18462
- * the cache by setting it to the literal `undefined`.
18463
- */
18464
- set templateCache (cache) {
18465
- defaultWriter.templateCache = cache;
18466
- },
18467
- /**
18468
- * Gets the default or overridden caching object from the default writer.
18469
- */
18470
- get templateCache () {
18471
- return defaultWriter.templateCache;
18472
- }
18473
- };
18474
14941
 
18475
- // All high-level mustache.* functions use this writer.
18476
- var defaultWriter = new Writer();
14942
+ addMessageBubble(choice.text);
14943
+ sendAction({
14944
+ type: actionTypes.pickChoice,
14945
+ originMessage: payload.id,
14946
+ choice: {
14947
+ id: choice.id,
14948
+ text: choice.text,
14949
+ chooseAgain
14950
+ }
14951
+ });
14952
+ setShowOptions(false);
14953
+ };
18477
14954
 
18478
- /**
18479
- * Clears all cached templates in the default writer.
18480
- */
18481
- mustache.clearCache = function clearCache () {
18482
- return defaultWriter.clearCache();
18483
- };
14955
+ const onChooseAgainClickHandler = () => {
14956
+ setShowOptions(s => !s);
14957
+ };
18484
14958
 
18485
- /**
18486
- * Parses and caches the given template in the default writer and returns the
18487
- * array of tokens it contains. Doing this ahead of time avoids the need to
18488
- * parse templates on the fly as they are rendered.
18489
- */
18490
- mustache.parse = function parse (template, tags) {
18491
- return defaultWriter.parse(template, tags);
14959
+ return {
14960
+ body,
14961
+ subEvent,
14962
+ showOptions,
14963
+ chooseAgain,
14964
+ onChoiceClickHandler,
14965
+ onChooseAgainClickHandler
14966
+ };
18492
14967
  };
18493
14968
 
18494
- /**
18495
- * Renders the `template` with the given `view`, `partials`, and `config`
18496
- * using the default writer.
18497
- */
18498
- mustache.render = function render (template, view, partials, config) {
18499
- if (typeof template !== 'string') {
18500
- throw new TypeError('Invalid template! Template should be a "string" ' +
18501
- 'but "' + typeStr(template) + '" was given as the first ' +
18502
- 'argument for mustache#render(template, view, partials)');
18503
- }
14969
+ const ChoicePrompt = _ref => {
14970
+ let {
14971
+ event,
14972
+ children
14973
+ } = _ref,
14974
+ props = choice_prompt_objectWithoutProperties(_ref, choice_prompt_excluded);
18504
14975
 
18505
- return defaultWriter.render(template, view, partials, config);
14976
+ const {
14977
+ t
14978
+ } = useI18n();
14979
+ const descriptorId = useGeneratedId();
14980
+ const {
14981
+ body,
14982
+ subEvent,
14983
+ showOptions,
14984
+ chooseAgain,
14985
+ onChoiceClickHandler,
14986
+ onChooseAgainClickHandler
14987
+ } = useChoicePrompt(event);
14988
+ return (0,jsx_runtime_namespaceObject.jsxs)(jsx_runtime_namespaceObject.Fragment, {
14989
+ children: [(0,external_preact_namespaceObject.toChildArray)(children).map(child => {
14990
+ child.props = choice_prompt_objectSpread(choice_prompt_objectSpread({}, child.props), {}, {
14991
+ event: subEvent,
14992
+ descriptorId,
14993
+ showTranslationToggle: false
14994
+ });
14995
+ return child;
14996
+ }), chooseAgain && (0,jsx_runtime_namespaceObject.jsxs)("button", {
14997
+ type: "button",
14998
+ className: css_className('button', 'button--secondary', 'button--choose-again'),
14999
+ "aria-expanded": showOptions ? 'true' : 'false',
15000
+ onClick: onChooseAgainClickHandler,
15001
+ "aria-describedby": descriptorId,
15002
+ children: [showOptions ? t('message.choicePrompts.cancelChooseAgain') : t('message.choicePrompts.chooseAgain'), (0,jsx_runtime_namespaceObject.jsx)(icon, {
15003
+ name: "chevronDown",
15004
+ size: "8"
15005
+ })]
15006
+ }), showOptions && (0,jsx_runtime_namespaceObject.jsx)(message_container, choice_prompt_objectSpread(choice_prompt_objectSpread({
15007
+ type: "choice-prompt",
15008
+ showParticipant: false,
15009
+ event: event
15010
+ }, props), {}, {
15011
+ children: (0,jsx_runtime_namespaceObject.jsx)("ul", {
15012
+ className: css_className('choice-prompt', 'choice-prompt--many'),
15013
+ children: body.choices.map(choice => (0,jsx_runtime_namespaceObject.jsx)("li", {
15014
+ className: css_className('choice-prompt__item', {
15015
+ [`choice-prompt__item--${choice.category}`]: choice.category
15016
+ }),
15017
+ children: (0,jsx_runtime_namespaceObject.jsx)("button", {
15018
+ type: "button",
15019
+ className: css_className('button', 'button--primary'),
15020
+ onClick: () => {
15021
+ onChoiceClickHandler(choice);
15022
+ },
15023
+ children: choice.text
15024
+ })
15025
+ }, choice.id))
15026
+ })
15027
+ }))]
15028
+ });
18506
15029
  };
18507
15030
 
18508
- // Export the escaping function so that the user may override it.
18509
- // See https://github.com/janl/mustache.js/issues/244
18510
- mustache.escape = escapeHtml;
18511
-
18512
- // Export these mainly for testing, but also for advanced usage.
18513
- mustache.Scanner = Scanner;
18514
- mustache.Context = Context;
18515
- mustache.Writer = Writer;
18516
-
18517
- /* harmony default export */ const mustache_mustache = (mustache);
18518
-
18519
- ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js
18520
-
15031
+ /* harmony default export */ const choice_prompt = (ChoicePrompt);
15032
+ ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js
18521
15033
 
18522
- mustache_mustache.escape = function (escapeText) {
18523
- return escapeText;
18524
- };
18525
15034
 
18526
- const parseLinkVariable = variable => {
18527
- return `<a href='${variable.url}' data-link-id='${variable.id}' ${variable.newTab ? 'target="_blank"' : ''}>${variable.name}</a>`;
18528
- };
18529
15035
 
18530
- function parseRichText(text, variables = {}) {
18531
- const view = {};
18532
- Object.entries(variables).forEach(([key, variable]) => {
18533
- switch (variable.type) {
18534
- case 'link':
18535
- view[key] = parseLinkVariable(variable);
18536
- break;
15036
+ const useEventLinkClickHandler = eventId => {
15037
+ const {
15038
+ sendAction
15039
+ } = use_seamly_commands();
18537
15040
 
18538
- case 'text':
18539
- view[key] = variable.value;
18540
- break;
15041
+ const eventClick = e => {
15042
+ if (e.target && e.target.dataset.linkId) {
15043
+ sendAction({
15044
+ type: actionTypes.navigate,
15045
+ originMessage: eventId,
15046
+ link: {
15047
+ id: e.target.dataset.linkId,
15048
+ url: e.target.getAttribute('href')
15049
+ }
15050
+ });
18541
15051
  }
18542
- }, {}); // Disable escaping as we'll be generating HTML
18543
-
18544
- const oldEscape = mustache_mustache.escape;
18545
-
18546
- mustache_mustache.escape = function (escapeText) {
18547
- return escapeText;
18548
15052
  };
18549
15053
 
18550
- const output = mustache_mustache.render(text, view);
18551
- mustache_mustache.escape = oldEscape;
18552
- return output;
18553
- }
15054
+ return eventClick;
15055
+ };
15056
+
15057
+ /* harmony default export */ const use_event_link_click_handler = (useEventLinkClickHandler);
18554
15058
  ;// CONCATENATED MODULE: ./src/javascripts/ui/components/conversation/event/text.js
18555
15059
  const text_excluded = ["event"];
18556
15060
 
@@ -18570,8 +15074,6 @@ function text_objectWithoutPropertiesLoose(source, excluded) { if (source == nul
18570
15074
 
18571
15075
 
18572
15076
 
18573
-
18574
-
18575
15077
  const Text = _ref => {
18576
15078
  let {
18577
15079
  event
@@ -18581,20 +15083,20 @@ const Text = _ref => {
18581
15083
  const [body] = useTranslatedEventData(event);
18582
15084
  const eventClick = use_event_link_click_handler(event.payload.id);
18583
15085
  const containerProps = (0,hooks_namespaceObject.useMemo)(() => {
18584
- if (!event.payload.fromClient) {
15086
+ if (event.payload.optimisticallyInjected) {
18585
15087
  return {
18586
- bodyProps: {
18587
- dangerouslySetInnerHTML: {
18588
- __html: parseRichText(parse_body(body.text), body.variables)
18589
- }
18590
- }
15088
+ children: (0,jsx_runtime_namespaceObject.jsx)("p", {
15089
+ children: body.text
15090
+ })
18591
15091
  };
18592
15092
  }
18593
15093
 
18594
15094
  return {
18595
- children: (0,jsx_runtime_namespaceObject.jsx)("p", {
18596
- children: body.text
18597
- })
15095
+ bodyProps: {
15096
+ dangerouslySetInnerHTML: {
15097
+ __html: body.text
15098
+ }
15099
+ }
18598
15100
  };
18599
15101
  }, [body, event]);
18600
15102
  return (0,jsx_runtime_namespaceObject.jsx)(message_container, text_objectSpread(text_objectSpread({
@@ -20378,9 +16880,6 @@ const Translation = _ref => {
20378
16880
 
20379
16881
 
20380
16882
 
20381
-
20382
-
20383
-
20384
16883
  const Participant = ({
20385
16884
  event
20386
16885
  }) => {
@@ -20388,11 +16887,8 @@ const Participant = ({
20388
16887
  participant
20389
16888
  } = event.payload;
20390
16889
  const [introduction] = useTranslatedEventData(event);
20391
- const intro = (0,hooks_namespaceObject.useMemo)(() => {
20392
- return introduction ? mustache_mustache.render(parse_body(introduction), participant) : undefined;
20393
- }, [introduction, participant]);
20394
16890
 
20395
- if (!intro) {
16891
+ if (!introduction) {
20396
16892
  return null;
20397
16893
  }
20398
16894
 
@@ -20400,7 +16896,7 @@ const Participant = ({
20400
16896
  graphicSrc: participant.avatar,
20401
16897
  graphicType: participant.avatar ? 'avatar' : undefined,
20402
16898
  iconName: !participant.avatar ? 'balloon' : undefined,
20403
- childrenHTML: intro,
16899
+ childrenHTML: introduction,
20404
16900
  dividerType: "participant"
20405
16901
  });
20406
16902
  };
@@ -20424,8 +16920,6 @@ function splash_objectWithoutPropertiesLoose(source, excluded) { if (source == n
20424
16920
 
20425
16921
 
20426
16922
 
20427
-
20428
-
20429
16923
  const Splash = _ref => {
20430
16924
  let {
20431
16925
  event
@@ -20444,7 +16938,7 @@ const Splash = _ref => {
20444
16938
  }, props), {}, {
20445
16939
  bodyProps: {
20446
16940
  dangerouslySetInnerHTML: {
20447
- __html: parseRichText(parse_body(body.text), body.variables)
16941
+ __html: body.text
20448
16942
  }
20449
16943
  }
20450
16944
  }));
@@ -20544,7 +17038,6 @@ const Upload = _ref => {
20544
17038
 
20545
17039
 
20546
17040
 
20547
-
20548
17041
  const Cta = ({
20549
17042
  event
20550
17043
  }) => {
@@ -20568,7 +17061,7 @@ const Cta = ({
20568
17061
  className: css_className('cta__content'),
20569
17062
  id: descriptionId,
20570
17063
  dangerouslySetInnerHTML: {
20571
- __html: parse_body(body.description)
17064
+ __html: body.description
20572
17065
  },
20573
17066
  onClick: eventClick
20574
17067
  }), (0,jsx_runtime_namespaceObject.jsx)("a", {
@@ -20598,7 +17091,6 @@ function card_component_defineProperty(obj, key, value) { if (key in obj) { Obje
20598
17091
 
20599
17092
 
20600
17093
 
20601
-
20602
17094
  const CardComponent = ({
20603
17095
  id,
20604
17096
  action,
@@ -20682,7 +17174,7 @@ const CardComponent = ({
20682
17174
  }), description && (0,jsx_runtime_namespaceObject.jsx)("div", {
20683
17175
  className: css_className('card__description'),
20684
17176
  dangerouslySetInnerHTML: {
20685
- __html: parse_body(description)
17177
+ __html: description
20686
17178
  }
20687
17179
  }), (0,jsx_runtime_namespaceObject.jsx)(CardActionComponent, card_component_objectSpread(card_component_objectSpread({
20688
17180
  tabIndex: isCarouselItem && !hasFocus ? '-1' : undefined // disable to prevent tabbing through cards
@@ -21033,11 +17525,17 @@ const ConversationSuggestions = _ref => {
21033
17525
  suggestions,
21034
17526
  payload
21035
17527
  } = useSuggestions(event);
17528
+ const events = useEvents();
21036
17529
  const {
21037
17530
  t
21038
17531
  } = useI18n();
21039
17532
  const headingText = t('suggestions.headingText');
21040
- const footerText = t('suggestions.footerText');
17533
+ const footerText = t('suggestions.footerText'); // We check if there is at least one last transaction
17534
+ // to avoid rendering the suggestions before prior events are rendered.
17535
+
17536
+ const hasLastTransactionEvent = (0,hooks_namespaceObject.useMemo)(() => events.some(({
17537
+ payload: eventPayload
17538
+ }) => eventPayload?.transactionLast), [events]);
21041
17539
  const handleClick = (0,hooks_namespaceObject.useCallback)(({
21042
17540
  id,
21043
17541
  question
@@ -21059,7 +17557,7 @@ const ConversationSuggestions = _ref => {
21059
17557
  addMessageBubble(question);
21060
17558
  }, [dispatch, sendAction, payload.id, addMessageBubble]);
21061
17559
 
21062
- if (!isExpanded || userResponded) {
17560
+ if (!isExpanded || userResponded || !hasLastTransactionEvent) {
21063
17561
  return null;
21064
17562
  }
21065
17563
 
@@ -22417,7 +18915,7 @@ const Options = () => {
22417
18915
  return RenderOption ? (0,jsx_runtime_namespaceObject.jsx)(RenderOption, {}) : null;
22418
18916
  };
22419
18917
 
22420
- /* harmony default export */ const options_options = (Options);
18918
+ /* harmony default export */ const options = (Options);
22421
18919
  ;// CONCATENATED MODULE: ./src/javascripts/ui/components/options/options-button.js
22422
18920
 
22423
18921
 
@@ -22581,7 +19079,7 @@ const OptionsButton = () => {
22581
19079
  isActive: panelActive,
22582
19080
  children: (0,jsx_runtime_namespaceObject.jsx)("div", {
22583
19081
  className: css_className('options__dialog'),
22584
- children: (0,jsx_runtime_namespaceObject.jsx)(options_options, {})
19082
+ children: (0,jsx_runtime_namespaceObject.jsx)(options, {})
22585
19083
  })
22586
19084
  }), multiMenu && (0,jsx_runtime_namespaceObject.jsx)(in_out_transition, {
22587
19085
  isActive: menuIsOpen,
@@ -22808,6 +19306,10 @@ function inline_view_defineProperty(obj, key, value) { if (key in obj) { Object.
22808
19306
 
22809
19307
  const InlineView = () => {
22810
19308
  use_seamly_chat();
19309
+ const {
19310
+ showInlineView,
19311
+ containerRef
19312
+ } = useShowInlineView();
22811
19313
  const {
22812
19314
  isOpen
22813
19315
  } = useVisibility();
@@ -22825,6 +19327,7 @@ const InlineView = () => {
22825
19327
  isActive: !isOpen,
22826
19328
  transitionStartState: transitionStartStates.rendered,
22827
19329
  children: (0,jsx_runtime_namespaceObject.jsxs)("div", {
19330
+ ref: containerRef,
22828
19331
  className: css_className('unstarted-wrapper', 'unstarted-wrapper--inline'),
22829
19332
  children: [(0,jsx_runtime_namespaceObject.jsx)(PreChatMessages, {}), (0,jsx_runtime_namespaceObject.jsx)(suggestions, {})]
22830
19333
  })
@@ -22832,7 +19335,8 @@ const InlineView = () => {
22832
19335
  isActive: isOpen,
22833
19336
  transitionStartState: transitionStartStates.rendered,
22834
19337
  children: (0,jsx_runtime_namespaceObject.jsx)(chat, {
22835
- children: (0,jsx_runtime_namespaceObject.jsxs)(chat_frame, {
19338
+ ref: containerRef,
19339
+ children: showInlineView && (0,jsx_runtime_namespaceObject.jsxs)(chat_frame, {
22836
19340
  interruptComponent: interrupt,
22837
19341
  children: [isOpen && (0,jsx_runtime_namespaceObject.jsx)(conversation, {}), (0,jsx_runtime_namespaceObject.jsx)(entry_container, {})]
22838
19342
  })
@@ -25841,6 +22345,7 @@ class API {
25841
22345
  this.configReady = false;
25842
22346
  this.externalId = config.externalId;
25843
22347
  this.layoutMode = layoutMode;
22348
+ this.userResponded = false;
25844
22349
  this.internalProducer = new EventProducer('API');
25845
22350
  this.internal$ = xstream_default().create(this.internalProducer).flatten();
25846
22351
  this.connection$ = this.internal$.filter(event => event.type === 'connection');
@@ -25853,7 +22358,14 @@ class API {
25853
22358
  this.ready = ready;
25854
22359
  }
25855
22360
  });
25856
- this.URLS = {};
22361
+ this.URLS = {}; // We want to reconnect whenever the page is loaded from cache (bfcache).
22362
+ // Older browsers don't support 'pageshow' and 'bfcache' so this will be ignored and work as usual.
22363
+
22364
+ window.addEventListener('pageshow', event => {
22365
+ if (event.persisted && this.connected) {
22366
+ this.connect();
22367
+ }
22368
+ });
25857
22369
  }
25858
22370
 
25859
22371
  getAccessToken() {
@@ -25886,6 +22398,8 @@ class API {
25886
22398
  this.store.set('channelTopic', topic);
25887
22399
  }
25888
22400
 
22401
+ getLocale = locale => locale || this.locale;
22402
+
25889
22403
  clearStore() {
25890
22404
  this.store.delete('accessToken');
25891
22405
  this.store.delete('conversationUrl'); // TODO: Remove `channelName` when all clients have been upgraded past v20.
@@ -25950,6 +22464,8 @@ class API {
25950
22464
  this.setChannelTopic(conversation.channelTopic);
25951
22465
  this.updateUrls(body);
25952
22466
  this.setConversationUrl(this.URLS.conversation);
22467
+ this.locale = conversation.translation?.locale;
22468
+ this.userResponded = conversation.userResponded;
25953
22469
  return initialState;
25954
22470
  } catch (error) {
25955
22471
  if (error.status >= 500) {
@@ -26095,6 +22611,7 @@ class API {
26095
22611
  body
26096
22612
  }) => {
26097
22613
  this.updateUrls(body);
22614
+ this.userResponded = body.conversation.userResponded;
26098
22615
  return omit(body.conversation, ['accessToken', 'channelTopic']);
26099
22616
  }).catch(error => {
26100
22617
  if (error.status === 401) {
@@ -26115,7 +22632,7 @@ class API {
26115
22632
 
26116
22633
  async getTranslations(locale) {
26117
22634
  try {
26118
- const url = `${this.getUrlPrefix('http')}${this.URLS.translations}`.replace('{version}', String(TRANSLATIONS_VERSION)).replace('{locale}', locale);
22635
+ const url = `${this.getUrlPrefix('http')}${this.URLS.translations}`.replace('{version}', String(TRANSLATIONS_VERSION)).replace('{locale}', this.getLocale(locale));
26119
22636
  const request = client_default().get(url);
26120
22637
  const {
26121
22638
  body
@@ -26182,7 +22699,7 @@ class API {
26182
22699
  return {
26183
22700
  clientName: "@seamly/web-ui",
26184
22701
  clientVariant: this.layoutMode,
26185
- clientVersion: "20.4.0",
22702
+ clientVersion: "20.5.0",
26186
22703
  currentUrl: window.location.toString(),
26187
22704
  screenResolution: `${window.screen.width}x${window.screen.height}`,
26188
22705
  timezone: getTimeZone(),
@@ -27196,16 +23713,23 @@ const DeprecatedView = () => {
27196
23713
  openChat,
27197
23714
  closeChat
27198
23715
  } = use_seamly_chat();
27199
- return isVisible && (0,jsx_runtime_namespaceObject.jsxs)(deprecated_app_frame, {
27200
- children: [(0,jsx_runtime_namespaceObject.jsx)(deprecated_toggle_button, {
27201
- onOpenChat: openChat
27202
- }), (0,jsx_runtime_namespaceObject.jsx)(header, {
27203
- onCloseChat: closeChat,
27204
- children: (0,jsx_runtime_namespaceObject.jsx)(agent_info, {})
27205
- }), (0,jsx_runtime_namespaceObject.jsxs)(chat_frame, {
27206
- interruptComponent: interrupt,
27207
- children: [(0,jsx_runtime_namespaceObject.jsx)(conversation, {}), (0,jsx_runtime_namespaceObject.jsx)(entry_container, {})]
27208
- })]
23716
+ const {
23717
+ showInlineView,
23718
+ containerRef
23719
+ } = useShowInlineView();
23720
+ return isVisible && (0,jsx_runtime_namespaceObject.jsx)("div", {
23721
+ ref: containerRef,
23722
+ children: showInlineView && (0,jsx_runtime_namespaceObject.jsxs)(deprecated_app_frame, {
23723
+ children: [(0,jsx_runtime_namespaceObject.jsx)(deprecated_toggle_button, {
23724
+ onOpenChat: openChat
23725
+ }), (0,jsx_runtime_namespaceObject.jsx)(header, {
23726
+ onCloseChat: closeChat,
23727
+ children: (0,jsx_runtime_namespaceObject.jsx)(agent_info, {})
23728
+ }), (0,jsx_runtime_namespaceObject.jsxs)(chat_frame, {
23729
+ interruptComponent: interrupt,
23730
+ children: [(0,jsx_runtime_namespaceObject.jsx)(conversation, {}), (0,jsx_runtime_namespaceObject.jsx)(entry_container, {})]
23731
+ })]
23732
+ })
27209
23733
  });
27210
23734
  };
27211
23735