stylelint执行插件的全过程

news2024/11/23 4:27:21

stylelint可以用来扩展插件去实现各种规则,接下来带大家看看stylelint是如何执行插件的

首先遍历absoluteFilePaths路径(该路径是我们执行lint命令配置的文件类型eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix,.{vue,ts,tsx}这个就是匹配的文件类型)。接下来执行lintSource方法。

// node_modules\stylelint\lib\standalone.js
const getStylelintResults = absoluteFilePaths.map(async (absoluteFilepath) => {
			debug(`Processing ${absoluteFilepath}`);

			try {
				const postcssResult = await lintSource(stylelint, {
					filePath: absoluteFilepath,
					cache: useCache,
				});

				...

这里首先会获取针对当前文件类型的配置文件,该文件包括本地配置的.stylelintrc.js。

// node_modules\stylelint\lib\lintSource.js
try {
		configForFile = await getConfigForFile(stylelint, configSearchPath, inputFilePath);
	} catch (err) {
		if (isCodeNotFile && isPathNotFoundError(err)) {
			configForFile = await getConfigForFile(stylelint, cwd);
		} else {
			throw err;
		}
	}

配置文件包括当前文件要执行的plugins,我们此次要分析的是stylelint-order插件
在这里插入图片描述

// node_modules\stylelint\lib\lintSource.js
// 读取要处理的文件内容
const postcssResult =
		existingPostcssResult ||
		(await getPostcssResult(stylelint, {
			code: options.code,
			codeFilename: options.codeFilename,
			filePath: inputFilePath,
			codeProcessors: config.codeProcessors,
			customSyntax: config.customSyntax,
		}));
// 调用插件处理
	await lintPostcssResult(stylelint._options, stylelintPostcssResult, config);
	// 处理完得到root,root的nodes,root包括处理好的样式和codeBefore、codeAfter
	return stylelintPostcssResult;

首先执行getPostcssResult方法获取要处理的文件内容,然后

// node_modules\stylelint\lib\getPostcssResult.js
if (options.code !== undefined) {
		getCode = options.code;
	} else if (options.filePath) {
		getCode = await fs.readFile(options.filePath, 'utf8');
	}

	if (getCode === undefined) {
		return Promise.reject(new Error('code or filePath required'));
	}

	if (options.codeProcessors && options.codeProcessors.length) {
		if (stylelint._options.fix) {
			console.warn(
				'Autofix is incompatible with processors and will be disabled. Are you sure you need a processor?',
			);
			stylelint._options.fix = false;
		}

		const sourceName = options.code ? options.codeFilename : options.filePath;

		for (const codeProcessor of options.codeProcessors) {
			getCode = codeProcessor(getCode, sourceName);
		}
	}
	// postcss-html插件处理读取的文件
	const postcssResult = await new LazyResult(postcssProcessor, getCode, postcssOptions);

此时获取syntax去解析已读取的文件内容,我们此处用的是postcss-html。该插件可以读取vue模板中的style样式。

// node_modules\postcss\lib\lazy-result.js
let parser = parse
if (opts.syntax) parser = opts.syntax.parse
 if (opts.parser) parser = opts.parser
 if (parser.parse) parser = parser.parse

 try {
   root = parser(css, opts)
 } catch (error) {
   this.processed = true
   this.error = error
 }

在这里插入图片描述

在这里插入图片描述
在lintSource.js文件中处理完毕后得到postcssResult回到standalone.js文件

// node_modules\stylelint\lib\standalone.js
if (
	postcssResult.root &&
	postcssResult.opts &&
	!postcssResult.stylelint.ignored &&
	fix &&
	!postcssResult.stylelint.disableWritingFix
) {// 将插件处理好的拼接起来
	const fixedCss = postcssResult.root.toString(postcssResult.opts.syntax);

	if (
		postcssResult.root &&
		postcssResult.root.source &&
		postcssResult.root.source.input.css !== fixedCss
	) {
		await writeFileAtomic(absoluteFilepath, fixedCss);
	}
}

此时调用postcssResult.root.toString方法拼接Root中的nodes和raws的codeBefore、codeAfter。

// node_modules\postcss-html\lib\stringify.js
if (node.nodes.length) {
		node.nodes.forEach((root) => {
			// 加上被处理样式之前
			builder(root.raws.codeBefore, root, "codeBefore");
			if (root.source.syntax) {
				// 执行builder加上已处理样式
				root.source.syntax.stringify(root, builder);
			} else {
				postcssStringify(root, builder);
			}
			// 加上被处理的样式后面
			builder(root.raws.codeAfter || "", root, "codeAfter");
		});
	} else {
		// If it do not have root, it will output the input.
		builder(node.source.input.css);
	}

此时拼接好的就是排序好的代码
在这里插入图片描述
此时回到standalone.js执行writeFileAtomic方法覆盖原文件

// node_modules\stylelint\lib\standalone.js
if (
	postcssResult.root &&
	postcssResult.root.source &&
	postcssResult.root.source.input.css !== fixedCss
) {
	await writeFileAtomic(absoluteFilepath, fixedCss);
}

在这里插入图片描述

总结

  1. stylelint会获取所有的需要lint的文件路径
  2. 根据路径的文件类型生成配置
  3. 使用node读取文件内容并调用配置的syntax解析文件
  4. 调用插件执行已解析的文件内容
  5. 拼接已处理的文件为完整字符串
  6. 重新写入文件覆盖原内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark RDD

RDD RDD 是构建 Spark 分布式内存计算引擎的基石,如 :DAG/调度系统都衍生自 RDD RDD 是对分布式数据集的抽象,囊括所有内存/磁盘的分布式数据实体 RDD/数组差异 对比项数组RDD概念数据结构实体数据模型抽象数据跨度单机进程内跨进程&…

GC简介和监控调优

GC简介: GC(Garbage Collection)是java中的垃圾回收机制,是Java与C/C的主要区别之一,在使用JAVA的时候,一般不需要专门编写内存回收和垃圾清理代 码。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。 什么…

ThreadLoca基本使用以及与synchronized的区别

文章目录1. ThreadLocal介绍1.1 官方介绍1.2 基本使用1.2.1 常用方法1.2.2 使用案例1.3 ThreadLocal类与synchronized关键字1.3.1 synchronized同步方式1.3.2 ThreadLocal与synchronized的区别2. 运用场景_事务案例2.1 转账案例2.1.1 场景构建2.1.2 引入事务2.2 常规解决方案2.…

k8s servelList(服务列表) 卡死不同步问题分析

提要容器集群版本情况:k8s 1.20客户端k8s client版本: 0.21事情是这样的,运行了一年的服务,突然有一天业务反馈服务使用异常,然后初步调查结果如下以下截图是网关异常以下截图是客户端zull(feign&#xff0…

依赖倒置DIP在系统架构中的应用

最近在对项目中的某一模块进行重构和功能的拓展。一直没想到好方法。 简单理解为: R项目 调用了 E项目的打印接口,但是E项目需要对R传来对数据传输对象DTO进行二次处理,甚至夹杂很多R项目的业务逻辑(去调用R项目的接口&#xff0…

代码规范书写说明

目录 一,命名风格 二、常量定义 三、代码格式 一,命名风格 (1)、不能够以下划线或者美元符号开始,也不能以下划线或者美元符号结束 反例:_name / __name / $name / name_ (2)、所…

春招进行时:“211文科硕士吐槽工资5500” HR:行情和能力决定价值

学历重要,还是能力重要? 春招进行时,不少学生求职遇冷,会把原因归结为学历水平不够高、毕业院校不够档次、专业不够热门、非一线城市就业机会少等等。 直到上海一位211大学的文科男硕士,吐槽招聘会提供的岗位薪资待遇…

10个实用技巧:如何让你的外贸独立站排名直线上升

在当今竞争激烈的互联网市场中,谷歌SEO已经成为了外贸独立站排名提升的必修课程。为了使得自己的网站能够在谷歌上排名更高,网站优化的工作显得尤为重要。 在这篇文章中,我们将分享10个实用技巧,帮助你的外贸独立站排名直线上升。…

【软件测试】接口测试总结

本文主要分为两个部分: 第一部分:主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两者之前的区别与联系。但该部分只交代了怎么做和如何做?并没有解释为什么要做? 第二部分&#xff1…

java虚拟机栈解读

虚拟机栈出现的背景 由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更…

【微信小程序-原生开发】实用教程11 - 用户登录鉴权(含云函数的创建、删除、使用,通过云函数获取用户的openid)

此篇可在实用教程10(见下方链接)的基础上继续开发,也可以在任何微信小程序中直接使用。 https://blog.csdn.net/weixin_41192489/article/details/128835069 用户登录鉴权逻辑 核心技术:通过云函数获取用户的openid 要想使用云函数…

网络层IP协议与数据链路层以太网协议

文章目录一、IP协议IP地址地址管理路由选择DNS二、以太网协议以太网帧MTU一、IP协议 IP协议是我们网络层的代表协议,今天我们就来一起学习一下吧,我们这里介绍的主要是IPv4协议。 版本:指定IP协议的版本,版本的取值只有4&#x…

如何使用ExchangeFinder在给定域中寻找Microsoft Exchange实例

关于ExchangeFinder ExchangeFinder是一款功能强大且使用简单的开源工具,该工具能够在给定域中尝试搜索指定的Microsoft Exchange实例,该工具的搜索机制基于Microsoft Exchange的常见DNS名称实现,并且能够识别指定的Microsoft Exchange版本&…

java基础之异常总结(自问自答版本)

1.errors和exception的区别是什么? 二者都是JAVA异常处理的重要子类,各自都包含大量子类 区别: exception:程序本身可以处理的异常,可以通过catch来进行捕获,遇到这种错误,应对其进行处理,使应用程序可以继…

大数据技术之Canal入门篇

大数据技术之Canal入门篇 文章目录大数据技术之Canal入门篇写在前面第 1 章 Canal 入门1.1 什么是 Canal1.2 MySQL 的Binlog1.2.1 什么是 Binlog1.2.2 Binlog 的分类1.3 Canal 的工作原理1.3.1 MySQL 主从复制过程1.3.2 Canal 的工作原理1.4 使用场景第 2 章 MySQL 的准备2.1 创…

作为产品经理,你都是怎样思考问题的?

作为产品经理,我们既不是产品的业务员更不是原型画师,而是伟大的创造者。用户对一个产品的评价可能只有好与坏,而作为产品工作者的我们必须有自己思考产品的视角,透过表现洞察本质。笔者根据自己有限的用户研究与产品设计的工作经…

leetcode_回溯算法

回溯算法刷题总结回溯法理论基础回溯算法的模板组合问题77.组合优化版本216.组合总和III17.电话号码的字母组合组合总和组合总和II分割131.分割回文串93.复原IP地址子集78.子集90.子集II491.递增子序列(和子集问题很像)排列全排列全排列II其他问题332.重…

RK3568平台开发系列讲解(Linux系统篇)伪文件系统目录详细介绍

🚀返回专栏总目录 文章目录 一、procfs文件系统二、sysfs文件系统沉淀、分享、成长,让自己和他人都能有所收获!😄 📢除了专门用于存储设备记录文件的文 件系统外,Linux 内核还提供了procfs、sysfs 等伪文件系统。 伪文件系统存在于内存中,通常不占用硬盘空间,它以文…

QML 键盘事件

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 和鼠标一样,键盘同样也提供了用户交互的能力,所以在介绍完《QML 鼠标事件》之后,是时候深入键盘事件了。 在 QML 中,有一个附加属性 - Keys,是专供可视元素进行按键处理的。当用户按下或释放一个按键时…

DDD:统一语言

目录一、统一语言的作用阐述二、统一语言与领域分析2.1、统一的领域术语2.2、统一的领域行为描述三、统一语言落地执行一、统一语言的作用阐述 【统一语言】,怎么强调都不为过!! 日常沟通中,时常会出现这么一幕:A同学…