feat: chapter function
This commit is contained in:
145
app/utils/chapter.ts
Normal file
145
app/utils/chapter.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
|
||||
export interface ChapterItem {
|
||||
rawTitle:string
|
||||
title:string
|
||||
/**
|
||||
* the chapter content
|
||||
*/
|
||||
text:string
|
||||
/**
|
||||
* the chapter number
|
||||
*/
|
||||
number:number
|
||||
key:string
|
||||
indexOf:number
|
||||
}
|
||||
|
||||
export type Chapters = ChapterItem[]
|
||||
|
||||
function formatLines(text:string){
|
||||
const lines = text.split('\n')
|
||||
// .reduce<string[]>((result,line)=>{
|
||||
// const childLines = line.split('\r\n').map(childLine=>{
|
||||
// return childLine.split("\r")
|
||||
// })
|
||||
// return result.concat(
|
||||
// ...childLines
|
||||
// )
|
||||
// },[])
|
||||
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function splitChapter(text:string){
|
||||
const lines = formatLines(text)
|
||||
|
||||
const chapters:Chapters = []
|
||||
|
||||
/**
|
||||
* the chapters array index, not the chapter number
|
||||
* like pointer
|
||||
*/
|
||||
let chapterIndex = -1
|
||||
let offset = 0
|
||||
for(let lineIndex=0;lineIndex<lines.length;lineIndex++) {
|
||||
const lineText = lines[lineIndex]
|
||||
offset += lineText.length
|
||||
if(!lineText || !lineText.trim()) {
|
||||
continue
|
||||
}
|
||||
const title = getChapterTitle(lineText)
|
||||
if(title!==null){
|
||||
++chapterIndex;
|
||||
chapters[chapterIndex] = {
|
||||
rawTitle:lineText,
|
||||
title,
|
||||
text:"",
|
||||
number:chapterIndex+1,
|
||||
key:generateKey(),
|
||||
indexOf:Math.max(0,offset-1)
|
||||
}
|
||||
// lastLineOffset+=lineText.length
|
||||
continue
|
||||
}
|
||||
if(chapterIndex===-1) {
|
||||
chapterIndex = 0
|
||||
chapters[chapterIndex] = {
|
||||
title:"",
|
||||
rawTitle:"",
|
||||
text:lineText+"\n",
|
||||
number:1,
|
||||
key:generateKey(),
|
||||
indexOf:Math.max(0,offset)
|
||||
}
|
||||
continue
|
||||
}
|
||||
const chapter = chapters[chapterIndex]
|
||||
chapter.text += lineText
|
||||
// chapter.indexOf = lastLineOffset+lineText.length
|
||||
// lastLineOffset = chapter.indexOf
|
||||
}
|
||||
|
||||
console.info("chapters",chapters)
|
||||
return chapters
|
||||
}
|
||||
|
||||
function getChapterTitle(text:string){
|
||||
const matchTitleSpecialCharRegexp = /[^\s\da-z]/i
|
||||
// example: Chapter 1
|
||||
if(/^chapter\s*\d+/i.test(text)) {
|
||||
return text.replace(/^chapter\s*\d+/i,"").replace(matchTitleSpecialCharRegexp,"").trim()
|
||||
}
|
||||
|
||||
// example Chapter: title
|
||||
// example Chapter 2: title
|
||||
// example Chapter one: title
|
||||
// example Chapter One: "title"
|
||||
// example Chapter One: [title]
|
||||
// example Chapter III: [title]
|
||||
// example Chapter: [title]
|
||||
if(/^chapter\s*.*[^\s\da-z]([\s\da-z]+)/i.test(text)) {
|
||||
return text.replace(/^chapter\s*.*[^\s\da-z]([\s\da-z]+)/i,"$1").replace(matchTitleSpecialCharRegexp,"").trim()
|
||||
}
|
||||
|
||||
if(
|
||||
/^([-=+<>#\*])\1{2,}$/.test(text)
|
||||
) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if(/SPLIT\s*CHAPTER/.test(text)) return ""
|
||||
if(/CHAPTER\s*SPLIT/.test(text)) return ""
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function randomString(count:number) {
|
||||
const seeds = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
|
||||
return Array(count).fill("").map(()=>{
|
||||
const index = Math.floor(Math.random() * 1000) % (seeds.length)
|
||||
return seeds[index]
|
||||
}).join("")
|
||||
|
||||
}
|
||||
|
||||
const generateKey = () => randomString(20)
|
||||
|
||||
export async function readFile(file:File){
|
||||
const reader = new FileReader()
|
||||
|
||||
const promise = new Promise<string>((resolve,reject)=>{
|
||||
reader.addEventListener("loadend",function(){
|
||||
let txt = reader.result as unknown as string
|
||||
txt = txt.replace('\r\n','\n').replace('\r','\n')
|
||||
resolve(reader.result as unknown as string)
|
||||
})
|
||||
reader.addEventListener("error",reject)
|
||||
})
|
||||
|
||||
reader.readAsText(file,"utf-8")
|
||||
|
||||
return promise
|
||||
}
|
Reference in New Issue
Block a user