marktext/src/main/filesystem/markdown.js
Felix Häusler 77ff23c2c8 refactor main source code (#1006)
* refactor main source code

* fix invalid file cache entries during startup
2019-05-04 22:14:45 +08:00

100 lines
2.8 KiB
JavaScript

import fs from 'fs-extra'
import path from 'path'
import log from 'electron-log'
import { LINE_ENDING_REG, LF_LINE_ENDING_REG, CRLF_LINE_ENDING_REG } from '../config'
import { writeFile } from '../filesystem'
const getLineEnding = lineEnding => {
if (lineEnding === 'lf') {
return '\n'
} else if (lineEnding === 'crlf') {
return '\r\n'
}
// This should not happend but use fallback value.
log.error(`Invalid end of line character: expected "lf" or "crlf" but got "${lineEnding}".`)
return '\n'
}
const convertLineEndings = (text, lineEnding) => {
return text.replace(LINE_ENDING_REG, getLineEnding(lineEnding))
}
/**
* Write the content into a file.
*
* @param {string} pathname The path to the file.
* @param {string} content The buffer to save.
* @param {IMarkdownDocumentOptions} options The markdown document options
*/
export const writeMarkdownFile = (pathname, content, options) => {
const { adjustLineEndingOnSave, encoding, lineEnding } = options
const extension = path.extname(pathname) || '.md'
if (encoding === 'utf8bom') {
content = '\uFEFF' + content
}
if (adjustLineEndingOnSave) {
content = convertLineEndings(content, lineEnding)
}
// TODO(@fxha): "safeSaveDocuments" using temporary file and rename syscall.
return writeFile(pathname, content, extension)
}
/**
* Reads the contents of a markdown file.
*
* @param {string} pathname The path to the markdown file.
* @param {string} preferedEOL The prefered EOL.
* @returns {IMarkdownDocumentRaw} Returns a raw markdown document.
*/
export const loadMarkdownFile = async (pathname, preferedEOL) => {
let markdown = await fs.readFile(path.resolve(pathname), 'utf-8')
// Check UTF-8 BOM (EF BB BF) encoding
const isUtf8BomEncoded = markdown.length >= 1 && markdown.charCodeAt(0) === 0xFEFF
if (isUtf8BomEncoded) {
markdown.splice(0, 1)
}
// TODO(@fxha): Check for more file encodings and whether the file is binary but for now expect UTF-8.
const encoding = isUtf8BomEncoded ? 'utf8bom' : 'utf8'
// Detect line ending
const isLf = LF_LINE_ENDING_REG.test(markdown)
const isCrlf = CRLF_LINE_ENDING_REG.test(markdown)
const isMixedLineEndings = isLf && isCrlf
const isUnknownEnding = !isLf && !isCrlf
let lineEnding = preferedEOL
if (isLf && !isCrlf) {
lineEnding = 'lf'
} else if (isCrlf && !isLf) {
lineEnding = 'crlf'
}
let adjustLineEndingOnSave = false
if (isMixedLineEndings || isUnknownEnding || lineEnding !== 'lf') {
adjustLineEndingOnSave = lineEnding !== 'lf'
// Convert to LF for internal use.
markdown = convertLineEndings(markdown, 'lf')
}
const filename = path.basename(pathname)
return {
// document information
markdown,
filename,
pathname,
// options
encoding,
lineEnding,
adjustLineEndingOnSave,
// raw file information
isMixedLineEndings
}
}