UNPKG

webmat

Version:

Formats your entire project with clang-format

117 lines 4.75 kB
"use strict"; /** * @license * Copyright (c) 2018 Google Inc. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * Code distributed by Google as part of this project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ Object.defineProperty(exports, "__esModule", { value: true }); const clangFormat = require("clang-format"); const dom5 = require("dom5"); const fastGlob = require("fast-glob"); const fs = require("fs"); const parse5 = require("parse5"); const path = require("path"); const stream = require("stream"); const util_1 = require("util"); const util_2 = require("./util"); const write_output_1 = require("./write-output"); const readFile = util_1.promisify(fs.readFile); /** * Runs the files through the formatter, and overwrites them. * * @param filePaths Paths of the files to be formatted. */ async function formatFiles(filePaths, style) { const htmlFiles = filePaths.filter((file) => path.extname(file) === '.html'); const nonHtmlFiles = filePaths.filter((file) => path.extname(file) !== '.html'); const formatPromises = []; for (const path of htmlFiles) { const htmlFormatted = formatHTMLFiles(path, style).then(function (formattedContent) { return write_output_1.writeTofile(formattedContent); }); formatPromises.push(htmlFormatted); } for (const path of nonHtmlFiles) { formatInPlace(path, style); } // wait for all HTML files to be formatted as well await Promise.all(formatPromises); } exports.formatFiles = formatFiles; /** * Runs the contents of the script tags in an HTML document through the * formatter and returns their unindented, formatted contents. * * @param filePath Path of HTML file. */ async function formatHTMLFiles(filePath, style) { const scriptContent = await getInlineScriptContents(filePath); const formattedContent = { filePath: filePath, contents: [], dom: scriptContent.dom }; for (const contentChunk of scriptContent.contents) { const cfChildProcess = clangFormat.spawnClangFormat(['-assume-filename=.js', `-style=${JSON.stringify(style)}`], function () { }, ['pipe', 'pipe', process.stderr]); const cachedStdout = new util_2.ReadableStreamCache(cfChildProcess.stdout); const readable = new stream.PassThrough(); readable.pipe(cfChildProcess.stdin); readable.push(await contentChunk.streamReader.streamCached); readable.push(null); const formattedChunk = { node: contentChunk.node, streamReader: cachedStdout }; formattedContent.contents.push(formattedChunk); } return formattedContent; } /** * Runs the given file through the formatter which overwrites the file's * contents. * * @param filePath Path of file to be formatted in place. */ function formatInPlace(filePath, style) { clangFormat.spawnClangFormat([filePath, '-i', `-style=${JSON.stringify(style)}`], function () { }, ['ignore', 'pipe', process.stderr]); } /** * Gathers all the contents of an HTML file's inline scripts. * * @param filePath Path of the flile to be searched. */ async function getInlineScriptContents(filePath) { const htmlContent = await readFile(filePath, 'utf-8'); const dom = parse5.parse(htmlContent, { locationInfo: true }); const matcher = dom5.predicates.AND(dom5.predicates.hasTagName('script'), dom5.predicates.OR(dom5.predicates.NOT(dom5.predicates.hasAttr('type')), dom5.predicates.hasAttrValue('type', 'text/javascript'), dom5.predicates.hasAttrValue('type', 'application/javascript'), dom5.predicates.hasAttrValue('type', 'module'))); const scriptNodes = dom5.queryAll(dom, matcher); const contentChunks = { filePath: filePath, contents: [], dom: htmlContent }; for (const scriptNode of scriptNodes) { const content = dom5.getTextContent(scriptNode); const contentStream = new stream.PassThrough(); const cachedContentStream = new util_2.ReadableStreamCache(contentStream); contentStream.push(content); contentStream.push(null); const contentChunk = { node: scriptNode, streamReader: cachedContentStream }; contentChunks.contents.push(contentChunk); } return contentChunks; } /** * Executes the globs inside of a given format config. * * @param config Config file to be executed. */ function getFilesToFormat(config) { const filesToFormat = fastGlob.sync(config.include, { ignore: config.exclude }); return filesToFormat; } exports.getFilesToFormat = getFilesToFormat; //# sourceMappingURL=format.js.map