@incremark/core 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -1
- package/dist/index.d.ts +326 -2
- package/dist/index.js +552 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +43 -0
- package/src/transformer/BlockTransformer.ts +552 -0
- package/src/transformer/index.ts +36 -0
- package/src/transformer/plugins.ts +113 -0
- package/src/transformer/styles.css +33 -0
- package/src/transformer/types.ts +114 -0
- package/src/transformer/utils.ts +191 -0
package/dist/index.js
CHANGED
|
@@ -520,6 +520,557 @@ function joinLines(lines, start, end) {
|
|
|
520
520
|
return lines.slice(start, end + 1).join("\n");
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
// src/transformer/utils.ts
|
|
524
|
+
function countChars(node) {
|
|
525
|
+
let count = 0;
|
|
526
|
+
function traverse(n) {
|
|
527
|
+
if (n.value && typeof n.value === "string") {
|
|
528
|
+
count += n.value.length;
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
if (n.children && Array.isArray(n.children)) {
|
|
532
|
+
for (const child of n.children) {
|
|
533
|
+
traverse(child);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
traverse(node);
|
|
538
|
+
return count;
|
|
539
|
+
}
|
|
540
|
+
function sliceAst(node, maxChars, accumulatedChunks) {
|
|
541
|
+
if (maxChars <= 0) return null;
|
|
542
|
+
let remaining = maxChars;
|
|
543
|
+
let charIndex = 0;
|
|
544
|
+
const chunkRanges = [];
|
|
545
|
+
if (accumulatedChunks && accumulatedChunks.chunks.length > 0) {
|
|
546
|
+
let chunkStart = accumulatedChunks.stableChars;
|
|
547
|
+
for (const chunk of accumulatedChunks.chunks) {
|
|
548
|
+
chunkRanges.push({
|
|
549
|
+
start: chunkStart,
|
|
550
|
+
end: chunkStart + chunk.text.length,
|
|
551
|
+
chunk
|
|
552
|
+
});
|
|
553
|
+
chunkStart += chunk.text.length;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
function process(n) {
|
|
557
|
+
if (remaining <= 0) return null;
|
|
558
|
+
if (n.value && typeof n.value === "string") {
|
|
559
|
+
const take = Math.min(n.value.length, remaining);
|
|
560
|
+
remaining -= take;
|
|
561
|
+
if (take === 0) return null;
|
|
562
|
+
const slicedValue = n.value.slice(0, take);
|
|
563
|
+
const nodeStart = charIndex;
|
|
564
|
+
const nodeEnd = charIndex + take;
|
|
565
|
+
charIndex += take;
|
|
566
|
+
const result = {
|
|
567
|
+
...n,
|
|
568
|
+
value: slicedValue
|
|
569
|
+
};
|
|
570
|
+
if (chunkRanges.length > 0 && accumulatedChunks) {
|
|
571
|
+
const nodeChunks = [];
|
|
572
|
+
let firstChunkLocalStart = take;
|
|
573
|
+
for (const range of chunkRanges) {
|
|
574
|
+
const overlapStart = Math.max(range.start, nodeStart);
|
|
575
|
+
const overlapEnd = Math.min(range.end, nodeEnd);
|
|
576
|
+
if (overlapStart < overlapEnd) {
|
|
577
|
+
const localStart = overlapStart - nodeStart;
|
|
578
|
+
const localEnd = overlapEnd - nodeStart;
|
|
579
|
+
const chunkText = slicedValue.slice(localStart, localEnd);
|
|
580
|
+
if (chunkText.length > 0) {
|
|
581
|
+
if (nodeChunks.length === 0) {
|
|
582
|
+
firstChunkLocalStart = localStart;
|
|
583
|
+
}
|
|
584
|
+
nodeChunks.push({
|
|
585
|
+
text: chunkText,
|
|
586
|
+
createdAt: range.chunk.createdAt
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (nodeChunks.length > 0) {
|
|
592
|
+
result.stableLength = firstChunkLocalStart;
|
|
593
|
+
result.chunks = nodeChunks;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return result;
|
|
597
|
+
}
|
|
598
|
+
if (n.children && Array.isArray(n.children)) {
|
|
599
|
+
const newChildren = [];
|
|
600
|
+
for (const child of n.children) {
|
|
601
|
+
if (remaining <= 0) break;
|
|
602
|
+
const processed = process(child);
|
|
603
|
+
if (processed) {
|
|
604
|
+
newChildren.push(processed);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (newChildren.length === 0) {
|
|
608
|
+
return null;
|
|
609
|
+
}
|
|
610
|
+
return { ...n, children: newChildren };
|
|
611
|
+
}
|
|
612
|
+
remaining -= 1;
|
|
613
|
+
charIndex += 1;
|
|
614
|
+
return { ...n };
|
|
615
|
+
}
|
|
616
|
+
return process(node);
|
|
617
|
+
}
|
|
618
|
+
function cloneNode(node) {
|
|
619
|
+
return JSON.parse(JSON.stringify(node));
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// src/transformer/BlockTransformer.ts
|
|
623
|
+
var BlockTransformer = class {
|
|
624
|
+
state;
|
|
625
|
+
options;
|
|
626
|
+
rafId = null;
|
|
627
|
+
lastTickTime = 0;
|
|
628
|
+
isRunning = false;
|
|
629
|
+
isPaused = false;
|
|
630
|
+
chunks = [];
|
|
631
|
+
// 累积的 chunks(用于 fade-in 动画)
|
|
632
|
+
visibilityHandler = null;
|
|
633
|
+
constructor(options = {}) {
|
|
634
|
+
this.options = {
|
|
635
|
+
charsPerTick: options.charsPerTick ?? 1,
|
|
636
|
+
tickInterval: options.tickInterval ?? 20,
|
|
637
|
+
effect: options.effect ?? "none",
|
|
638
|
+
plugins: options.plugins ?? [],
|
|
639
|
+
onChange: options.onChange ?? (() => {
|
|
640
|
+
}),
|
|
641
|
+
pauseOnHidden: options.pauseOnHidden ?? true
|
|
642
|
+
};
|
|
643
|
+
this.state = {
|
|
644
|
+
completedBlocks: [],
|
|
645
|
+
currentBlock: null,
|
|
646
|
+
currentProgress: 0,
|
|
647
|
+
pendingBlocks: []
|
|
648
|
+
};
|
|
649
|
+
if (this.options.pauseOnHidden && typeof document !== "undefined") {
|
|
650
|
+
this.setupVisibilityHandler();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* 推入新的 blocks
|
|
655
|
+
* 会自动过滤已存在的 blocks
|
|
656
|
+
*/
|
|
657
|
+
push(blocks) {
|
|
658
|
+
const existingIds = this.getAllBlockIds();
|
|
659
|
+
const newBlocks = blocks.filter((b) => !existingIds.has(b.id));
|
|
660
|
+
if (newBlocks.length > 0) {
|
|
661
|
+
this.state.pendingBlocks.push(...newBlocks);
|
|
662
|
+
this.startIfNeeded();
|
|
663
|
+
}
|
|
664
|
+
if (this.state.currentBlock) {
|
|
665
|
+
const updated = blocks.find((b) => b.id === this.state.currentBlock.id);
|
|
666
|
+
if (updated && updated.node !== this.state.currentBlock.node) {
|
|
667
|
+
const oldTotal = this.countChars(this.state.currentBlock.node);
|
|
668
|
+
const newTotal = this.countChars(updated.node);
|
|
669
|
+
if (newTotal < oldTotal || newTotal < this.state.currentProgress) {
|
|
670
|
+
this.state.currentProgress = Math.min(this.state.currentProgress, newTotal);
|
|
671
|
+
}
|
|
672
|
+
this.state.currentBlock = updated;
|
|
673
|
+
if (!this.rafId && !this.isPaused) {
|
|
674
|
+
if (this.state.currentProgress < newTotal) {
|
|
675
|
+
this.startIfNeeded();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* 更新指定 block(用于 pending block 内容增加时)
|
|
683
|
+
*/
|
|
684
|
+
update(block) {
|
|
685
|
+
if (this.state.currentBlock?.id === block.id) {
|
|
686
|
+
const oldTotal = this.countChars(this.state.currentBlock.node);
|
|
687
|
+
const newTotal = this.countChars(block.node);
|
|
688
|
+
this.state.currentBlock = block;
|
|
689
|
+
if (newTotal > oldTotal && !this.rafId && !this.isPaused && this.state.currentProgress >= oldTotal) {
|
|
690
|
+
this.startIfNeeded();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* 跳过所有动画,直接显示全部内容
|
|
696
|
+
*/
|
|
697
|
+
skip() {
|
|
698
|
+
this.stop();
|
|
699
|
+
const allBlocks = [
|
|
700
|
+
...this.state.completedBlocks,
|
|
701
|
+
...this.state.currentBlock ? [this.state.currentBlock] : [],
|
|
702
|
+
...this.state.pendingBlocks
|
|
703
|
+
];
|
|
704
|
+
this.state = {
|
|
705
|
+
completedBlocks: allBlocks,
|
|
706
|
+
currentBlock: null,
|
|
707
|
+
currentProgress: 0,
|
|
708
|
+
pendingBlocks: []
|
|
709
|
+
};
|
|
710
|
+
this.chunks = [];
|
|
711
|
+
this.emit();
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* 重置状态
|
|
715
|
+
*/
|
|
716
|
+
reset() {
|
|
717
|
+
this.stop();
|
|
718
|
+
this.state = {
|
|
719
|
+
completedBlocks: [],
|
|
720
|
+
currentBlock: null,
|
|
721
|
+
currentProgress: 0,
|
|
722
|
+
pendingBlocks: []
|
|
723
|
+
};
|
|
724
|
+
this.chunks = [];
|
|
725
|
+
this.emit();
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* 暂停动画
|
|
729
|
+
*/
|
|
730
|
+
pause() {
|
|
731
|
+
this.isPaused = true;
|
|
732
|
+
this.cancelRaf();
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* 恢复动画
|
|
736
|
+
*/
|
|
737
|
+
resume() {
|
|
738
|
+
if (this.isPaused) {
|
|
739
|
+
this.isPaused = false;
|
|
740
|
+
this.startIfNeeded();
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* 获取用于渲染的 display blocks
|
|
745
|
+
*/
|
|
746
|
+
getDisplayBlocks() {
|
|
747
|
+
const result = [];
|
|
748
|
+
for (const block of this.state.completedBlocks) {
|
|
749
|
+
result.push({
|
|
750
|
+
...block,
|
|
751
|
+
displayNode: block.node,
|
|
752
|
+
progress: 1,
|
|
753
|
+
isDisplayComplete: true
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
if (this.state.currentBlock) {
|
|
757
|
+
const total = this.countChars(this.state.currentBlock.node);
|
|
758
|
+
const accumulatedChunks = this.options.effect === "fade-in" && this.chunks.length > 0 ? { stableChars: 0, chunks: this.chunks } : void 0;
|
|
759
|
+
const displayNode = this.sliceNode(
|
|
760
|
+
this.state.currentBlock.node,
|
|
761
|
+
this.state.currentProgress,
|
|
762
|
+
accumulatedChunks
|
|
763
|
+
);
|
|
764
|
+
result.push({
|
|
765
|
+
...this.state.currentBlock,
|
|
766
|
+
displayNode: displayNode || { type: "paragraph", children: [] },
|
|
767
|
+
progress: total > 0 ? this.state.currentProgress / total : 1,
|
|
768
|
+
isDisplayComplete: false
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
return result;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* 是否正在处理中
|
|
775
|
+
*/
|
|
776
|
+
isProcessing() {
|
|
777
|
+
return this.isRunning || this.state.currentBlock !== null || this.state.pendingBlocks.length > 0;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* 是否已暂停
|
|
781
|
+
*/
|
|
782
|
+
isPausedState() {
|
|
783
|
+
return this.isPaused;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* 获取内部状态(用于调试)
|
|
787
|
+
*/
|
|
788
|
+
getState() {
|
|
789
|
+
return { ...this.state };
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* 动态更新配置
|
|
793
|
+
*/
|
|
794
|
+
setOptions(options) {
|
|
795
|
+
if (options.charsPerTick !== void 0) {
|
|
796
|
+
this.options.charsPerTick = options.charsPerTick;
|
|
797
|
+
}
|
|
798
|
+
if (options.tickInterval !== void 0) {
|
|
799
|
+
this.options.tickInterval = options.tickInterval;
|
|
800
|
+
}
|
|
801
|
+
if (options.effect !== void 0) {
|
|
802
|
+
this.options.effect = options.effect;
|
|
803
|
+
}
|
|
804
|
+
if (options.pauseOnHidden !== void 0) {
|
|
805
|
+
this.options.pauseOnHidden = options.pauseOnHidden;
|
|
806
|
+
if (options.pauseOnHidden && typeof document !== "undefined") {
|
|
807
|
+
this.setupVisibilityHandler();
|
|
808
|
+
} else {
|
|
809
|
+
this.removeVisibilityHandler();
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* 获取当前配置
|
|
815
|
+
*/
|
|
816
|
+
getOptions() {
|
|
817
|
+
return {
|
|
818
|
+
charsPerTick: this.options.charsPerTick,
|
|
819
|
+
tickInterval: this.options.tickInterval,
|
|
820
|
+
effect: this.options.effect
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* 获取当前动画效果
|
|
825
|
+
*/
|
|
826
|
+
getEffect() {
|
|
827
|
+
return this.options.effect;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* 销毁,清理资源
|
|
831
|
+
*/
|
|
832
|
+
destroy() {
|
|
833
|
+
this.stop();
|
|
834
|
+
this.removeVisibilityHandler();
|
|
835
|
+
}
|
|
836
|
+
// ============ 私有方法 ============
|
|
837
|
+
getAllBlockIds() {
|
|
838
|
+
return new Set([
|
|
839
|
+
...this.state.completedBlocks.map((b) => b.id),
|
|
840
|
+
this.state.currentBlock?.id,
|
|
841
|
+
...this.state.pendingBlocks.map((b) => b.id)
|
|
842
|
+
].filter((id) => id !== void 0));
|
|
843
|
+
}
|
|
844
|
+
setupVisibilityHandler() {
|
|
845
|
+
if (this.visibilityHandler) return;
|
|
846
|
+
this.visibilityHandler = () => {
|
|
847
|
+
if (document.hidden) {
|
|
848
|
+
this.pause();
|
|
849
|
+
} else {
|
|
850
|
+
this.resume();
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
854
|
+
}
|
|
855
|
+
removeVisibilityHandler() {
|
|
856
|
+
if (this.visibilityHandler) {
|
|
857
|
+
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
858
|
+
this.visibilityHandler = null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
startIfNeeded() {
|
|
862
|
+
if (this.rafId || this.isPaused) return;
|
|
863
|
+
if (!this.state.currentBlock && this.state.pendingBlocks.length > 0) {
|
|
864
|
+
this.state.currentBlock = this.state.pendingBlocks.shift();
|
|
865
|
+
this.state.currentProgress = 0;
|
|
866
|
+
}
|
|
867
|
+
if (this.state.currentBlock) {
|
|
868
|
+
this.isRunning = true;
|
|
869
|
+
this.lastTickTime = 0;
|
|
870
|
+
this.scheduleNextFrame();
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
scheduleNextFrame() {
|
|
874
|
+
this.rafId = requestAnimationFrame((time) => this.animationFrame(time));
|
|
875
|
+
}
|
|
876
|
+
animationFrame(time) {
|
|
877
|
+
this.rafId = null;
|
|
878
|
+
if (this.lastTickTime === 0) {
|
|
879
|
+
this.lastTickTime = time;
|
|
880
|
+
}
|
|
881
|
+
const elapsed = time - this.lastTickTime;
|
|
882
|
+
if (elapsed >= this.options.tickInterval) {
|
|
883
|
+
this.lastTickTime = time;
|
|
884
|
+
this.tick();
|
|
885
|
+
}
|
|
886
|
+
if (this.isRunning && !this.isPaused) {
|
|
887
|
+
this.scheduleNextFrame();
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
tick() {
|
|
891
|
+
const block = this.state.currentBlock;
|
|
892
|
+
if (!block) {
|
|
893
|
+
this.processNext();
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
const total = this.countChars(block.node);
|
|
897
|
+
const step = this.getStep();
|
|
898
|
+
const prevProgress = this.state.currentProgress;
|
|
899
|
+
this.state.currentProgress = Math.min(prevProgress + step, total);
|
|
900
|
+
if (this.options.effect === "fade-in" && this.state.currentProgress > prevProgress) {
|
|
901
|
+
const newText = this.extractText(block.node, prevProgress, this.state.currentProgress);
|
|
902
|
+
if (newText.length > 0) {
|
|
903
|
+
this.chunks.push({
|
|
904
|
+
text: newText,
|
|
905
|
+
createdAt: Date.now()
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
this.emit();
|
|
910
|
+
if (this.state.currentProgress >= total) {
|
|
911
|
+
this.notifyComplete(block.node);
|
|
912
|
+
this.state.completedBlocks.push(block);
|
|
913
|
+
this.state.currentBlock = null;
|
|
914
|
+
this.state.currentProgress = 0;
|
|
915
|
+
this.chunks = [];
|
|
916
|
+
this.processNext();
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* 从 AST 节点中提取指定范围的文本
|
|
921
|
+
*/
|
|
922
|
+
extractText(node, start, end) {
|
|
923
|
+
let result = "";
|
|
924
|
+
let charIndex = 0;
|
|
925
|
+
function traverse(n) {
|
|
926
|
+
if (charIndex >= end) return false;
|
|
927
|
+
if (n.value && typeof n.value === "string") {
|
|
928
|
+
const nodeStart = charIndex;
|
|
929
|
+
const nodeEnd = charIndex + n.value.length;
|
|
930
|
+
charIndex = nodeEnd;
|
|
931
|
+
const overlapStart = Math.max(start, nodeStart);
|
|
932
|
+
const overlapEnd = Math.min(end, nodeEnd);
|
|
933
|
+
if (overlapStart < overlapEnd) {
|
|
934
|
+
result += n.value.slice(overlapStart - nodeStart, overlapEnd - nodeStart);
|
|
935
|
+
}
|
|
936
|
+
return charIndex < end;
|
|
937
|
+
}
|
|
938
|
+
if (n.children && Array.isArray(n.children)) {
|
|
939
|
+
for (const child of n.children) {
|
|
940
|
+
if (!traverse(child)) return false;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
945
|
+
traverse(node);
|
|
946
|
+
return result;
|
|
947
|
+
}
|
|
948
|
+
getStep() {
|
|
949
|
+
const { charsPerTick } = this.options;
|
|
950
|
+
if (typeof charsPerTick === "number") {
|
|
951
|
+
return charsPerTick;
|
|
952
|
+
}
|
|
953
|
+
const [min, max] = charsPerTick;
|
|
954
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
955
|
+
}
|
|
956
|
+
processNext() {
|
|
957
|
+
if (this.state.pendingBlocks.length > 0) {
|
|
958
|
+
this.state.currentBlock = this.state.pendingBlocks.shift();
|
|
959
|
+
this.state.currentProgress = 0;
|
|
960
|
+
this.chunks = [];
|
|
961
|
+
this.emit();
|
|
962
|
+
} else {
|
|
963
|
+
this.isRunning = false;
|
|
964
|
+
this.cancelRaf();
|
|
965
|
+
this.emit();
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
cancelRaf() {
|
|
969
|
+
if (this.rafId) {
|
|
970
|
+
cancelAnimationFrame(this.rafId);
|
|
971
|
+
this.rafId = null;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
stop() {
|
|
975
|
+
this.cancelRaf();
|
|
976
|
+
this.isRunning = false;
|
|
977
|
+
this.isPaused = false;
|
|
978
|
+
}
|
|
979
|
+
emit() {
|
|
980
|
+
this.options.onChange(this.getDisplayBlocks());
|
|
981
|
+
}
|
|
982
|
+
// ============ 插件调用 ============
|
|
983
|
+
countChars(node) {
|
|
984
|
+
for (const plugin of this.options.plugins) {
|
|
985
|
+
if (plugin.match?.(node) && plugin.countChars) {
|
|
986
|
+
const result = plugin.countChars(node);
|
|
987
|
+
if (result !== void 0) return result;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
return countChars(node);
|
|
991
|
+
}
|
|
992
|
+
sliceNode(node, chars, accumulatedChunks) {
|
|
993
|
+
for (const plugin of this.options.plugins) {
|
|
994
|
+
if (plugin.match?.(node) && plugin.sliceNode) {
|
|
995
|
+
const total = this.countChars(node);
|
|
996
|
+
const result = plugin.sliceNode(node, chars, total);
|
|
997
|
+
if (result !== null) return result;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return sliceAst(node, chars, accumulatedChunks);
|
|
1001
|
+
}
|
|
1002
|
+
notifyComplete(node) {
|
|
1003
|
+
for (const plugin of this.options.plugins) {
|
|
1004
|
+
if (plugin.match?.(node) && plugin.onComplete) {
|
|
1005
|
+
plugin.onComplete(node);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
function createBlockTransformer(options) {
|
|
1011
|
+
return new BlockTransformer(options);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/transformer/plugins.ts
|
|
1015
|
+
var codeBlockPlugin = {
|
|
1016
|
+
name: "code-block",
|
|
1017
|
+
match: (node) => node.type === "code",
|
|
1018
|
+
countChars: () => 1,
|
|
1019
|
+
// 算作 1 个字符,整体出现
|
|
1020
|
+
sliceNode: (node, displayedChars, totalChars) => {
|
|
1021
|
+
return displayedChars >= totalChars ? node : null;
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
var mermaidPlugin = {
|
|
1025
|
+
name: "mermaid",
|
|
1026
|
+
match: (node) => {
|
|
1027
|
+
if (node.type !== "code") return false;
|
|
1028
|
+
const codeNode = node;
|
|
1029
|
+
return codeNode.lang === "mermaid";
|
|
1030
|
+
},
|
|
1031
|
+
countChars: () => 1,
|
|
1032
|
+
sliceNode: (node, displayedChars) => displayedChars > 0 ? node : null
|
|
1033
|
+
};
|
|
1034
|
+
var imagePlugin = {
|
|
1035
|
+
name: "image",
|
|
1036
|
+
match: (node) => node.type === "image",
|
|
1037
|
+
countChars: () => 0
|
|
1038
|
+
// 0 字符,立即显示
|
|
1039
|
+
};
|
|
1040
|
+
var mathPlugin = {
|
|
1041
|
+
name: "math",
|
|
1042
|
+
match: (node) => {
|
|
1043
|
+
const type = node.type;
|
|
1044
|
+
return type === "math" || type === "inlineMath";
|
|
1045
|
+
},
|
|
1046
|
+
countChars: () => 1,
|
|
1047
|
+
sliceNode: (node, displayedChars) => displayedChars > 0 ? node : null
|
|
1048
|
+
};
|
|
1049
|
+
var thematicBreakPlugin = {
|
|
1050
|
+
name: "thematic-break",
|
|
1051
|
+
match: (node) => node.type === "thematicBreak",
|
|
1052
|
+
countChars: () => 0
|
|
1053
|
+
};
|
|
1054
|
+
var defaultPlugins = [
|
|
1055
|
+
imagePlugin,
|
|
1056
|
+
thematicBreakPlugin
|
|
1057
|
+
];
|
|
1058
|
+
var allPlugins = [
|
|
1059
|
+
mermaidPlugin,
|
|
1060
|
+
// mermaid 优先于普通 code block
|
|
1061
|
+
codeBlockPlugin,
|
|
1062
|
+
imagePlugin,
|
|
1063
|
+
mathPlugin,
|
|
1064
|
+
thematicBreakPlugin
|
|
1065
|
+
];
|
|
1066
|
+
function createPlugin(name, matcher, options = {}) {
|
|
1067
|
+
return {
|
|
1068
|
+
name,
|
|
1069
|
+
match: matcher,
|
|
1070
|
+
...options
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
export { BlockTransformer, IncremarkParser, allPlugins, calculateLineOffset, cloneNode, codeBlockPlugin, countChars, createBlockTransformer, createIncremarkParser, createInitialContext, createPlugin, defaultPlugins, detectContainer, detectContainerEnd, detectFenceEnd, detectFenceStart, generateId, imagePlugin, isBlockBoundary, isBlockquoteStart, isEmptyLine, isHeading, isHtmlBlock, isListItemStart, isTableDelimiter, isThematicBreak, joinLines, mathPlugin, mermaidPlugin, resetIdCounter, sliceAst, splitLines, thematicBreakPlugin, updateContext };
|
|
524
1075
|
//# sourceMappingURL=index.js.map
|
|
525
1076
|
//# sourceMappingURL=index.js.map
|