@incremark/vue 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ function useIncremark(options = {}) {
65
65
  markdown.value = "";
66
66
  isLoading.value = false;
67
67
  }
68
- function render13(content) {
68
+ function render14(content) {
69
69
  const update = parser.render(content);
70
70
  markdown.value = parser.getBuffer();
71
71
  completedBlocks.value = parser.getCompletedBlocks().map((b) => markRaw(b));
@@ -95,7 +95,7 @@ function useIncremark(options = {}) {
95
95
  /** 重置解析器 */
96
96
  reset,
97
97
  /** 一次性渲染(reset + append + finalize) */
98
- render: render13,
98
+ render: render14,
99
99
  /** 解析器实例 */
100
100
  parser
101
101
  };
@@ -154,20 +154,80 @@ function useDevTools(incremark, options = {}) {
154
154
  return devtools;
155
155
  }
156
156
 
157
+ // src/composables/useBlockTransformer.ts
158
+ import { ref as ref3, watch, computed as computed3, onUnmounted as onUnmounted2 } from "vue";
159
+ import {
160
+ createBlockTransformer
161
+ } from "@incremark/core";
162
+ function useBlockTransformer(sourceBlocks, options = {}) {
163
+ const displayBlocksRef = ref3([]);
164
+ const isProcessingRef = ref3(false);
165
+ const isPausedRef = ref3(false);
166
+ const effectRef = ref3(options.effect ?? "none");
167
+ const transformer = createBlockTransformer({
168
+ ...options,
169
+ onChange: (blocks) => {
170
+ displayBlocksRef.value = blocks;
171
+ isProcessingRef.value = transformer.isProcessing();
172
+ isPausedRef.value = transformer.isPausedState();
173
+ }
174
+ });
175
+ watch(
176
+ sourceBlocks,
177
+ (blocks) => {
178
+ transformer.push(blocks);
179
+ const currentDisplaying = displayBlocksRef.value.find((b) => !b.isDisplayComplete);
180
+ if (currentDisplaying) {
181
+ const updated = blocks.find((b) => b.id === currentDisplaying.id);
182
+ if (updated) {
183
+ transformer.update(updated);
184
+ }
185
+ }
186
+ },
187
+ { immediate: true, deep: true }
188
+ );
189
+ onUnmounted2(() => {
190
+ transformer.destroy();
191
+ });
192
+ return {
193
+ displayBlocks: computed3(() => displayBlocksRef.value),
194
+ isProcessing: computed3(() => isProcessingRef.value),
195
+ isPaused: computed3(() => isPausedRef.value),
196
+ effect: computed3(() => effectRef.value),
197
+ skip: () => transformer.skip(),
198
+ reset: () => transformer.reset(),
199
+ pause: () => {
200
+ transformer.pause();
201
+ isPausedRef.value = true;
202
+ },
203
+ resume: () => {
204
+ transformer.resume();
205
+ isPausedRef.value = false;
206
+ },
207
+ setOptions: (opts) => {
208
+ transformer.setOptions(opts);
209
+ if (opts.effect !== void 0) {
210
+ effectRef.value = opts.effect;
211
+ }
212
+ },
213
+ transformer
214
+ };
215
+ }
216
+
157
217
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/Incremark.vue?type=script
158
218
  import { defineComponent as _defineComponent11 } from "vue";
159
- import { computed as computed7 } from "vue";
219
+ import { computed as computed8 } from "vue";
160
220
 
161
221
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/IncremarkHeading.vue?type=script
162
222
  import { defineComponent as _defineComponent3 } from "vue";
163
- import { computed as computed4 } from "vue";
223
+ import { computed as computed5 } from "vue";
164
224
 
165
225
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/IncremarkInline.vue?type=script
166
226
  import { defineComponent as _defineComponent2 } from "vue";
167
227
 
168
228
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/IncremarkMath.vue?type=script
169
229
  import { defineComponent as _defineComponent } from "vue";
170
- import { computed as computed3, ref as ref3, watch, shallowRef as shallowRef2, onUnmounted as onUnmounted2 } from "vue";
230
+ import { computed as computed4, ref as ref4, watch as watch2, shallowRef as shallowRef2, onUnmounted as onUnmounted3 } from "vue";
171
231
  var IncremarkMath_default = /* @__PURE__ */ _defineComponent({
172
232
  __name: "IncremarkMath",
173
233
  props: {
@@ -177,13 +237,13 @@ var IncremarkMath_default = /* @__PURE__ */ _defineComponent({
177
237
  setup(__props, { expose: __expose }) {
178
238
  __expose();
179
239
  const props = __props;
180
- const renderedHtml = ref3("");
181
- const renderError = ref3("");
182
- const isLoading = ref3(false);
240
+ const renderedHtml = ref4("");
241
+ const renderError = ref4("");
242
+ const isLoading = ref4(false);
183
243
  const katexRef = shallowRef2(null);
184
244
  let renderTimer = null;
185
- const isInline = computed3(() => props.node.type === "inlineMath");
186
- const formula = computed3(() => props.node.value);
245
+ const isInline = computed4(() => props.node.type === "inlineMath");
246
+ const formula = computed4(() => props.node.value);
187
247
  function scheduleRender() {
188
248
  if (!formula.value) {
189
249
  renderedHtml.value = "";
@@ -218,12 +278,12 @@ var IncremarkMath_default = /* @__PURE__ */ _defineComponent({
218
278
  isLoading.value = false;
219
279
  }
220
280
  }
221
- onUnmounted2(() => {
281
+ onUnmounted3(() => {
222
282
  if (renderTimer) {
223
283
  clearTimeout(renderTimer);
224
284
  }
225
285
  });
226
- watch(formula, scheduleRender, { immediate: true });
286
+ watch2(formula, scheduleRender, { immediate: true });
227
287
  const __returned__ = { props, renderedHtml, renderError, isLoading, katexRef, get renderTimer() {
228
288
  return renderTimer;
229
289
  }, set renderTimer(v) {
@@ -340,6 +400,7 @@ import { renderList as _renderList, Fragment as _Fragment2, openBlock as _openBl
340
400
  var _hoisted_12 = { class: "incremark-inline-code" };
341
401
  var _hoisted_22 = ["href"];
342
402
  var _hoisted_32 = ["src", "alt"];
403
+ var _hoisted_42 = ["innerHTML"];
343
404
  function render2(_ctx, _cache, $props, $setup, $data, $options) {
344
405
  const _component_IncremarkInline = _resolveComponent("IncremarkInline", true);
345
406
  return _openBlock2(true), _createElementBlock2(
@@ -473,6 +534,17 @@ function render2(_ctx, _cache, $props, $setup, $data, $options) {
473
534
  ],
474
535
  2112
475
536
  /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
537
+ )) : node.type === "html" ? (_openBlock2(), _createElementBlock2(
538
+ _Fragment2,
539
+ { key: 9 },
540
+ [
541
+ _createCommentVNode2(" \u539F\u59CB HTML\uFF08\u7528\u4E8E fade-mask \u7B49\u7279\u6B8A\u5143\u7D20\uFF09 "),
542
+ _createElementVNode2("span", {
543
+ innerHTML: node.value
544
+ }, null, 8, _hoisted_42)
545
+ ],
546
+ 2112
547
+ /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */
476
548
  )) : _createCommentVNode2("v-if", true)
477
549
  ],
478
550
  64
@@ -498,7 +570,7 @@ var IncremarkHeading_default = /* @__PURE__ */ _defineComponent3({
498
570
  setup(__props, { expose: __expose }) {
499
571
  __expose();
500
572
  const props = __props;
501
- const tag = computed4(() => `h${props.node.depth}`);
573
+ const tag = computed5(() => `h${props.node.depth}`);
502
574
  const __returned__ = { props, tag, IncremarkInline: IncremarkInline_default2 };
503
575
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
504
576
  return __returned__;
@@ -559,7 +631,7 @@ var IncremarkParagraph_default2 = IncremarkParagraph_default;
559
631
 
560
632
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/IncremarkCode.vue?type=script
561
633
  import { defineComponent as _defineComponent5 } from "vue";
562
- import { computed as computed5, ref as ref4, watch as watch2, shallowRef as shallowRef3, onUnmounted as onUnmounted3 } from "vue";
634
+ import { computed as computed6, ref as ref5, watch as watch3, shallowRef as shallowRef3, onUnmounted as onUnmounted4 } from "vue";
563
635
  var IncremarkCode_default = /* @__PURE__ */ _defineComponent5({
564
636
  __name: "IncremarkCode",
565
637
  props: {
@@ -571,22 +643,22 @@ var IncremarkCode_default = /* @__PURE__ */ _defineComponent5({
571
643
  setup(__props, { expose: __expose }) {
572
644
  __expose();
573
645
  const props = __props;
574
- const copied = ref4(false);
575
- const highlightedHtml = ref4("");
576
- const isHighlighting = ref4(false);
577
- const highlightError = ref4(false);
578
- const mermaidSvg = ref4("");
579
- const mermaidError = ref4("");
580
- const mermaidLoading = ref4(false);
646
+ const copied = ref5(false);
647
+ const highlightedHtml = ref5("");
648
+ const isHighlighting = ref5(false);
649
+ const highlightError = ref5(false);
650
+ const mermaidSvg = ref5("");
651
+ const mermaidError = ref5("");
652
+ const mermaidLoading = ref5(false);
581
653
  const mermaidRef = shallowRef3(null);
582
654
  let mermaidTimer = null;
583
- const mermaidViewMode = ref4("preview");
655
+ const mermaidViewMode = ref5("preview");
584
656
  function toggleMermaidView() {
585
657
  mermaidViewMode.value = mermaidViewMode.value === "preview" ? "source" : "preview";
586
658
  }
587
- const language = computed5(() => props.node.lang || "text");
588
- const code = computed5(() => props.node.value);
589
- const isMermaid = computed5(() => language.value === "mermaid");
659
+ const language = computed6(() => props.node.lang || "text");
660
+ const code = computed6(() => props.node.value);
661
+ const isMermaid = computed6(() => language.value === "mermaid");
590
662
  const highlighterRef = shallowRef3(null);
591
663
  const loadedLanguages = /* @__PURE__ */ new Set();
592
664
  const loadedThemes = /* @__PURE__ */ new Set();
@@ -624,7 +696,7 @@ var IncremarkCode_default = /* @__PURE__ */ _defineComponent5({
624
696
  mermaidLoading.value = false;
625
697
  }
626
698
  }
627
- onUnmounted3(() => {
699
+ onUnmounted4(() => {
628
700
  if (mermaidTimer) {
629
701
  clearTimeout(mermaidTimer);
630
702
  }
@@ -677,7 +749,7 @@ var IncremarkCode_default = /* @__PURE__ */ _defineComponent5({
677
749
  isHighlighting.value = false;
678
750
  }
679
751
  }
680
- watch2([code, () => props.theme, isMermaid], highlight, { immediate: true });
752
+ watch3([code, () => props.theme, isMermaid], highlight, { immediate: true });
681
753
  async function copyCode() {
682
754
  try {
683
755
  await navigator.clipboard.writeText(code.value);
@@ -706,7 +778,7 @@ var _hoisted_14 = {
706
778
  };
707
779
  var _hoisted_23 = { class: "mermaid-header" };
708
780
  var _hoisted_33 = { class: "mermaid-actions" };
709
- var _hoisted_42 = ["disabled"];
781
+ var _hoisted_43 = ["disabled"];
710
782
  var _hoisted_52 = { class: "mermaid-content" };
711
783
  var _hoisted_62 = {
712
784
  key: 0,
@@ -747,7 +819,7 @@ function render5(_ctx, _cache, $props, $setup, $data, $options) {
747
819
  onClick: $setup.toggleMermaidView,
748
820
  type: "button",
749
821
  disabled: !$setup.mermaidSvg
750
- }, _toDisplayString3($setup.mermaidViewMode === "preview" ? "\u6E90\u7801" : "\u9884\u89C8"), 9, _hoisted_42),
822
+ }, _toDisplayString3($setup.mermaidViewMode === "preview" ? "\u6E90\u7801" : "\u9884\u89C8"), 9, _hoisted_43),
751
823
  _createElementVNode3(
752
824
  "button",
753
825
  {
@@ -903,7 +975,7 @@ var IncremarkCode_default2 = IncremarkCode_default;
903
975
 
904
976
  // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/IncremarkList.vue?type=script
905
977
  import { defineComponent as _defineComponent6 } from "vue";
906
- import { computed as computed6 } from "vue";
978
+ import { computed as computed7 } from "vue";
907
979
  var IncremarkList_default = /* @__PURE__ */ _defineComponent6({
908
980
  __name: "IncremarkList",
909
981
  props: {
@@ -912,7 +984,7 @@ var IncremarkList_default = /* @__PURE__ */ _defineComponent6({
912
984
  setup(__props, { expose: __expose }) {
913
985
  __expose();
914
986
  const props = __props;
915
- const tag = computed6(() => props.node.ordered ? "ol" : "ul");
987
+ const tag = computed7(() => props.node.ordered ? "ol" : "ul");
916
988
  function getItemContent(item) {
917
989
  const firstChild = item.children[0];
918
990
  if (firstChild?.type === "paragraph") {
@@ -1234,7 +1306,7 @@ var Incremark_default = /* @__PURE__ */ _defineComponent11({
1234
1306
  math: IncremarkMath_default2,
1235
1307
  inlineMath: IncremarkMath_default2
1236
1308
  };
1237
- const mergedComponents = computed7(() => ({
1309
+ const mergedComponents = computed8(() => ({
1238
1310
  ...defaultComponents,
1239
1311
  ...props.components
1240
1312
  }));
@@ -1265,7 +1337,8 @@ function render11(_ctx, _cache, $props, $setup, $data, $options) {
1265
1337
  class: _normalizeClass2([
1266
1338
  "incremark-block",
1267
1339
  block.status === "completed" ? $props.completedClass : $props.pendingClass,
1268
- { "incremark-show-status": $props.showBlockStatus }
1340
+ { "incremark-show-status": $props.showBlockStatus },
1341
+ { "incremark-last-pending": block.isLastPending }
1269
1342
  ])
1270
1343
  },
1271
1344
  [
@@ -1332,7 +1405,160 @@ function render12(_ctx, _cache, $props, $setup, $data, $options) {
1332
1405
  IncremarkRenderer_default.render = render12;
1333
1406
  IncremarkRenderer_default.__file = "src/components/IncremarkRenderer.vue";
1334
1407
  var IncremarkRenderer_default2 = IncremarkRenderer_default;
1408
+
1409
+ // sfc-script:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/AutoScrollContainer.vue?type=script
1410
+ import { defineComponent as _defineComponent13 } from "vue";
1411
+ import { ref as ref6, onMounted as onMounted2, onUnmounted as onUnmounted5, nextTick } from "vue";
1412
+ var AutoScrollContainer_default = /* @__PURE__ */ _defineComponent13({
1413
+ __name: "AutoScrollContainer",
1414
+ props: {
1415
+ enabled: { type: Boolean, required: false, default: true },
1416
+ threshold: { type: Number, required: false, default: 50 },
1417
+ behavior: { type: null, required: false, default: "instant" }
1418
+ },
1419
+ setup(__props, { expose: __expose }) {
1420
+ const props = __props;
1421
+ const containerRef = ref6(null);
1422
+ const isUserScrolledUp = ref6(false);
1423
+ let lastScrollTop = 0;
1424
+ let lastScrollHeight = 0;
1425
+ function isNearBottom() {
1426
+ const container = containerRef.value;
1427
+ if (!container) return true;
1428
+ const { scrollTop, scrollHeight, clientHeight } = container;
1429
+ return scrollHeight - scrollTop - clientHeight <= props.threshold;
1430
+ }
1431
+ function scrollToBottom(force = false) {
1432
+ const container = containerRef.value;
1433
+ if (!container) return;
1434
+ if (isUserScrolledUp.value && !force) return;
1435
+ container.scrollTo({
1436
+ top: container.scrollHeight,
1437
+ behavior: props.behavior
1438
+ });
1439
+ }
1440
+ function hasScrollbar() {
1441
+ const container = containerRef.value;
1442
+ if (!container) return false;
1443
+ return container.scrollHeight > container.clientHeight;
1444
+ }
1445
+ function handleScroll() {
1446
+ const container = containerRef.value;
1447
+ if (!container) return;
1448
+ const { scrollTop, scrollHeight, clientHeight } = container;
1449
+ if (scrollHeight <= clientHeight) {
1450
+ isUserScrolledUp.value = false;
1451
+ lastScrollTop = 0;
1452
+ lastScrollHeight = scrollHeight;
1453
+ return;
1454
+ }
1455
+ if (isNearBottom()) {
1456
+ isUserScrolledUp.value = false;
1457
+ } else {
1458
+ const isScrollingUp = scrollTop < lastScrollTop;
1459
+ const isContentUnchanged = scrollHeight === lastScrollHeight;
1460
+ if (isScrollingUp && isContentUnchanged) {
1461
+ isUserScrolledUp.value = true;
1462
+ }
1463
+ }
1464
+ lastScrollTop = scrollTop;
1465
+ lastScrollHeight = scrollHeight;
1466
+ }
1467
+ let observer = null;
1468
+ onMounted2(() => {
1469
+ if (!containerRef.value) return;
1470
+ lastScrollTop = containerRef.value.scrollTop;
1471
+ lastScrollHeight = containerRef.value.scrollHeight;
1472
+ observer = new MutationObserver(() => {
1473
+ nextTick(() => {
1474
+ if (!containerRef.value) return;
1475
+ if (!hasScrollbar()) {
1476
+ isUserScrolledUp.value = false;
1477
+ }
1478
+ lastScrollHeight = containerRef.value.scrollHeight;
1479
+ if (props.enabled && !isUserScrolledUp.value) {
1480
+ scrollToBottom();
1481
+ }
1482
+ });
1483
+ });
1484
+ observer.observe(containerRef.value, {
1485
+ childList: true,
1486
+ subtree: true,
1487
+ characterData: true
1488
+ });
1489
+ });
1490
+ onUnmounted5(() => {
1491
+ observer?.disconnect();
1492
+ });
1493
+ __expose({
1494
+ /** 强制滚动到底部 */
1495
+ scrollToBottom: () => scrollToBottom(true),
1496
+ /** 是否用户手动向上滚动了 */
1497
+ isUserScrolledUp: () => isUserScrolledUp.value,
1498
+ /** 容器元素引用 */
1499
+ container: containerRef
1500
+ });
1501
+ const __returned__ = { props, containerRef, isUserScrolledUp, get lastScrollTop() {
1502
+ return lastScrollTop;
1503
+ }, set lastScrollTop(v) {
1504
+ lastScrollTop = v;
1505
+ }, get lastScrollHeight() {
1506
+ return lastScrollHeight;
1507
+ }, set lastScrollHeight(v) {
1508
+ lastScrollHeight = v;
1509
+ }, isNearBottom, scrollToBottom, hasScrollbar, handleScroll, get observer() {
1510
+ return observer;
1511
+ }, set observer(v) {
1512
+ observer = v;
1513
+ } };
1514
+ Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
1515
+ return __returned__;
1516
+ }
1517
+ });
1518
+
1519
+ // sfc-template:/Users/yishuai/develop/ai/markdown/packages/vue/src/components/AutoScrollContainer.vue?type=template
1520
+ import { renderSlot as _renderSlot, openBlock as _openBlock13, createElementBlock as _createElementBlock11 } from "vue";
1521
+ function render13(_ctx, _cache, $props, $setup, $data, $options) {
1522
+ return _openBlock13(), _createElementBlock11(
1523
+ "div",
1524
+ {
1525
+ ref: "containerRef",
1526
+ class: "auto-scroll-container",
1527
+ onScroll: $setup.handleScroll
1528
+ },
1529
+ [
1530
+ _renderSlot(_ctx.$slots, "default", {}, void 0, true)
1531
+ ],
1532
+ 544
1533
+ /* NEED_HYDRATION, NEED_PATCH */
1534
+ );
1535
+ }
1536
+
1537
+ // src/components/AutoScrollContainer.vue
1538
+ AutoScrollContainer_default.render = render13;
1539
+ AutoScrollContainer_default.__file = "src/components/AutoScrollContainer.vue";
1540
+ AutoScrollContainer_default.__scopeId = "data-v-e0d180b8";
1541
+ var AutoScrollContainer_default2 = AutoScrollContainer_default;
1542
+
1543
+ // src/index.ts
1544
+ import {
1545
+ BlockTransformer as BlockTransformer2,
1546
+ createBlockTransformer as createBlockTransformer2,
1547
+ countChars,
1548
+ sliceAst,
1549
+ cloneNode,
1550
+ codeBlockPlugin,
1551
+ mermaidPlugin,
1552
+ imagePlugin,
1553
+ mathPlugin,
1554
+ thematicBreakPlugin,
1555
+ defaultPlugins,
1556
+ allPlugins,
1557
+ createPlugin
1558
+ } from "@incremark/core";
1335
1559
  export {
1560
+ AutoScrollContainer_default2 as AutoScrollContainer,
1561
+ BlockTransformer2 as BlockTransformer,
1336
1562
  Incremark_default2 as Incremark,
1337
1563
  IncremarkBlockquote_default2 as IncremarkBlockquote,
1338
1564
  IncremarkCode_default2 as IncremarkCode,
@@ -1345,6 +1571,19 @@ export {
1345
1571
  IncremarkRenderer_default2 as IncremarkRenderer,
1346
1572
  IncremarkTable_default2 as IncremarkTable,
1347
1573
  IncremarkThematicBreak_default2 as IncremarkThematicBreak,
1574
+ allPlugins,
1575
+ cloneNode,
1576
+ codeBlockPlugin,
1577
+ countChars,
1578
+ createBlockTransformer2 as createBlockTransformer,
1579
+ createPlugin,
1580
+ defaultPlugins,
1581
+ imagePlugin,
1582
+ mathPlugin,
1583
+ mermaidPlugin,
1584
+ sliceAst,
1585
+ thematicBreakPlugin,
1586
+ useBlockTransformer,
1348
1587
  useDevTools,
1349
1588
  useIncremark,
1350
1589
  useStreamRenderer