This commit is contained in:
bwstudio
2025-10-22 08:19:00 +08:00
parent 467b04e5b0
commit 97fbfe08d7
6040 changed files with 529099 additions and 9685 deletions
+15
View File
@@ -0,0 +1,15 @@
{
"version" : "1.0",
"configurations" : [
{
"default" : {
"launchtype" : "local"
},
"h5" : {
"launchtype" : "local"
},
"provider" : "aliyun",
"type" : "uniCloud"
}
]
}
+66
View File
@@ -0,0 +1,66 @@
<script>
import Vue from 'vue'
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
export default {
onLaunch: function() {
console.log('应用启动')
// 初始化uView配置
this.$u.config.unit = 'rpx'
},
onShow: function() {
console.log('应用显示')
},
onHide: function() {
console.log('应用隐藏')
}
}
</script>
<style lang="scss">
/*每个页面公共css */
@import "@/uni_modules/uview-ui/index.scss";
/* 全局样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 28rpx;
color: #333333;
background-color: #f5f7fa;
}
// 全局颜色变量
:root {
--primary-color: #1989fa;
--success-color: #67c23a;
--warning-color: #e6a23c;
--danger-color: #f56c6c;
--info-color: #909399;
--text-color: #303133;
--text-color-secondary: #606266;
--border-color: #dcdfe6;
--border-color-light: #e4e7ed;
--background-color: #f5f7fa;
}
// 适配安全区域
page {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
// 滚动条样式
::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
</style>
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+97 -1
View File
@@ -1,2 +1,98 @@
# FileCollect
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView 2.0</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues)
[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com)
[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases)
[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License)
## 说明
uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
## [官方文档:https://uviewui.com](https://uviewui.com)
### 官方1群:1042987248(已满)
### 官方2群:249718512(已满)
### 官方3群:1129077272(已满)
### 官方4群:1084514613(已满)
### 官方5群:863820668(已满)
### 官方6群:745721078(已满)
### 官方7群:627867855(已满)
### 官方8群:496409492(已满)
### 官方9群:828504448(已满)
### 官方10群:232041042(已满)
### 官方11群:364463526(已满)
### 官方12群:229707069(已满)
### [点击加13群交流反馈:879811455](https://jq.qq.com/?_wv=1027&k=vz4By4k5)
## 特性
- 全面兼容nvue,原生渲染,高性能
- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨
- 众多的常用页面和布局,让您专注逻辑,事半功倍
- 详尽的文档支持,现代化的演示效果
- 按需引入,精简打包体积
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
## 链接
- [官方文档](https://www.uviewui.com/)
- [更新日志](https://www.uviewui.com/components/changelog.html)
- [升级指南](https://www.uviewui.com/components/changeGuide.html)
- [关于我们](https://www.uviewui.com/cooperation/about.html)
## 交流反馈
欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html)
## 关于PR
> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。
> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢!
## 安装
#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593)
请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容
## 快速上手
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
```html
<template>
<u-button text="按钮"></u-button>
</template>
```
## 捐赠uView的研发
uView文档内容和框架源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
<img src="https://uviewui.com/common/wechat.png" width="220" >
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。
+3
View File
@@ -0,0 +1,3 @@
const { http } = uni.$u
// 获取菜单
export const fetchMenu = (params, config = {}) => http.post('/ebapi/public_api/index', params, config)
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
baseUrl: 'https://api.youzixy.com'
}
+45
View File
@@ -0,0 +1,45 @@
.u-block{
padding: 14px;
&__section{
margin-bottom:10px;
}
&__title {
margin-top:10px;
font-size: 15px;
color: $u-content-color;
margin-bottom:10px;
}
&__flex{
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
}
}
// 使用了cell组件的icon图片样式
.u-cell-icon {
width: 36rpx;
height: 36rpx;
margin-right: 8rpx;
}
.u-page {
padding: 15px 15px 40px 15px;
}
.u-demo-block {
flex: 1;
margin-bottom: 23px;
&__content {
@include flex(column);
}
&__title {
font-size: 14px;
color: rgb(143, 156, 162);
margin-bottom: 8px;
@include flex;
}
}
+7
View File
@@ -0,0 +1,7 @@
export default {
data() {
return {
}
}
}
+2
View File
@@ -0,0 +1,2 @@
uni.$u.props.gap.bgColor = '#f3f4f6'
uni.$u.props.gap.height = '10'
+25
View File
@@ -0,0 +1,25 @@
<template>
<view class="abc">
<u-button>nihao</u-button>
</view>
</template>
<script>
export default {
name:"demo-com",
options: { styleIsolation: 'shared' },
data() {
return {
};
}
}
</script>
<style lang="scss">
.abc ::v-deep .u-button {
color: red !important;
}
</style>
+113
View File
@@ -0,0 +1,113 @@
<template>
<view class="nav-wrap">
<view class="nav-title">
<u--image :showLoading="true" src="https://cdn.uviewui.com/uview/common/logo.png" width="70px"
height="70px" />
<view class="nav-info">
<view class="nav-info__title" @tap="jumpToWx">
<text class="nav-info__title__text">uView {{version}}</text>
<!-- #ifdef MP-WEIXIN -->
<!-- uni-app不支持text内部的text组件的tap事件所以放到外部响应tap -->
<text class="nav-info__title__jump">查看1.x演示</text>
<!-- #endif -->
</view>
<text class="nav-slogan">多平台快速开发的UI框架</text>
</view>
</view>
<text class="nav-desc">{{desc}}</text>
</view>
</template>
<script>
export default {
props: {
desc: String,
title: String,
},
data() {
return {
version: uni.$u.config.v
}
},
methods: {
jumpToWx() {
// #ifdef MP-WEIXIN
uni.navigateToMiniProgram({
appId: 'wx3be833c4a263e0c2'
})
// #endif
}
},
}
</script>
<style lang="scss" scoped>
.nav-wrap {
padding: 15px;
position: relative;
}
.lang {
position: absolute;
top: 15px;
right: 15px;
}
.nav-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: flex-start;
}
.nav-info {
margin-left: 15px;
&__title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
&__text {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
color: $u-main-color;
font-size: 25px;
font-weight: bold;
text-align: left;
}
&__jump {
font-size: 12px;
color: $u-primary;
font-weight: normal;
margin-left: 20px;
}
}
}
.logo {
width: 70px;
height: 70px;
/* #ifndef APP-NVUE */
height: auto;
/* #endif */
}
.nav-slogan {
color: $u-tips-color;
font-size: 14px;
}
.nav-desc {
margin-top: 10px;
font-size: 14px;
color: $u-content-color;
line-height: 20px;
}
</style>
-326
View File
@@ -1,326 +0,0 @@
# Element UI 配置指南
本文档提供了在项目中正确使用Element UI的配置步骤和最佳实践,替代之前的Tailwind CSS方案。
## Element UI 简介
Element UI 是一套基于 Vue 2.0 的桌面端组件库,提供了丰富的UI组件,可以快速构建美观、一致的用户界面。对于我们的图片收集小程序后台管理页面,Element UI提供了完善的PC端组件支持,非常适合构建企业级应用界面。
## 配置步骤
### 方法一:使用CDN引入(适合原型开发)
1. **在HTML文件头部引入Element UI**
```html
<!-- 引入Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<!-- 引入Element UI CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.15.8/lib/theme-chalk/index.css">
<!-- 引入Element UI JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/element-ui@2.15.8/lib/index.js"></script>
<!-- 引入Element UI 图标库 -->
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
```
2. **初始化Vue实例**
```html
<script>
new Vue({
el: '#app',
data: {
// 数据定义
},
methods: {
// 方法定义
}
})
</script>
```
### 方法二:使用npm安装(适合生产环境)
1. **初始化项目**
```bash
npm init -y
```
2. **安装依赖**
```bash
npm install vue@2.6.14 element-ui@2.15.8
```
3. **在项目入口文件中引入Element UI**
```javascript
// main.js
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
new Vue({
el: '#app',
render: h => h(App)
})
```
## 核心组件使用示例
### 1. 布局组件
```html
<div id="app">
<!-- 后台管理页面布局 -->
<el-container>
<!-- 侧边栏导航 -->
<el-aside width="200px">
<el-menu :default-active="activeIndex" class="el-menu-vertical">
<el-submenu index="1">
<template slot="title">
<i class="fa fa-users"></i>
<span>用户管理</span>
</template>
<el-menu-item index="1-1">用户列表</el-menu-item>
<el-menu-item index="1-2">角色权限</el-menu-item>
</el-submenu>
<el-submenu index="2">
<template slot="title">
<i class="fa fa-building"></i>
<span>部门管理</span>
</template>
<el-menu-item index="2-1">部门结构</el-menu-item>
</el-submenu>
<!-- 更多菜单项 -->
</el-menu>
</el-aside>
<el-container>
<!-- 顶部导航 -->
<el-header>
<div class="flex justify-between items-center">
<div class="text-lg font-medium">图片收集管理系统</div>
<div class="flex items-center">
<el-dropdown>
<span class="el-dropdown-link">
<i class="fa fa-bell-o"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>通知1</el-dropdown-item>
<el-dropdown-item>通知2</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class="ml-4">管理员</div>
</div>
</div>
</el-header>
<!-- 主内容区 -->
<el-main>
<!-- 页面内容 -->
</el-main>
</el-container>
</el-container>
</div>
```
### 2. 表格组件(适合数据管理页面)
```html
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 'active' ? 'success' : 'danger'">
{{ scope.row.status === 'active' ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
layout="prev, pager, next"
:total="total"
:page-size="10"
@current-change="handleCurrentChange"
></el-pagination>
```
### 3. 表单组件
```html
<el-form :model="formData" :rules="rules" ref="form">
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="描述">
<el-input type="textarea" v-model="formData.description"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="formData.status"></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">提交</el-button>
<el-button @click="resetForm('form')">重置</el-button>
</el-form-item>
</el-form>
<script>
new Vue({
el: '#app',
data: {
formData: {
name: '',
description: '',
status: true
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
]
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$message.success('提交成功!');
// 提交表单数据
} else {
this.$message.error('请检查表单信息');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
})
</script>
```
### 4. 图片上传组件
```html
<el-upload
action="#"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:before-upload="beforeUpload"
multiple
>
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>
new Vue({
el: '#app',
data: {
dialogImageUrl: '',
dialogVisible: false
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传图片只能是 JPG/PNG 格式!');
}
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}
}
})
</script>
```
## 响应式设计
Element UI 提供了响应式工具类,可以适配不同的屏幕尺寸:
```html
<div class="el-col-xs-24 el-col-sm-12 el-col-md-8 el-col-lg-6">
<!-- 在不同屏幕尺寸下有不同的宽度 -->
</div>
```
## 自定义主题
Element UI 支持自定义主题,可以通过以下方式修改:
1. **使用在线主题生成工具**
访问 Element UI 官方主题生成器,生成自定义主题包。
2. **通过SCSS变量自定义**
```scss
// 引入官方样式文件
@import "~element-ui/packages/theme-chalk/src/index";
// 修改变量
$--color-primary: #1989fa;
$--color-success: #67c23a;
$--color-warning: #e6a23c;
$--color-danger: #f56c6c;
$--color-info: #909399;
```
## 生产环境注意事项
1. **按需引入**:在生产环境中,可以使用 babel-plugin-component 实现按需引入,减小打包体积
```bash
npm install babel-plugin-component -D
```
配置 .babelrc
```json
{
"presets": ["@babel/preset-env"],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
```
2. **CDN优化**:使用稳定的CDN源,如BootCDN,提高加载速度和稳定性
3. **组件缓存**:对于频繁使用的组件,可以考虑缓存策略,提高性能
4. **按需加载路由**:结合Vue Router的路由懒加载,提高应用启动速度
+35
View File
@@ -0,0 +1,35 @@
import Vue from 'vue'
import App from './App'
// vuex
import store from './store'
// 引入全局uView
import uView from '@/uni_modules/uview-ui'
import mixin from './common/mixin'
Vue.prototype.$store = store
Vue.config.productionTip = false
App.mpType = 'app'
Vue.use(uView)
// #ifdef MP
// 引入uView对小程序分享的mixin封装
const mpShare = require('@/uni_modules/uview-ui/libs/mixin/mpShare.js')
Vue.mixin(mpShare)
// #endif
Vue.mixin(mixin)
const app = new Vue({
store,
...App
})
// 引入请求封装
require('./util/request/index')(app)
app.$mount()
+152
View File
@@ -0,0 +1,152 @@
{
"name" : "FileCollect",
"appid" : "__UNI__745B1CF",
"description" : "多平台快速开发的UI框架",
"versionName" : "2.0.37",
"versionCode" : 1,
"transformPx" : false,
"app-plus" : {
"optimization" : {
"subPackages" : true
},
"safearea" : {
"bottom" : {
"offset" : "none"
}
},
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
"usingComponents" : true,
"nvueCompiler" : "uni-app",
"compilerVersion" : 3,
"modules" : {
"Webview-x5" : {}
},
"distribute" : {
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a" ]
},
"ios" : {
"idfa" : false
},
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
"quickapp" : {},
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false,
"es6" : false,
"minified" : false,
"postcss" : false
},
"optimization" : {
"subPackages" : true
},
"usingComponents" : true,
"mergeVirtualHostAttributes" : true
},
"mp-alipay" : {
"usingComponents" : true,
"component2" : true
},
"mp-qq" : {
"optimization" : {
"subPackages" : true
},
"appid" : "15646153"
},
"mp-baidu" : {
"usingComponents" : true,
"appid" : ""
},
"mp-toutiao" : {
"usingComponents" : true,
"appid" : ""
},
"h5" : {
"template" : "template.h5.html",
"router" : {
"mode" : "history",
"base" : ""
},
"optimization" : {
"treeShaking" : {
"enable" : false
}
},
"title" : "uView UI",
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : ""
}
}
},
"domain" : ""
},
"vueVersion" : "2"
}
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../acorn/bin/acorn" "$@"
else
exec node "$basedir/../acorn/bin/acorn" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\acorn\bin\acorn" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args
} else {
& "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../acorn/bin/acorn" $args
} else {
& "node$exe" "$basedir/../acorn/bin/acorn" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../eslint/bin/eslint.js" "$@"
else
exec node "$basedir/../eslint/bin/eslint.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\eslint\bin\eslint.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../eslint/bin/eslint.js" $args
} else {
& "$basedir/node$exe" "$basedir/../eslint/bin/eslint.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../eslint/bin/eslint.js" $args
} else {
& "node$exe" "$basedir/../eslint/bin/eslint.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../js-yaml/bin/js-yaml.js" "$@"
else
exec node "$basedir/../js-yaml/bin/js-yaml.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\js-yaml\bin\js-yaml.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
} else {
& "$basedir/node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
} else {
& "node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../json5/lib/cli.js" "$@"
else
exec node "$basedir/../json5/lib/cli.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\json5\lib\cli.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../json5/lib/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../json5/lib/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../json5/lib/cli.js" $args
} else {
& "node$exe" "$basedir/../json5/lib/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../loose-envify/cli.js" "$@"
else
exec node "$basedir/../loose-envify/cli.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\loose-envify\cli.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../loose-envify/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../loose-envify/cli.js" $args
} else {
& "node$exe" "$basedir/../loose-envify/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../which/bin/node-which" "$@"
else
exec node "$basedir/../which/bin/node-which" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\node-which" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
} else {
& "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../which/bin/node-which" $args
} else {
& "node$exe" "$basedir/../which/bin/node-which" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../resolve/bin/resolve" "$@"
else
exec node "$basedir/../resolve/bin/resolve" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\resolve\bin\resolve" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args
} else {
& "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../resolve/bin/resolve" $args
} else {
& "node$exe" "$basedir/../resolve/bin/resolve" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../rimraf/bin.js" "$@"
else
exec node "$basedir/../rimraf/bin.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rimraf\bin.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../rimraf/bin.js" $args
} else {
& "$basedir/node$exe" "$basedir/../rimraf/bin.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../rimraf/bin.js" $args
} else {
& "node$exe" "$basedir/../rimraf/bin.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
else
exec node "$basedir/../semver/bin/semver.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
} else {
& "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
} else {
& "node$exe" "$basedir/../semver/bin/semver.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+3463
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Toru Nagashima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+37
View File
@@ -0,0 +1,37 @@
# @eslint-community/eslint-utils
[![npm version](https://img.shields.io/npm/v/@eslint-community/eslint-utils.svg)](https://www.npmjs.com/package/@eslint-community/eslint-utils)
[![Downloads/month](https://img.shields.io/npm/dm/@eslint-community/eslint-utils.svg)](http://www.npmtrends.com/@eslint-community/eslint-utils)
[![Build Status](https://github.com/eslint-community/eslint-utils/workflows/CI/badge.svg)](https://github.com/eslint-community/eslint-utils/actions)
[![Coverage Status](https://codecov.io/gh/eslint-community/eslint-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/eslint-community/eslint-utils)
## 🏁 Goal
This package provides utility functions and classes for make ESLint custom rules.
For examples:
- [`getStaticValue`](https://eslint-community.github.io/eslint-utils/api/ast-utils.html#getstaticvalue) evaluates static value on AST.
- [`ReferenceTracker`](https://eslint-community.github.io/eslint-utils/api/scope-utils.html#referencetracker-class) checks the members of modules/globals as handling assignments and destructuring.
## 📖 Usage
See [documentation](https://eslint-community.github.io/eslint-utils).
## 📰 Changelog
See [releases](https://github.com/eslint-community/eslint-utils/releases).
## ❤️ Contributing
Welcome contributing!
Please use GitHub's Issues/PRs.
### Development Tools
- `npm run test-coverage` runs tests and measures coverage.
- `npm run clean` removes the coverage result of `npm run test-coverage` command.
- `npm run coverage` shows the coverage result of the last `npm run test-coverage` command.
- `npm run lint` runs ESLint.
- `npm run watch` runs tests on each file change.
+217
View File
@@ -0,0 +1,217 @@
import * as eslint from 'eslint';
import { Rule, AST } from 'eslint';
import * as estree from 'estree';
declare const READ: unique symbol;
declare const CALL: unique symbol;
declare const CONSTRUCT: unique symbol;
declare const ESM: unique symbol;
declare class ReferenceTracker {
constructor(globalScope: Scope$2, options?: {
mode?: "legacy" | "strict" | undefined;
globalObjectNames?: string[] | undefined;
} | undefined);
private variableStack;
private globalScope;
private mode;
private globalObjectNames;
iterateGlobalReferences<T>(traceMap: TraceMap$2<T>): IterableIterator<TrackedReferences$2<T>>;
iterateCjsReferences<T_1>(traceMap: TraceMap$2<T_1>): IterableIterator<TrackedReferences$2<T_1>>;
iterateEsmReferences<T_2>(traceMap: TraceMap$2<T_2>): IterableIterator<TrackedReferences$2<T_2>>;
iteratePropertyReferences<T_3>(node: Expression, traceMap: TraceMap$2<T_3>): IterableIterator<TrackedReferences$2<T_3>>;
private _iterateVariableReferences;
private _iteratePropertyReferences;
private _iterateLhsReferences;
private _iterateImportReferences;
}
declare namespace ReferenceTracker {
export { READ };
export { CALL };
export { CONSTRUCT };
export { ESM };
}
type Scope$2 = eslint.Scope.Scope;
type Expression = estree.Expression;
type TraceMap$2<T> = TraceMap$1<T>;
type TrackedReferences$2<T> = TrackedReferences$1<T>;
type StaticValue$2 = StaticValueProvided$1 | StaticValueOptional$1;
type StaticValueProvided$1 = {
optional?: undefined;
value: unknown;
};
type StaticValueOptional$1 = {
optional?: true;
value: undefined;
};
type ReferenceTrackerOptions$1 = {
globalObjectNames?: string[];
mode?: "legacy" | "strict";
};
type TraceMap$1<T = unknown> = {
[i: string]: TraceMapObject<T>;
};
type TraceMapObject<T> = {
[i: string]: TraceMapObject<T>;
[CALL]?: T;
[CONSTRUCT]?: T;
[READ]?: T;
[ESM]?: boolean;
};
type TrackedReferences$1<T> = {
info: T;
node: Rule.Node;
path: string[];
type: typeof CALL | typeof CONSTRUCT | typeof READ;
};
type HasSideEffectOptions$1 = {
considerGetters?: boolean;
considerImplicitTypeConversion?: boolean;
};
type PunctuatorToken<Value extends string> = AST.Token & {
type: "Punctuator";
value: Value;
};
type ArrowToken$1 = PunctuatorToken<"=>">;
type CommaToken$1 = PunctuatorToken<",">;
type SemicolonToken$1 = PunctuatorToken<";">;
type ColonToken$1 = PunctuatorToken<":">;
type OpeningParenToken$1 = PunctuatorToken<"(">;
type ClosingParenToken$1 = PunctuatorToken<")">;
type OpeningBracketToken$1 = PunctuatorToken<"[">;
type ClosingBracketToken$1 = PunctuatorToken<"]">;
type OpeningBraceToken$1 = PunctuatorToken<"{">;
type ClosingBraceToken$1 = PunctuatorToken<"}">;
declare function findVariable(initialScope: Scope$1, nameOrNode: string | Identifier): Variable | null;
type Scope$1 = eslint.Scope.Scope;
type Variable = eslint.Scope.Variable;
type Identifier = estree.Identifier;
declare function getFunctionHeadLocation(node: FunctionNode$1, sourceCode: SourceCode$2): SourceLocation | null;
type SourceCode$2 = eslint.SourceCode;
type FunctionNode$1 = estree.Function;
type SourceLocation = estree.SourceLocation;
declare function getFunctionNameWithKind(node: FunctionNode, sourceCode?: eslint.SourceCode | undefined): string;
type FunctionNode = estree.Function;
declare function getInnermostScope(initialScope: Scope, node: Node$4): Scope;
type Scope = eslint.Scope.Scope;
type Node$4 = estree.Node;
declare function getPropertyName(node: MemberExpression | MethodDefinition | Property | PropertyDefinition, initialScope?: eslint.Scope.Scope | undefined): string | null | undefined;
type MemberExpression = estree.MemberExpression;
type MethodDefinition = estree.MethodDefinition;
type Property = estree.Property;
type PropertyDefinition = estree.PropertyDefinition;
declare function getStaticValue(node: Node$3, initialScope?: eslint.Scope.Scope | null | undefined): StaticValue$1 | null;
type StaticValue$1 = StaticValue$2;
type Node$3 = estree.Node;
declare function getStringIfConstant(node: Node$2, initialScope?: eslint.Scope.Scope | null | undefined): string | null;
type Node$2 = estree.Node;
declare function hasSideEffect(node: Node$1, sourceCode: SourceCode$1, options?: HasSideEffectOptions$1 | undefined): boolean;
type Node$1 = estree.Node;
type SourceCode$1 = eslint.SourceCode;
declare function isArrowToken(token: CommentOrToken): token is ArrowToken$1;
declare function isCommaToken(token: CommentOrToken): token is CommaToken$1;
declare function isSemicolonToken(token: CommentOrToken): token is SemicolonToken$1;
declare function isColonToken(token: CommentOrToken): token is ColonToken$1;
declare function isOpeningParenToken(token: CommentOrToken): token is OpeningParenToken$1;
declare function isClosingParenToken(token: CommentOrToken): token is ClosingParenToken$1;
declare function isOpeningBracketToken(token: CommentOrToken): token is OpeningBracketToken$1;
declare function isClosingBracketToken(token: CommentOrToken): token is ClosingBracketToken$1;
declare function isOpeningBraceToken(token: CommentOrToken): token is OpeningBraceToken$1;
declare function isClosingBraceToken(token: CommentOrToken): token is ClosingBraceToken$1;
declare function isCommentToken(token: CommentOrToken): token is estree.Comment;
declare function isNotArrowToken(arg0: CommentOrToken): boolean;
declare function isNotCommaToken(arg0: CommentOrToken): boolean;
declare function isNotSemicolonToken(arg0: CommentOrToken): boolean;
declare function isNotColonToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningParenToken(arg0: CommentOrToken): boolean;
declare function isNotClosingParenToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningBracketToken(arg0: CommentOrToken): boolean;
declare function isNotClosingBracketToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningBraceToken(arg0: CommentOrToken): boolean;
declare function isNotClosingBraceToken(arg0: CommentOrToken): boolean;
declare function isNotCommentToken(arg0: CommentOrToken): boolean;
type Token = eslint.AST.Token;
type Comment = estree.Comment;
type CommentOrToken = Comment | Token;
declare function isParenthesized(timesOrNode: Node | number, nodeOrSourceCode: Node | SourceCode, optionalSourceCode?: eslint.SourceCode | undefined): boolean;
type Node = estree.Node;
type SourceCode = eslint.SourceCode;
declare class PatternMatcher {
constructor(pattern: RegExp, options?: {
escaped?: boolean | undefined;
} | undefined);
execAll(str: string): IterableIterator<RegExpExecArray>;
test(str: string): boolean;
[Symbol.replace](str: string, replacer: string | ((...strs: string[]) => string)): string;
}
declare namespace _default {
export { CALL };
export { CONSTRUCT };
export { ESM };
export { findVariable };
export { getFunctionHeadLocation };
export { getFunctionNameWithKind };
export { getInnermostScope };
export { getPropertyName };
export { getStaticValue };
export { getStringIfConstant };
export { hasSideEffect };
export { isArrowToken };
export { isClosingBraceToken };
export { isClosingBracketToken };
export { isClosingParenToken };
export { isColonToken };
export { isCommaToken };
export { isCommentToken };
export { isNotArrowToken };
export { isNotClosingBraceToken };
export { isNotClosingBracketToken };
export { isNotClosingParenToken };
export { isNotColonToken };
export { isNotCommaToken };
export { isNotCommentToken };
export { isNotOpeningBraceToken };
export { isNotOpeningBracketToken };
export { isNotOpeningParenToken };
export { isNotSemicolonToken };
export { isOpeningBraceToken };
export { isOpeningBracketToken };
export { isOpeningParenToken };
export { isParenthesized };
export { isSemicolonToken };
export { PatternMatcher };
export { READ };
export { ReferenceTracker };
}
type StaticValue = StaticValue$2;
type StaticValueOptional = StaticValueOptional$1;
type StaticValueProvided = StaticValueProvided$1;
type ReferenceTrackerOptions = ReferenceTrackerOptions$1;
type TraceMap<T> = TraceMap$1<T>;
type TrackedReferences<T> = TrackedReferences$1<T>;
type HasSideEffectOptions = HasSideEffectOptions$1;
type ArrowToken = ArrowToken$1;
type CommaToken = CommaToken$1;
type SemicolonToken = SemicolonToken$1;
type ColonToken = ColonToken$1;
type OpeningParenToken = OpeningParenToken$1;
type ClosingParenToken = ClosingParenToken$1;
type OpeningBracketToken = OpeningBracketToken$1;
type ClosingBracketToken = ClosingBracketToken$1;
type OpeningBraceToken = OpeningBraceToken$1;
type ClosingBraceToken = ClosingBraceToken$1;
export { ArrowToken, CALL, CONSTRUCT, ClosingBraceToken, ClosingBracketToken, ClosingParenToken, ColonToken, CommaToken, ESM, HasSideEffectOptions, OpeningBraceToken, OpeningBracketToken, OpeningParenToken, PatternMatcher, READ, ReferenceTracker, ReferenceTrackerOptions, SemicolonToken, StaticValue, StaticValueOptional, StaticValueProvided, TraceMap, TrackedReferences, _default as default, findVariable, getFunctionHeadLocation, getFunctionNameWithKind, getInnermostScope, getPropertyName, getStaticValue, getStringIfConstant, hasSideEffect, isArrowToken, isClosingBraceToken, isClosingBracketToken, isClosingParenToken, isColonToken, isCommaToken, isCommentToken, isNotArrowToken, isNotClosingBraceToken, isNotClosingBracketToken, isNotClosingParenToken, isNotColonToken, isNotCommaToken, isNotCommentToken, isNotOpeningBraceToken, isNotOpeningBracketToken, isNotOpeningParenToken, isNotSemicolonToken, isOpeningBraceToken, isOpeningBracketToken, isOpeningParenToken, isParenthesized, isSemicolonToken };
+217
View File
@@ -0,0 +1,217 @@
import * as eslint from 'eslint';
import { Rule, AST } from 'eslint';
import * as estree from 'estree';
declare const READ: unique symbol;
declare const CALL: unique symbol;
declare const CONSTRUCT: unique symbol;
declare const ESM: unique symbol;
declare class ReferenceTracker {
constructor(globalScope: Scope$2, options?: {
mode?: "legacy" | "strict" | undefined;
globalObjectNames?: string[] | undefined;
} | undefined);
private variableStack;
private globalScope;
private mode;
private globalObjectNames;
iterateGlobalReferences<T>(traceMap: TraceMap$2<T>): IterableIterator<TrackedReferences$2<T>>;
iterateCjsReferences<T_1>(traceMap: TraceMap$2<T_1>): IterableIterator<TrackedReferences$2<T_1>>;
iterateEsmReferences<T_2>(traceMap: TraceMap$2<T_2>): IterableIterator<TrackedReferences$2<T_2>>;
iteratePropertyReferences<T_3>(node: Expression, traceMap: TraceMap$2<T_3>): IterableIterator<TrackedReferences$2<T_3>>;
private _iterateVariableReferences;
private _iteratePropertyReferences;
private _iterateLhsReferences;
private _iterateImportReferences;
}
declare namespace ReferenceTracker {
export { READ };
export { CALL };
export { CONSTRUCT };
export { ESM };
}
type Scope$2 = eslint.Scope.Scope;
type Expression = estree.Expression;
type TraceMap$2<T> = TraceMap$1<T>;
type TrackedReferences$2<T> = TrackedReferences$1<T>;
type StaticValue$2 = StaticValueProvided$1 | StaticValueOptional$1;
type StaticValueProvided$1 = {
optional?: undefined;
value: unknown;
};
type StaticValueOptional$1 = {
optional?: true;
value: undefined;
};
type ReferenceTrackerOptions$1 = {
globalObjectNames?: string[];
mode?: "legacy" | "strict";
};
type TraceMap$1<T = unknown> = {
[i: string]: TraceMapObject<T>;
};
type TraceMapObject<T> = {
[i: string]: TraceMapObject<T>;
[CALL]?: T;
[CONSTRUCT]?: T;
[READ]?: T;
[ESM]?: boolean;
};
type TrackedReferences$1<T> = {
info: T;
node: Rule.Node;
path: string[];
type: typeof CALL | typeof CONSTRUCT | typeof READ;
};
type HasSideEffectOptions$1 = {
considerGetters?: boolean;
considerImplicitTypeConversion?: boolean;
};
type PunctuatorToken<Value extends string> = AST.Token & {
type: "Punctuator";
value: Value;
};
type ArrowToken$1 = PunctuatorToken<"=>">;
type CommaToken$1 = PunctuatorToken<",">;
type SemicolonToken$1 = PunctuatorToken<";">;
type ColonToken$1 = PunctuatorToken<":">;
type OpeningParenToken$1 = PunctuatorToken<"(">;
type ClosingParenToken$1 = PunctuatorToken<")">;
type OpeningBracketToken$1 = PunctuatorToken<"[">;
type ClosingBracketToken$1 = PunctuatorToken<"]">;
type OpeningBraceToken$1 = PunctuatorToken<"{">;
type ClosingBraceToken$1 = PunctuatorToken<"}">;
declare function findVariable(initialScope: Scope$1, nameOrNode: string | Identifier): Variable | null;
type Scope$1 = eslint.Scope.Scope;
type Variable = eslint.Scope.Variable;
type Identifier = estree.Identifier;
declare function getFunctionHeadLocation(node: FunctionNode$1, sourceCode: SourceCode$2): SourceLocation | null;
type SourceCode$2 = eslint.SourceCode;
type FunctionNode$1 = estree.Function;
type SourceLocation = estree.SourceLocation;
declare function getFunctionNameWithKind(node: FunctionNode, sourceCode?: eslint.SourceCode | undefined): string;
type FunctionNode = estree.Function;
declare function getInnermostScope(initialScope: Scope, node: Node$4): Scope;
type Scope = eslint.Scope.Scope;
type Node$4 = estree.Node;
declare function getPropertyName(node: MemberExpression | MethodDefinition | Property | PropertyDefinition, initialScope?: eslint.Scope.Scope | undefined): string | null | undefined;
type MemberExpression = estree.MemberExpression;
type MethodDefinition = estree.MethodDefinition;
type Property = estree.Property;
type PropertyDefinition = estree.PropertyDefinition;
declare function getStaticValue(node: Node$3, initialScope?: eslint.Scope.Scope | null | undefined): StaticValue$1 | null;
type StaticValue$1 = StaticValue$2;
type Node$3 = estree.Node;
declare function getStringIfConstant(node: Node$2, initialScope?: eslint.Scope.Scope | null | undefined): string | null;
type Node$2 = estree.Node;
declare function hasSideEffect(node: Node$1, sourceCode: SourceCode$1, options?: HasSideEffectOptions$1 | undefined): boolean;
type Node$1 = estree.Node;
type SourceCode$1 = eslint.SourceCode;
declare function isArrowToken(token: CommentOrToken): token is ArrowToken$1;
declare function isCommaToken(token: CommentOrToken): token is CommaToken$1;
declare function isSemicolonToken(token: CommentOrToken): token is SemicolonToken$1;
declare function isColonToken(token: CommentOrToken): token is ColonToken$1;
declare function isOpeningParenToken(token: CommentOrToken): token is OpeningParenToken$1;
declare function isClosingParenToken(token: CommentOrToken): token is ClosingParenToken$1;
declare function isOpeningBracketToken(token: CommentOrToken): token is OpeningBracketToken$1;
declare function isClosingBracketToken(token: CommentOrToken): token is ClosingBracketToken$1;
declare function isOpeningBraceToken(token: CommentOrToken): token is OpeningBraceToken$1;
declare function isClosingBraceToken(token: CommentOrToken): token is ClosingBraceToken$1;
declare function isCommentToken(token: CommentOrToken): token is estree.Comment;
declare function isNotArrowToken(arg0: CommentOrToken): boolean;
declare function isNotCommaToken(arg0: CommentOrToken): boolean;
declare function isNotSemicolonToken(arg0: CommentOrToken): boolean;
declare function isNotColonToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningParenToken(arg0: CommentOrToken): boolean;
declare function isNotClosingParenToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningBracketToken(arg0: CommentOrToken): boolean;
declare function isNotClosingBracketToken(arg0: CommentOrToken): boolean;
declare function isNotOpeningBraceToken(arg0: CommentOrToken): boolean;
declare function isNotClosingBraceToken(arg0: CommentOrToken): boolean;
declare function isNotCommentToken(arg0: CommentOrToken): boolean;
type Token = eslint.AST.Token;
type Comment = estree.Comment;
type CommentOrToken = Comment | Token;
declare function isParenthesized(timesOrNode: Node | number, nodeOrSourceCode: Node | SourceCode, optionalSourceCode?: eslint.SourceCode | undefined): boolean;
type Node = estree.Node;
type SourceCode = eslint.SourceCode;
declare class PatternMatcher {
constructor(pattern: RegExp, options?: {
escaped?: boolean | undefined;
} | undefined);
execAll(str: string): IterableIterator<RegExpExecArray>;
test(str: string): boolean;
[Symbol.replace](str: string, replacer: string | ((...strs: string[]) => string)): string;
}
declare namespace _default {
export { CALL };
export { CONSTRUCT };
export { ESM };
export { findVariable };
export { getFunctionHeadLocation };
export { getFunctionNameWithKind };
export { getInnermostScope };
export { getPropertyName };
export { getStaticValue };
export { getStringIfConstant };
export { hasSideEffect };
export { isArrowToken };
export { isClosingBraceToken };
export { isClosingBracketToken };
export { isClosingParenToken };
export { isColonToken };
export { isCommaToken };
export { isCommentToken };
export { isNotArrowToken };
export { isNotClosingBraceToken };
export { isNotClosingBracketToken };
export { isNotClosingParenToken };
export { isNotColonToken };
export { isNotCommaToken };
export { isNotCommentToken };
export { isNotOpeningBraceToken };
export { isNotOpeningBracketToken };
export { isNotOpeningParenToken };
export { isNotSemicolonToken };
export { isOpeningBraceToken };
export { isOpeningBracketToken };
export { isOpeningParenToken };
export { isParenthesized };
export { isSemicolonToken };
export { PatternMatcher };
export { READ };
export { ReferenceTracker };
}
type StaticValue = StaticValue$2;
type StaticValueOptional = StaticValueOptional$1;
type StaticValueProvided = StaticValueProvided$1;
type ReferenceTrackerOptions = ReferenceTrackerOptions$1;
type TraceMap<T> = TraceMap$1<T>;
type TrackedReferences<T> = TrackedReferences$1<T>;
type HasSideEffectOptions = HasSideEffectOptions$1;
type ArrowToken = ArrowToken$1;
type CommaToken = CommaToken$1;
type SemicolonToken = SemicolonToken$1;
type ColonToken = ColonToken$1;
type OpeningParenToken = OpeningParenToken$1;
type ClosingParenToken = ClosingParenToken$1;
type OpeningBracketToken = OpeningBracketToken$1;
type ClosingBracketToken = ClosingBracketToken$1;
type OpeningBraceToken = OpeningBraceToken$1;
type ClosingBraceToken = ClosingBraceToken$1;
export { ArrowToken, CALL, CONSTRUCT, ClosingBraceToken, ClosingBracketToken, ClosingParenToken, ColonToken, CommaToken, ESM, HasSideEffectOptions, OpeningBraceToken, OpeningBracketToken, OpeningParenToken, PatternMatcher, READ, ReferenceTracker, ReferenceTrackerOptions, SemicolonToken, StaticValue, StaticValueOptional, StaticValueProvided, TraceMap, TrackedReferences, _default as default, findVariable, getFunctionHeadLocation, getFunctionNameWithKind, getInnermostScope, getPropertyName, getStaticValue, getStringIfConstant, hasSideEffect, isArrowToken, isClosingBraceToken, isClosingBracketToken, isClosingParenToken, isColonToken, isCommaToken, isCommentToken, isNotArrowToken, isNotClosingBraceToken, isNotClosingBracketToken, isNotClosingParenToken, isNotColonToken, isNotCommaToken, isNotCommentToken, isNotOpeningBraceToken, isNotOpeningBracketToken, isNotOpeningParenToken, isNotSemicolonToken, isOpeningBraceToken, isOpeningBracketToken, isOpeningParenToken, isParenthesized, isSemicolonToken };
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+89
View File
@@ -0,0 +1,89 @@
{
"name": "@eslint-community/eslint-utils",
"version": "4.9.0",
"description": "Utilities for ESLint plugins.",
"keywords": [
"eslint"
],
"homepage": "https://github.com/eslint-community/eslint-utils#readme",
"bugs": {
"url": "https://github.com/eslint-community/eslint-utils/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint-community/eslint-utils"
},
"license": "MIT",
"author": "Toru Nagashima",
"sideEffects": false,
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js"
},
"./package.json": "./package.json"
},
"main": "index",
"module": "index.mjs",
"files": [
"index.*"
],
"scripts": {
"prebuild": "npm run -s clean",
"build": "npm run build:dts && npm run build:rollup",
"build:dts": "tsc -p tsconfig.build.json",
"build:rollup": "rollup -c",
"clean": "rimraf .nyc_output coverage index.* dist",
"coverage": "opener ./coverage/lcov-report/index.html",
"docs:build": "vitepress build docs",
"docs:watch": "vitepress dev docs",
"format": "npm run -s format:prettier -- --write",
"format:prettier": "prettier .",
"format:check": "npm run -s format:prettier -- --check",
"lint:eslint": "eslint .",
"lint:format": "npm run -s format:check",
"lint:installed-check": "installed-check -v -i installed-check -i npm-run-all2 -i knip -i rollup-plugin-dts",
"lint:knip": "knip",
"lint": "run-p lint:*",
"test-coverage": "c8 mocha --reporter dot \"test/*.mjs\"",
"test": "mocha --reporter dot \"test/*.mjs\"",
"preversion": "npm run test-coverage && npm run -s build",
"postversion": "git push && git push --tags",
"prewatch": "npm run -s clean",
"watch": "warun \"{src,test}/**/*.mjs\" -- npm run -s test:mocha"
},
"dependencies": {
"eslint-visitor-keys": "^3.4.3"
},
"devDependencies": {
"@eslint-community/eslint-plugin-mysticatea": "^15.6.1",
"@types/eslint": "^9.6.1",
"@types/estree": "^1.0.7",
"@typescript-eslint/parser": "^5.62.0",
"@typescript-eslint/types": "^5.62.0",
"c8": "^8.0.1",
"dot-prop": "^7.2.0",
"eslint": "^8.57.1",
"installed-check": "^8.0.1",
"knip": "^5.33.3",
"mocha": "^9.2.2",
"npm-run-all2": "^6.2.3",
"opener": "^1.5.2",
"prettier": "2.8.8",
"rimraf": "^3.0.2",
"rollup": "^2.79.2",
"rollup-plugin-dts": "^4.2.3",
"rollup-plugin-sourcemaps": "^0.6.3",
"semver": "^7.6.3",
"typescript": "^4.9.5",
"vitepress": "^1.4.1",
"warun": "^1.0.0"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": "https://opencollective.com/eslint"
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Toru Nagashima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+177
View File
@@ -0,0 +1,177 @@
# @eslint-community/regexpp
[![npm version](https://img.shields.io/npm/v/@eslint-community/regexpp.svg)](https://www.npmjs.com/package/@eslint-community/regexpp)
[![Downloads/month](https://img.shields.io/npm/dm/@eslint-community/regexpp.svg)](http://www.npmtrends.com/@eslint-community/regexpp)
[![Build Status](https://github.com/eslint-community/regexpp/workflows/CI/badge.svg)](https://github.com/eslint-community/regexpp/actions)
[![codecov](https://codecov.io/gh/eslint-community/regexpp/branch/main/graph/badge.svg)](https://codecov.io/gh/eslint-community/regexpp)
A regular expression parser for ECMAScript.
## 💿 Installation
```bash
$ npm install @eslint-community/regexpp
```
- require Node@^12.0.0 || ^14.0.0 || >=16.0.0.
## 📖 Usage
```ts
import {
AST,
RegExpParser,
RegExpValidator,
RegExpVisitor,
parseRegExpLiteral,
validateRegExpLiteral,
visitRegExpAST
} from "@eslint-community/regexpp"
```
### parseRegExpLiteral(source, options?)
Parse a given regular expression literal then make AST object.
This is equivalent to `new RegExpParser(options).parseLiteral(source)`.
- **Parameters:**
- `source` (`string | RegExp`) The source code to parse.
- `options?` ([`RegExpParser.Options`]) The options to parse.
- **Return:**
- The AST of the regular expression.
### validateRegExpLiteral(source, options?)
Validate a given regular expression literal.
This is equivalent to `new RegExpValidator(options).validateLiteral(source)`.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `options?` ([`RegExpValidator.Options`]) The options to validate.
### visitRegExpAST(ast, handlers)
Visit each node of a given AST.
This is equivalent to `new RegExpVisitor(handlers).visit(ast)`.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
### RegExpParser
#### new RegExpParser(options?)
- **Parameters:**
- `options?` ([`RegExpParser.Options`]) The options to parse.
#### parser.parseLiteral(source, start?, end?)
Parse a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"/abc/g"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression.
#### parser.parsePattern(source, start?, end?, flags?)
Parse a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"abc"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
- **Return:**
- The AST of the regular expression pattern.
#### parser.parseFlags(source, start?, end?)
Parse a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"gim"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression flags.
### RegExpValidator
#### new RegExpValidator(options)
- **Parameters:**
- `options` ([`RegExpValidator.Options`]) The options to validate.
#### validator.validateLiteral(source, start, end)
Validate a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
#### validator.validatePattern(source, start, end, flags)
Validate a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
#### validator.validateFlags(source, start, end)
Validate a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
### RegExpVisitor
#### new RegExpVisitor(handlers)
- **Parameters:**
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
#### visitor.visit(ast)
Validate a regular expression literal.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
## 📰 Changelog
- [GitHub Releases](https://github.com/eslint-community/regexpp/releases)
## 🍻 Contributing
Welcome contributing!
Please use GitHub's Issues/PRs.
### Development Tools
- `npm test` runs tests and measures coverage.
- `npm run build` compiles TypeScript source code to `index.js`, `index.js.map`, and `index.d.ts`.
- `npm run clean` removes the temporary files which are created by `npm test` and `npm run build`.
- `npm run lint` runs ESLint.
- `npm run update:test` updates test fixtures.
- `npm run update:ids` updates `src/unicode/ids.ts`.
- `npm run watch` runs tests with `--watch` option.
[`AST.Node`]: src/ast.ts#L4
[`RegExpParser.Options`]: src/parser.ts#L743
[`RegExpValidator.Options`]: src/validator.ts#L220
[`RegExpVisitor.Handlers`]: src/visitor.ts#L291
+1163
View File
File diff suppressed because it is too large Load Diff
+3037
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+3027
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+91
View File
@@ -0,0 +1,91 @@
{
"name": "@eslint-community/regexpp",
"version": "4.12.1",
"description": "Regular expression parser for ECMAScript.",
"keywords": [
"regexp",
"regular",
"expression",
"parser",
"validator",
"ast",
"abstract",
"syntax",
"tree",
"ecmascript",
"es2015",
"es2016",
"es2017",
"es2018",
"es2019",
"es2020",
"es2021",
"annexB"
],
"homepage": "https://github.com/eslint-community/regexpp#readme",
"bugs": {
"url": "https://github.com/eslint-community/regexpp/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint-community/regexpp"
},
"license": "MIT",
"author": "Toru Nagashima",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.mjs",
"default": "./index.js"
},
"./package.json": "./package.json"
},
"main": "index",
"files": [
"index.*"
],
"scripts": {
"prebuild": "npm run -s clean",
"build": "run-s build:*",
"build:tsc": "tsc --module es2015",
"build:rollup": "rollup -c",
"build:dts": "npm run -s build:tsc -- --removeComments false && dts-bundle --name @eslint-community/regexpp --main .temp/index.d.ts --out ../index.d.ts && prettier --write index.d.ts",
"clean": "rimraf .temp index.*",
"lint": "eslint . --ext .ts",
"test": "nyc _mocha \"test/*.ts\" --reporter dot --timeout 10000",
"debug": "mocha --require ts-node/register/transpile-only \"test/*.ts\" --reporter dot --timeout 10000",
"update:test": "ts-node scripts/update-fixtures.ts",
"update:unicode": "run-s update:unicode:*",
"update:unicode:ids": "ts-node scripts/update-unicode-ids.ts",
"update:unicode:props": "ts-node scripts/update-unicode-properties.ts",
"update:test262:extract": "ts-node -T scripts/extract-test262.ts",
"preversion": "npm test && npm run -s build",
"postversion": "git push && git push --tags",
"prewatch": "npm run -s clean",
"watch": "_mocha \"test/*.ts\" --require ts-node/register --reporter dot --timeout 10000 --watch-extensions ts --watch --growl"
},
"dependencies": {},
"devDependencies": {
"@eslint-community/eslint-plugin-mysticatea": "^15.5.1",
"@rollup/plugin-node-resolve": "^14.1.0",
"@types/eslint": "^8.44.3",
"@types/jsdom": "^16.2.15",
"@types/mocha": "^9.1.1",
"@types/node": "^12.20.55",
"dts-bundle": "^0.7.3",
"eslint": "^8.50.0",
"js-tokens": "^8.0.2",
"jsdom": "^19.0.0",
"mocha": "^9.2.2",
"npm-run-all2": "^6.2.2",
"nyc": "^14.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.79.1",
"rollup-plugin-sourcemaps": "^0.6.3",
"ts-node": "^10.9.1",
"typescript": "~5.0.2"
},
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
}
+19
View File
@@ -0,0 +1,19 @@
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+115
View File
@@ -0,0 +1,115 @@
# ESLintRC Library
This repository contains the legacy ESLintRC configuration file format for ESLint. This package is not intended for use outside of the ESLint ecosystem. It is ESLint-specific and not intended for use in other programs.
**Note:** This package is frozen except for critical bug fixes as ESLint moves to a new config system.
## Installation
You can install the package as follows:
```
npm install @eslint/eslintrc --save-dev
# or
yarn add @eslint/eslintrc -D
```
## Usage (ESM)
The primary class in this package is `FlatCompat`, which is a utility to translate ESLintRC-style configs into flat configs. Here's how you use it inside of your `eslint.config.js` file:
```js
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import path from "path";
import { fileURLToPath } from "url";
// mimic CommonJS variables -- not needed if using CommonJS
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname, // optional; default: process.cwd()
resolvePluginsRelativeTo: __dirname, // optional
recommendedConfig: js.configs.recommended, // optional
allConfig: js.configs.all, // optional
});
export default [
// mimic ESLintRC-style extends
...compat.extends("standard", "example"),
// mimic environments
...compat.env({
es2020: true,
node: true
}),
// mimic plugins
...compat.plugins("airbnb", "react"),
// translate an entire config
...compat.config({
plugins: ["airbnb", "react"],
extends: "standard",
env: {
es2020: true,
node: true
},
rules: {
semi: "error"
}
})
];
```
## Usage (CommonJS)
Using `FlatCompat` in CommonJS files is similar to ESM, but you'll use `require()` and `module.exports` instead of `import` and `export`. Here's how you use it inside of your `eslint.config.js` CommonJS file:
```js
const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname, // optional; default: process.cwd()
resolvePluginsRelativeTo: __dirname, // optional
recommendedConfig: js.configs.recommended, // optional
allConfig: js.configs.all, // optional
});
module.exports = [
// mimic ESLintRC-style extends
...compat.extends("standard", "example"),
// mimic environments
...compat.env({
es2020: true,
node: true
}),
// mimic plugins
...compat.plugins("airbnb", "react"),
// translate an entire config
...compat.config({
plugins: ["airbnb", "react"],
extends: "standard",
env: {
es2020: true,
node: true
},
rules: {
semi: "error"
}
})
];
```
## License
MIT License
+79
View File
@@ -0,0 +1,79 @@
/**
* @fileoverview Defines a schema for configs.
* @author Sylvan Mably
*/
const baseConfigProperties = {
$schema: { type: "string" },
env: { type: "object" },
extends: { $ref: "#/definitions/stringOrStrings" },
globals: { type: "object" },
overrides: {
type: "array",
items: { $ref: "#/definitions/overrideConfig" },
additionalItems: false
},
parser: { type: ["string", "null"] },
parserOptions: { type: "object" },
plugins: { type: "array" },
processor: { type: "string" },
rules: { type: "object" },
settings: { type: "object" },
noInlineConfig: { type: "boolean" },
reportUnusedDisableDirectives: { type: "boolean" },
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
};
const configSchema = {
definitions: {
stringOrStrings: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" },
additionalItems: false
}
]
},
stringOrStringsRequired: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" },
additionalItems: false,
minItems: 1
}
]
},
// Config at top-level.
objectConfig: {
type: "object",
properties: {
root: { type: "boolean" },
ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
...baseConfigProperties
},
additionalProperties: false
},
// Config in `overrides`.
overrideConfig: {
type: "object",
properties: {
excludedFiles: { $ref: "#/definitions/stringOrStrings" },
files: { $ref: "#/definitions/stringOrStringsRequired" },
...baseConfigProperties
},
required: ["files"],
additionalProperties: false
}
},
$ref: "#/definitions/objectConfig"
};
export default configSchema;
+215
View File
@@ -0,0 +1,215 @@
/**
* @fileoverview Defines environment settings and globals.
* @author Elan Shanker
*/
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
import globals from "globals";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Get the object that has difference.
* @param {Record<string,boolean>} current The newer object.
* @param {Record<string,boolean>} prev The older object.
* @returns {Record<string,boolean>} The difference object.
*/
function getDiff(current, prev) {
const retv = {};
for (const [key, value] of Object.entries(current)) {
if (!Object.hasOwnProperty.call(prev, key)) {
retv[key] = value;
}
}
return retv;
}
const newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...
const newGlobals2017 = {
Atomics: false,
SharedArrayBuffer: false
};
const newGlobals2020 = {
BigInt: false,
BigInt64Array: false,
BigUint64Array: false,
globalThis: false
};
const newGlobals2021 = {
AggregateError: false,
FinalizationRegistry: false,
WeakRef: false
};
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/** @type {Map<string, import("../lib/shared/types").Environment>} */
export default new Map(Object.entries({
// Language
builtin: {
globals: globals.es5
},
es6: {
globals: newGlobals2015,
parserOptions: {
ecmaVersion: 6
}
},
es2015: {
globals: newGlobals2015,
parserOptions: {
ecmaVersion: 6
}
},
es2016: {
globals: newGlobals2015,
parserOptions: {
ecmaVersion: 7
}
},
es2017: {
globals: { ...newGlobals2015, ...newGlobals2017 },
parserOptions: {
ecmaVersion: 8
}
},
es2018: {
globals: { ...newGlobals2015, ...newGlobals2017 },
parserOptions: {
ecmaVersion: 9
}
},
es2019: {
globals: { ...newGlobals2015, ...newGlobals2017 },
parserOptions: {
ecmaVersion: 10
}
},
es2020: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
parserOptions: {
ecmaVersion: 11
}
},
es2021: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
parserOptions: {
ecmaVersion: 12
}
},
es2022: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
parserOptions: {
ecmaVersion: 13
}
},
es2023: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
parserOptions: {
ecmaVersion: 14
}
},
es2024: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
parserOptions: {
ecmaVersion: 15
}
},
// Platforms
browser: {
globals: globals.browser
},
node: {
globals: globals.node,
parserOptions: {
ecmaFeatures: {
globalReturn: true
}
}
},
"shared-node-browser": {
globals: globals["shared-node-browser"]
},
worker: {
globals: globals.worker
},
serviceworker: {
globals: globals.serviceworker
},
// Frameworks
commonjs: {
globals: globals.commonjs,
parserOptions: {
ecmaFeatures: {
globalReturn: true
}
}
},
amd: {
globals: globals.amd
},
mocha: {
globals: globals.mocha
},
jasmine: {
globals: globals.jasmine
},
jest: {
globals: globals.jest
},
phantomjs: {
globals: globals.phantomjs
},
jquery: {
globals: globals.jquery
},
qunit: {
globals: globals.qunit
},
prototypejs: {
globals: globals.prototypejs
},
shelljs: {
globals: globals.shelljs
},
meteor: {
globals: globals.meteor
},
mongo: {
globals: globals.mongo
},
protractor: {
globals: globals.protractor
},
applescript: {
globals: globals.applescript
},
nashorn: {
globals: globals.nashorn
},
atomtest: {
globals: globals.atomtest
},
embertest: {
globals: globals.embertest
},
webextensions: {
globals: globals.webextensions
},
greasemonkey: {
globals: globals.greasemonkey
}
}));
+82
View File
@@ -0,0 +1,82 @@
{
"name": "@eslint/eslintrc",
"version": "2.1.4",
"description": "The legacy ESLintRC config file format for ESLint",
"type": "module",
"main": "./dist/eslintrc.cjs",
"exports": {
".": {
"import": "./lib/index.js",
"require": "./dist/eslintrc.cjs"
},
"./package.json": "./package.json",
"./universal": {
"import": "./lib/index-universal.js",
"require": "./dist/eslintrc-universal.cjs"
}
},
"files": [
"lib",
"conf",
"LICENSE",
"dist",
"universal.js"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "rollup -c",
"lint": "eslint . --report-unused-disable-directives",
"lint:fix": "npm run lint -- --fix",
"prepare": "npm run build",
"release:generate:latest": "eslint-generate-release",
"release:generate:alpha": "eslint-generate-prerelease alpha",
"release:generate:beta": "eslint-generate-prerelease beta",
"release:generate:rc": "eslint-generate-prerelease rc",
"release:publish": "eslint-publish-release",
"test": "mocha -R progress -c 'tests/lib/*.cjs' && c8 mocha -R progress -c 'tests/lib/**/*.js'"
},
"repository": "eslint/eslintrc",
"funding": "https://opencollective.com/eslint",
"keywords": [
"ESLint",
"ESLintRC",
"Configuration"
],
"author": "Nicholas C. Zakas",
"license": "MIT",
"bugs": {
"url": "https://github.com/eslint/eslintrc/issues"
},
"homepage": "https://github.com/eslint/eslintrc#readme",
"devDependencies": {
"c8": "^7.7.3",
"chai": "^4.3.4",
"eslint": "^7.31.0",
"eslint-config-eslint": "^7.0.0",
"eslint-plugin-jsdoc": "^35.4.1",
"eslint-plugin-node": "^11.1.0",
"eslint-release": "^3.2.0",
"fs-teardown": "^0.1.3",
"mocha": "^9.0.3",
"rollup": "^2.70.1",
"shelljs": "^0.8.4",
"sinon": "^11.1.2",
"temp-dir": "^2.0.0"
},
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
"espree": "^9.6.0",
"globals": "^13.19.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
"minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
}
+9
View File
@@ -0,0 +1,9 @@
// Jest (and probably some other runtimes with custom implementations of
// `require`) doesn't support `exports` in `package.json`, so this file is here
// to help them load this module. Note that it is also `.js` and not `.cjs` for
// the same reason - `cjs` files requires to be loaded with an extension, but
// since Jest doesn't respect `module` outside of ESM mode it still works in
// this case (and the `require` in _this_ file does specify the extension).
// eslint-disable-next-line no-undef
module.exports = require("./dist/eslintrc-universal.cjs");
+19
View File
@@ -0,0 +1,19 @@
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+57
View File
@@ -0,0 +1,57 @@
[![npm version](https://img.shields.io/npm/v/@eslint/js.svg)](https://www.npmjs.com/package/@eslint/js)
# ESLint JavaScript Plugin
[Website](https://eslint.org) | [Configure ESLint](https://eslint.org/docs/latest/use/configure) | [Rules](https://eslint.org/docs/rules/) | [Contributing](https://eslint.org/docs/latest/contribute) | [Twitter](https://twitter.com/geteslint) | [Chatroom](https://eslint.org/chat)
The beginnings of separating out JavaScript-specific functionality from ESLint.
Right now, this plugin contains two configurations:
* `recommended` - enables the rules recommended by the ESLint team (the replacement for `"eslint:recommended"`)
* `all` - enables all ESLint rules (the replacement for `"eslint:all"`)
## Installation
```shell
npm install @eslint/js -D
```
## Usage
Use in your `eslint.config.js` file anytime you want to extend one of the configs:
```js
import js from "@eslint/js";
export default [
// apply recommended rules to JS files
{
files: ["**/*.js"],
rules: js.configs.recommended.rules
},
// apply recommended rules to JS files with an override
{
files: ["**/*.js"],
rules: {
...js.configs.recommended.rules,
"no-unused-vars": "warn"
}
},
// apply all rules to JS files
{
files: ["**/*.js"],
rules: {
...js.configs.all.rules,
"no-unused-vars": "warn"
}
}
]
```
## License
MIT
+31
View File
@@ -0,0 +1,31 @@
{
"name": "@eslint/js",
"version": "8.57.1",
"description": "ESLint JavaScript language implementation",
"main": "./src/index.js",
"scripts": {},
"files": [
"LICENSE",
"README.md",
"src"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/eslint/eslint.git",
"directory": "packages/js"
},
"homepage": "https://eslint.org",
"bugs": "https://github.com/eslint/eslint/issues/",
"keywords": [
"javascript",
"eslint-plugin",
"eslint"
],
"license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
}
+211
View File
@@ -0,0 +1,211 @@
/*
* WARNING: This file is autogenerated using the tools/update-eslint-all.js
* script. Do not edit manually.
*/
"use strict";
/* eslint quote-props: off -- autogenerated so don't lint */
module.exports = Object.freeze({
"rules": {
"accessor-pairs": "error",
"array-callback-return": "error",
"arrow-body-style": "error",
"block-scoped-var": "error",
"camelcase": "error",
"capitalized-comments": "error",
"class-methods-use-this": "error",
"complexity": "error",
"consistent-return": "error",
"consistent-this": "error",
"constructor-super": "error",
"curly": "error",
"default-case": "error",
"default-case-last": "error",
"default-param-last": "error",
"dot-notation": "error",
"eqeqeq": "error",
"for-direction": "error",
"func-name-matching": "error",
"func-names": "error",
"func-style": "error",
"getter-return": "error",
"grouped-accessor-pairs": "error",
"guard-for-in": "error",
"id-denylist": "error",
"id-length": "error",
"id-match": "error",
"init-declarations": "error",
"line-comment-position": "error",
"logical-assignment-operators": "error",
"max-classes-per-file": "error",
"max-depth": "error",
"max-lines": "error",
"max-lines-per-function": "error",
"max-nested-callbacks": "error",
"max-params": "error",
"max-statements": "error",
"multiline-comment-style": "error",
"new-cap": "error",
"no-alert": "error",
"no-array-constructor": "error",
"no-async-promise-executor": "error",
"no-await-in-loop": "error",
"no-bitwise": "error",
"no-caller": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-console": "error",
"no-const-assign": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-constructor-return": "error",
"no-continue": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-div-regex": "error",
"no-dupe-args": "error",
"no-dupe-class-members": "error",
"no-dupe-else-if": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-duplicate-imports": "error",
"no-else-return": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-function": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-eq-null": "error",
"no-eval": "error",
"no-ex-assign": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-boolean-cast": "error",
"no-extra-label": "error",
"no-fallthrough": "error",
"no-func-assign": "error",
"no-global-assign": "error",
"no-implicit-coercion": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-import-assign": "error",
"no-inline-comments": "error",
"no-inner-declarations": "error",
"no-invalid-regexp": "error",
"no-invalid-this": "error",
"no-irregular-whitespace": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-loss-of-precision": "error",
"no-magic-numbers": "error",
"no-misleading-character-class": "error",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-negated-condition": "error",
"no-nested-ternary": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-native-nonconstructor": "error",
"no-new-symbol": "error",
"no-new-wrappers": "error",
"no-nonoctal-decimal-escape": "error",
"no-obj-calls": "error",
"no-object-constructor": "error",
"no-octal": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
"no-plusplus": "error",
"no-promise-executor-return": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-restricted-exports": "error",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-script-url": "error",
"no-self-assign": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-setter-return": "error",
"no-shadow": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-template-curly-in-string": "error",
"no-ternary": "error",
"no-this-before-super": "error",
"no-throw-literal": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-undefined": "error",
"no-underscore-dangle": "error",
"no-unexpected-multiline": "error",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error",
"no-unreachable": "error",
"no-unreachable-loop": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-unused-vars": "error",
"no-use-before-define": "error",
"no-useless-backreference": "error",
"no-useless-call": "error",
"no-useless-catch": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-constructor": "error",
"no-useless-escape": "error",
"no-useless-rename": "error",
"no-useless-return": "error",
"no-var": "error",
"no-void": "error",
"no-warning-comments": "error",
"no-with": "error",
"object-shorthand": "error",
"one-var": "error",
"operator-assignment": "error",
"prefer-arrow-callback": "error",
"prefer-const": "error",
"prefer-destructuring": "error",
"prefer-exponentiation-operator": "error",
"prefer-named-capture-group": "error",
"prefer-numeric-literals": "error",
"prefer-object-has-own": "error",
"prefer-object-spread": "error",
"prefer-promise-reject-errors": "error",
"prefer-regex-literals": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
"radix": "error",
"require-atomic-updates": "error",
"require-await": "error",
"require-unicode-regexp": "error",
"require-yield": "error",
"sort-imports": "error",
"sort-keys": "error",
"sort-vars": "error",
"strict": "error",
"symbol-description": "error",
"unicode-bom": "error",
"use-isnan": "error",
"valid-typeof": "error",
"vars-on-top": "error",
"yoda": "error"
}
});
+76
View File
@@ -0,0 +1,76 @@
/**
* @fileoverview Configuration applied when a user configuration extends from
* eslint:recommended.
* @author Nicholas C. Zakas
*/
"use strict";
/* eslint sort-keys: ["error", "asc"] -- Long, so make more readable */
/** @type {import("../lib/shared/types").ConfigData} */
module.exports = Object.freeze({
rules: Object.freeze({
"constructor-super": "error",
"for-direction": "error",
"getter-return": "error",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-const-assign": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-args": "error",
"no-dupe-class-members": "error",
"no-dupe-else-if": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-extra-semi": "error",
"no-fallthrough": "error",
"no-func-assign": "error",
"no-global-assign": "error",
"no-import-assign": "error",
"no-inner-declarations": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-mixed-spaces-and-tabs": "error",
"no-new-symbol": "error",
"no-nonoctal-decimal-escape": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-prototype-builtins": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-setter-return": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
"no-undef": "error",
"no-unexpected-multiline": "error",
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-unused-vars": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-with": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error"
})
});
+17
View File
@@ -0,0 +1,17 @@
/**
* @fileoverview Main package entrypoint.
* @author Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
module.exports = {
configs: {
all: require("./configs/eslint-all"),
recommended: require("./configs/eslint-recommended")
}
};
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+342
View File
@@ -0,0 +1,342 @@
# Config Array
by [Nicholas C. Zakas](https://humanwhocodes.com)
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
## Description
A config array is a way of managing configurations that are based on glob pattern matching of filenames. Each config array contains the information needed to determine the correct configuration for any file based on the filename.
## Background
In 2019, I submitted an [ESLint RFC](https://github.com/eslint/rfcs/pull/9) proposing a new way of configuring ESLint. The goal was to streamline what had become an increasingly complicated configuration process. Over several iterations, this proposal was eventually born.
The basic idea is that all configuration, including overrides, can be represented by a single array where each item in the array is a config object. Config objects appearing later in the array override config objects appearing earlier in the array. You can calculate a config for a given file by traversing all config objects in the array to find the ones that match the filename. Matching is done by specifying glob patterns in `files` and `ignores` properties on each config object. Here's an example:
```js
export default [
// match all JSON files
{
name: "JSON Handler",
files: ["**/*.json"],
handler: jsonHandler
},
// match only package.json
{
name: "package.json Handler",
files: ["package.json"],
handler: packageJsonHandler
}
];
```
In this example, there are two config objects: the first matches all JSON files in all directories and the second matches just `package.json` in the base path directory (all the globs are evaluated as relative to a base path that can be specified). When you retrieve a configuration for `foo.json`, only the first config object matches so `handler` is equal to `jsonHandler`; when you retrieve a configuration for `package.json`, `handler` is equal to `packageJsonHandler` (because both config objects match, the second one wins).
## Installation
You can install the package using npm or Yarn:
```bash
npm install @humanwhocodes/config-array --save
# or
yarn add @humanwhocodes/config-array
```
## Usage
First, import the `ConfigArray` constructor:
```js
import { ConfigArray } from "@humanwhocodes/config-array";
// or using CommonJS
const { ConfigArray } = require("@humanwhocodes/config-array");
```
When you create a new instance of `ConfigArray`, you must pass in two arguments: an array of configs and an options object. The array of configs is most likely read in from a configuration file, so here's a typical example:
```js
const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(configFilename);
const configs = new ConfigArray(rawConfigs, {
// the path to match filenames from
basePath: process.cwd(),
// additional items in each config
schema: mySchema
});
```
This example reads in an object or array from `my.config.js` and passes it into the `ConfigArray` constructor as the first argument. The second argument is an object specifying the `basePath` (the directory in which `my.config.js` is found) and a `schema` to define the additional properties of a config object beyond `files`, `ignores`, and `name`.
### Specifying a Schema
The `schema` option is required for you to use additional properties in config objects. The schema is an object that follows the format of an [`ObjectSchema`](https://npmjs.com/package/@humanwhocodes/object-schema). The schema specifies both validation and merge rules that the `ConfigArray` instance needs to combine configs when there are multiple matches. Here's an example:
```js
const configFilename = path.resolve(process.cwd(), "my.config.js");
const { default: rawConfigs } = await import(configFilename);
const mySchema = {
// define the handler key in configs
handler: {
required: true,
merge(a, b) {
if (!b) return a;
if (!a) return b;
},
validate(value) {
if (typeof value !== "function") {
throw new TypeError("Function expected.");
}
}
}
};
const configs = new ConfigArray(rawConfigs, {
// the path to match filenames from
basePath: process.cwd(),
// additional item schemas in each config
schema: mySchema,
// additional config types supported (default: [])
extraConfigTypes: ["array", "function"];
});
```
### Config Arrays
Config arrays can be multidimensional, so it's possible for a config array to contain another config array when `extraConfigTypes` contains `"array"`, such as:
```js
export default [
// JS config
{
files: ["**/*.js"],
handler: jsHandler
},
// JSON configs
[
// match all JSON files
{
name: "JSON Handler",
files: ["**/*.json"],
handler: jsonHandler
},
// match only package.json
{
name: "package.json Handler",
files: ["package.json"],
handler: packageJsonHandler
}
],
// filename must match function
{
files: [ filePath => filePath.endsWith(".md") ],
handler: markdownHandler
},
// filename must match all patterns in subarray
{
files: [ ["*.test.*", "*.js"] ],
handler: jsTestHandler
},
// filename must not match patterns beginning with !
{
name: "Non-JS files",
files: ["!*.js"],
settings: {
js: false
}
}
];
```
In this example, the array contains both config objects and a config array. When a config array is normalized (see details below), it is flattened so only config objects remain. However, the order of evaluation remains the same.
If the `files` array contains a function, then that function is called with the absolute path of the file and is expected to return `true` if there is a match and `false` if not. (The `ignores` array can also contain functions.)
If the `files` array contains an item that is an array of strings and functions, then all patterns must match in order for the config to match. In the preceding examples, both `*.test.*` and `*.js` must match in order for the config object to be used.
If a pattern in the files array begins with `!` then it excludes that pattern. In the preceding example, any filename that doesn't end with `.js` will automatically get a `settings.js` property set to `false`.
You can also specify an `ignores` key that will force files matching those patterns to not be included. If the `ignores` key is in a config object without any other keys, then those ignores will always be applied; otherwise those ignores act as exclusions. Here's an example:
```js
export default [
// Always ignored
{
ignores: ["**/.git/**", "**/node_modules/**"]
},
// .eslintrc.js file is ignored only when .js file matches
{
files: ["**/*.js"],
ignores: [".eslintrc.js"]
handler: jsHandler
}
];
```
You can use negated patterns in `ignores` to exclude a file that was already ignored, such as:
```js
export default [
// Ignore all JSON files except tsconfig.json
{
files: ["**/*"],
ignores: ["**/*.json", "!tsconfig.json"]
},
];
```
### Config Functions
Config arrays can also include config functions when `extraConfigTypes` contains `"function"`. A config function accepts a single parameter, `context` (defined by you), and must return either a config object or a config array (it cannot return another function). Config functions allow end users to execute code in the creation of appropriate config objects. Here's an example:
```js
export default [
// JS config
{
files: ["**/*.js"],
handler: jsHandler
},
// JSON configs
function (context) {
return [
// match all JSON files
{
name: context.name + " JSON Handler",
files: ["**/*.json"],
handler: jsonHandler
},
// match only package.json
{
name: context.name + " package.json Handler",
files: ["package.json"],
handler: packageJsonHandler
}
];
}
];
```
When a config array is normalized, each function is executed and replaced in the config array with the return value.
**Note:** Config functions can also be async.
### Normalizing Config Arrays
Once a config array has been created and loaded with all of the raw config data, it must be normalized before it can be used. The normalization process goes through and flattens the config array as well as executing all config functions to get their final values.
To normalize a config array, call the `normalize()` method and pass in a context object:
```js
await configs.normalize({
name: "MyApp"
});
```
The `normalize()` method returns a promise, so be sure to use the `await` operator. The config array instance is normalized in-place, so you don't need to create a new variable.
If you want to disallow async config functions, you can call `normalizeSync()` instead. This method is completely synchronous and does not require using the `await` operator as it does not return a promise:
```js
await configs.normalizeSync({
name: "MyApp"
});
```
**Important:** Once a `ConfigArray` is normalized, it cannot be changed further. You can, however, create a new `ConfigArray` and pass in the normalized instance to create an unnormalized copy.
### Getting Config for a File
To get the config for a file, use the `getConfig()` method on a normalized config array and pass in the filename to get a config for:
```js
// pass in absolute filename
const fileConfig = configs.getConfig(path.resolve(process.cwd(), "package.json"));
```
The config array always returns an object, even if there are no configs matching the given filename. You can then inspect the returned config object to determine how to proceed.
A few things to keep in mind:
* You must pass in the absolute filename to get a config for.
* The returned config object never has `files`, `ignores`, or `name` properties; the only properties on the object will be the other configuration options specified.
* The config array caches configs, so subsequent calls to `getConfig()` with the same filename will return in a fast lookup rather than another calculation.
* A config will only be generated if the filename matches an entry in a `files` key. A config will not be generated without matching a `files` key (configs without a `files` key are only applied when another config with a `files` key is applied; configs without `files` are never applied on their own). Any config with a `files` key entry ending with `/**` or `/*` will only be applied if another entry in the same `files` key matches or another config matches.
## Determining Ignored Paths
You can determine if a file is ignored by using the `isFileIgnored()` method and passing in the absolute path of any file, as in this example:
```js
const ignored = configs.isFileIgnored('/foo/bar/baz.txt');
```
A file is considered ignored if any of the following is true:
* **It's parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/a.js` is considered ignored.
* **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/baz/a.js` is considered ignored.
* **It matches an ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
* **If it matches an entry in `files` and also in `ignores`.** For example, if `**/*.js` is in `files` and `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
* **The file is outside the `basePath`.** If the `basePath` is `/usr/me`, then `/foo/a.js` is considered ignored.
For directories, use the `isDirectoryIgnored()` method and pass in the absolute path of any directory, as in this example:
```js
const ignored = configs.isDirectoryIgnored('/foo/bar/');
```
A directory is considered ignored if any of the following is true:
* **It's parent directory is ignored.** For example, if `foo` is in `ignores`, then `foo/baz` is considered ignored.
* **It has an ancestor directory that is ignored.** For example, if `foo` is in `ignores`, then `foo/bar/baz/a.js` is considered ignored.
* **It matches and ignored file pattern.** For example, if `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
* **If it matches an entry in `files` and also in `ignores`.** For example, if `**/*.js` is in `files` and `**/a.js` is in `ignores`, then `foo/a.js` and `foo/baz/a.js` are considered ignored.
* **The file is outside the `basePath`.** If the `basePath` is `/usr/me`, then `/foo/a.js` is considered ignored.
**Important:** A pattern such as `foo/**` means that `foo` and `foo/` are *not* ignored whereas `foo/bar` is ignored. If you want to ignore `foo` and all of its subdirectories, use the pattern `foo` or `foo/` in `ignores`.
## Caching Mechanisms
Each `ConfigArray` aggressively caches configuration objects to avoid unnecessary work. This caching occurs in two ways:
1. **File-based Caching.** For each filename that is passed into a method, the resulting config is cached against that filename so you're always guaranteed to get the same object returned from `getConfig()` whenever you pass the same filename in.
2. **Index-based Caching.** Whenever a config is calculated, the config elements that were used to create the config are also cached. So if a given filename matches elements 1, 5, and 7, the resulting config is cached with a key of `1,5,7`. That way, if another file is passed that matches the same config elements, the result is already known and doesn't have to be recalculated. That means two files that match all the same elements will return the same config from `getConfig()`.
## Acknowledgements
The design of this project was influenced by feedback on the ESLint RFC, and incorporates ideas from:
* Teddy Katz (@not-an-aardvark)
* Toru Nagashima (@mysticatea)
* Kai Cataldo (@kaicataldo)
## License
Apache 2.0
+1128
View File
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
{
"name": "@humanwhocodes/config-array",
"version": "0.13.0",
"description": "Glob-based configuration matching.",
"author": "Nicholas C. Zakas",
"main": "api.js",
"files": [
"api.js",
"LICENSE",
"README.md"
],
"repository": {
"type": "git",
"url": "git+https://github.com/humanwhocodes/config-array.git"
},
"bugs": {
"url": "https://github.com/humanwhocodes/config-array/issues"
},
"homepage": "https://github.com/humanwhocodes/config-array#readme",
"scripts": {
"build": "rollup -c",
"format": "nitpik",
"lint": "eslint *.config.js src/*.js tests/*.js",
"lint:fix": "eslint --fix *.config.js src/*.js tests/*.js",
"prepublish": "npm run build",
"test:coverage": "nyc --include src/*.js npm run test",
"test": "mocha -r esm tests/ --recursive"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"eslint --fix --ignore-pattern '!.eslintrc.js'"
]
},
"keywords": [
"configuration",
"configarray",
"config file"
],
"license": "Apache-2.0",
"engines": {
"node": ">=10.10.0"
},
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.3",
"debug": "^4.3.1",
"minimatch": "^3.0.5"
},
"devDependencies": {
"@nitpik/javascript": "0.4.0",
"@nitpik/node": "0.0.5",
"chai": "4.3.10",
"eslint": "8.52.0",
"esm": "3.2.25",
"lint-staged": "15.0.2",
"mocha": "6.2.3",
"nyc": "15.1.0",
"rollup": "3.28.1",
"yorkie": "2.0.0"
}
}
+15
View File
@@ -0,0 +1,15 @@
# Changelog
## [1.0.1](https://github.com/humanwhocodes/module-importer/compare/v1.0.0...v1.0.1) (2022-08-18)
### Bug Fixes
* Ensure CommonJS mode works correctly. ([cf54a0b](https://github.com/humanwhocodes/module-importer/commit/cf54a0b998085066fbe1776dd0b4cacd808cc192)), closes [#6](https://github.com/humanwhocodes/module-importer/issues/6)
## 1.0.0 (2022-08-17)
### Features
* Implement ModuleImporter ([3ce4e82](https://www.github.com/humanwhocodes/module-importer/commit/3ce4e820c30c114e787bfed00a0966ac4772f563))
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+80
View File
@@ -0,0 +1,80 @@
# ModuleImporter
by [Nicholas C. Zakas](https://humanwhocodes.com)
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
## Description
A utility for seamlessly importing modules in Node.js regardless if they are CommonJS or ESM format. Under the hood, this uses `import()` and relies on Node.js's CommonJS compatibility to work correctly. This ensures that the correct locations and formats are used for CommonJS so you can call one method and not worry about any compatibility issues.
The problem with the default `import()` is that it always resolves relative to the file location in which it is called. If you want to resolve from a different location, you need to jump through a few hoops to achieve that. This package makes it easy to both resolve and import modules from any directory.
## Usage
### Node.js
Install using [npm][npm] or [yarn][yarn]:
```
npm install @humanwhocodes/module-importer
# or
yarn add @humanwhocodes/module-importer
```
Import into your Node.js project:
```js
// CommonJS
const { ModuleImporter } = require("@humanwhocodes/module-importer");
// ESM
import { ModuleImporter } from "@humanwhocodes/module-importer";
```
### Bun
Install using this command:
```
bun add @humanwhocodes/module-importer
```
Import into your Bun project:
```js
import { ModuleImporter } from "@humanwhocodes/module-importer";
```
## API
After importing, create a new instance of `ModuleImporter` to start emitting events:
```js
// cwd can be omitted to use process.cwd()
const importer = new ModuleImporter(cwd);
// you can resolve the location of any package
const location = importer.resolve("./some-file.cjs");
// you can also import directly
const module = importer.import("./some-file.cjs");
```
For both `resolve()` and `import()`, you can pass in package names and filenames.
## Developer Setup
1. Fork the repository
2. Clone your fork
3. Run `npm install` to setup dependencies
4. Run `npm test` to run tests
## License
Apache 2.0
[npm]: https://npmjs.com/
[yarn]: https://yarnpkg.com/
+65
View File
@@ -0,0 +1,65 @@
{
"name": "@humanwhocodes/module-importer",
"version": "1.0.1",
"description": "Universal module importer for Node.js",
"main": "src/module-importer.cjs",
"module": "src/module-importer.js",
"type": "module",
"types": "dist/module-importer.d.ts",
"exports": {
"require": "./src/module-importer.cjs",
"import": "./src/module-importer.js"
},
"files": [
"dist",
"src"
],
"publishConfig": {
"access": "public"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": [
"eslint --fix"
]
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/nzakas"
},
"scripts": {
"build": "rollup -c && tsc",
"prepare": "npm run build",
"lint": "eslint src/ tests/",
"test:unit": "c8 mocha tests/module-importer.test.js",
"test:build": "node tests/pkg.test.cjs && node tests/pkg.test.mjs",
"test": "npm run test:unit && npm run test:build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/humanwhocodes/module-importer.git"
},
"keywords": [
"modules",
"esm",
"commonjs"
],
"engines": {
"node": ">=12.22"
},
"author": "Nicholas C. Zaks",
"license": "Apache-2.0",
"devDependencies": {
"@types/node": "^18.7.6",
"c8": "7.12.0",
"chai": "4.3.6",
"eslint": "8.22.0",
"lint-staged": "13.0.3",
"mocha": "9.2.2",
"rollup": "2.78.0",
"typescript": "4.7.4",
"yorkie": "2.0.0"
}
}
+81
View File
@@ -0,0 +1,81 @@
/**
* @fileoverview Universal module importer
*/
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------
const { createRequire } = require("module");
const { pathToFileURL } = require("url");
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
const SLASHES = new Set(["/", "\\"]);
/**
* Normalizes directories to have a trailing slash.
* Resolve is pretty finicky -- if the directory name doesn't have
* a trailing slash then it tries to look in the parent directory.
* i.e., if the directory is "/usr/nzakas/foo" it will start the
* search in /usr/nzakas. However, if the directory is "/user/nzakas/foo/",
* then it will start the search in /user/nzakas/foo.
* @param {string} directory The directory to check.
* @returns {string} The normalized directory.
*/
function normalizeDirectory(directory) {
if (!SLASHES.has(directory[directory.length-1])) {
return directory + "/";
}
return directory;
}
//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
/**
* Class for importing both CommonJS and ESM modules in Node.js.
*/
exports.ModuleImporter = class ModuleImporter {
/**
* Creates a new instance.
* @param {string} [cwd] The current working directory to resolve from.
*/
constructor(cwd = process.cwd()) {
/**
* The base directory from which paths should be resolved.
* @type {string}
*/
this.cwd = normalizeDirectory(cwd);
}
/**
* Resolves a module based on its name or location.
* @param {string} specifier Either an npm package name or
* relative file path.
* @returns {string|undefined} The location of the import.
* @throws {Error} If specifier cannot be located.
*/
resolve(specifier) {
const require = createRequire(this.cwd);
return require.resolve(specifier);
}
/**
* Imports a module based on its name or location.
* @param {string} specifier Either an npm package name or
* relative file path.
* @returns {Promise<object>} The module's object.
*/
import(specifier) {
const location = this.resolve(specifier);
return import(pathToFileURL(location).href);
}
}
+22
View File
@@ -0,0 +1,22 @@
/**
* @fileoverview Universal module importer
*/
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------
import { createRequire } from "module";
import { fileURLToPath } from "url";
import { dirname } from "path";
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const require = createRequire(__dirname + "/");
const { ModuleImporter } = require("./module-importer.cjs");
export { ModuleImporter };
+40
View File
@@ -0,0 +1,40 @@
# Changelog
## [2.0.3](https://github.com/humanwhocodes/object-schema/compare/v2.0.2...v2.0.3) (2024-04-01)
### Bug Fixes
* Ensure test files are not including in package ([6eeb32c](https://github.com/humanwhocodes/object-schema/commit/6eeb32cc76a3e37d76b2990bd603d72061c816e0)), closes [#19](https://github.com/humanwhocodes/object-schema/issues/19)
## [2.0.2](https://github.com/humanwhocodes/object-schema/compare/v2.0.1...v2.0.2) (2024-01-10)
### Bug Fixes
* WrapperError should be an actual error ([2523f01](https://github.com/humanwhocodes/object-schema/commit/2523f014168167e5a40bb63e0cc03231b2c0f1bf))
## [2.0.1](https://github.com/humanwhocodes/object-schema/compare/v2.0.0...v2.0.1) (2023-10-20)
### Bug Fixes
* Custom properties should be available on thrown errors ([6ca80b0](https://github.com/humanwhocodes/object-schema/commit/6ca80b001a4ffb678b9b5544fc53322117374376))
## [2.0.0](https://github.com/humanwhocodes/object-schema/compare/v1.2.1...v2.0.0) (2023-10-18)
### ⚠ BREAKING CHANGES
* Throw custom errors instead of generics.
### Features
* Throw custom errors instead of generics. ([c6c01d7](https://github.com/humanwhocodes/object-schema/commit/c6c01d71eb354bf7b1fb3e883c40f7bd9b61647c))
### [1.2.1](https://www.github.com/humanwhocodes/object-schema/compare/v1.2.0...v1.2.1) (2021-11-02)
### Bug Fixes
* Never return original object from individual config ([5463c5c](https://www.github.com/humanwhocodes/object-schema/commit/5463c5c6d2cb35a7b7948dffc37c899a41d1775f))
+29
View File
@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2019, Human Who Codes
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+234
View File
@@ -0,0 +1,234 @@
# JavaScript ObjectSchema Package
by [Nicholas C. Zakas](https://humanwhocodes.com)
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
## Overview
A JavaScript object merge/validation utility where you can define a different merge and validation strategy for each key. This is helpful when you need to validate complex data structures and then merge them in a way that is more complex than `Object.assign()`.
## Installation
You can install using either npm:
```
npm install @humanwhocodes/object-schema
```
Or Yarn:
```
yarn add @humanwhocodes/object-schema
```
## Usage
Use CommonJS to get access to the `ObjectSchema` constructor:
```js
const { ObjectSchema } = require("@humanwhocodes/object-schema");
const schema = new ObjectSchema({
// define a definition for the "downloads" key
downloads: {
required: true,
merge(value1, value2) {
return value1 + value2;
},
validate(value) {
if (typeof value !== "number") {
throw new Error("Expected downloads to be a number.");
}
}
},
// define a strategy for the "versions" key
version: {
required: true,
merge(value1, value2) {
return value1.concat(value2);
},
validate(value) {
if (!Array.isArray(value)) {
throw new Error("Expected versions to be an array.");
}
}
}
});
const record1 = {
downloads: 25,
versions: [
"v1.0.0",
"v1.1.0",
"v1.2.0"
]
};
const record2 = {
downloads: 125,
versions: [
"v2.0.0",
"v2.1.0",
"v3.0.0"
]
};
// make sure the records are valid
schema.validate(record1);
schema.validate(record2);
// merge together (schema.merge() accepts any number of objects)
const result = schema.merge(record1, record2);
// result looks like this:
const result = {
downloads: 75,
versions: [
"v1.0.0",
"v1.1.0",
"v1.2.0",
"v2.0.0",
"v2.1.0",
"v3.0.0"
]
};
```
## Tips and Tricks
### Named merge strategies
Instead of specifying a `merge()` method, you can specify one of the following strings to use a default merge strategy:
* `"assign"` - use `Object.assign()` to merge the two values into one object.
* `"overwrite"` - the second value always replaces the first.
* `"replace"` - the second value replaces the first if the second is not `undefined`.
For example:
```js
const schema = new ObjectSchema({
name: {
merge: "replace",
validate() {}
}
});
```
### Named validation strategies
Instead of specifying a `validate()` method, you can specify one of the following strings to use a default validation strategy:
* `"array"` - value must be an array.
* `"boolean"` - value must be a boolean.
* `"number"` - value must be a number.
* `"object"` - value must be an object.
* `"object?"` - value must be an object or null.
* `"string"` - value must be a string.
* `"string!"` - value must be a non-empty string.
For example:
```js
const schema = new ObjectSchema({
name: {
merge: "replace",
validate: "string"
}
});
```
### Subschemas
If you are defining a key that is, itself, an object, you can simplify the process by using a subschema. Instead of defining `merge()` and `validate()`, assign a `schema` key that contains a schema definition, like this:
```js
const schema = new ObjectSchema({
name: {
schema: {
first: {
merge: "replace",
validate: "string"
},
last: {
merge: "replace",
validate: "string"
}
}
}
});
schema.validate({
name: {
first: "n",
last: "z"
}
});
```
### Remove Keys During Merge
If the merge strategy for a key returns `undefined`, then the key will not appear in the final object. For example:
```js
const schema = new ObjectSchema({
date: {
merge() {
return undefined;
},
validate(value) {
Date.parse(value); // throws an error when invalid
}
}
});
const object1 = { date: "5/5/2005" };
const object2 = { date: "6/6/2006" };
const result = schema.merge(object1, object2);
console.log("date" in result); // false
```
### Requiring Another Key Be Present
If you'd like the presence of one key to require the presence of another key, you can use the `requires` property to specify an array of other properties that any key requires. For example:
```js
const schema = new ObjectSchema();
const schema = new ObjectSchema({
date: {
merge() {
return undefined;
},
validate(value) {
Date.parse(value); // throws an error when invalid
}
},
time: {
requires: ["date"],
merge(first, second) {
return second;
},
validate(value) {
// ...
}
}
});
// throws error: Key "time" requires keys "date"
schema.validate({
time: "13:45"
});
```
In this example, even though `date` is an optional key, it is required to be present whenever `time` is present.
## License
BSD 3-Clause
+38
View File
@@ -0,0 +1,38 @@
{
"name": "@humanwhocodes/object-schema",
"version": "2.0.3",
"description": "An object schema merger/validator",
"main": "src/index.js",
"files": [
"src",
"LICENSE",
"README.md"
],
"directories": {
"test": "tests"
},
"scripts": {
"test": "mocha tests/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/humanwhocodes/object-schema.git"
},
"keywords": [
"object",
"validation",
"schema",
"merge"
],
"author": "Nicholas C. Zakas",
"license": "BSD-3-Clause",
"bugs": {
"url": "https://github.com/humanwhocodes/object-schema/issues"
},
"homepage": "https://github.com/humanwhocodes/object-schema#readme",
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.13.0",
"mocha": "^5.2.0"
}
}
+7
View File
@@ -0,0 +1,7 @@
/**
* @filedescription Object Schema Package
*/
exports.ObjectSchema = require("./object-schema").ObjectSchema;
exports.MergeStrategy = require("./merge-strategy").MergeStrategy;
exports.ValidationStrategy = require("./validation-strategy").ValidationStrategy;
+53
View File
@@ -0,0 +1,53 @@
/**
* @filedescription Merge Strategy
*/
"use strict";
//-----------------------------------------------------------------------------
// Class
//-----------------------------------------------------------------------------
/**
* Container class for several different merge strategies.
*/
class MergeStrategy {
/**
* Merges two keys by overwriting the first with the second.
* @param {*} value1 The value from the first object key.
* @param {*} value2 The value from the second object key.
* @returns {*} The second value.
*/
static overwrite(value1, value2) {
return value2;
}
/**
* Merges two keys by replacing the first with the second only if the
* second is defined.
* @param {*} value1 The value from the first object key.
* @param {*} value2 The value from the second object key.
* @returns {*} The second value if it is defined.
*/
static replace(value1, value2) {
if (typeof value2 !== "undefined") {
return value2;
}
return value1;
}
/**
* Merges two properties by assigning properties from the second to the first.
* @param {*} value1 The value from the first object key.
* @param {*} value2 The value from the second object key.
* @returns {*} A new object containing properties from both value1 and
* value2.
*/
static assign(value1, value2) {
return Object.assign({}, value1, value2);
}
}
exports.MergeStrategy = MergeStrategy;
+301
View File
@@ -0,0 +1,301 @@
/**
* @filedescription Object Schema
*/
"use strict";
//-----------------------------------------------------------------------------
// Requirements
//-----------------------------------------------------------------------------
const { MergeStrategy } = require("./merge-strategy");
const { ValidationStrategy } = require("./validation-strategy");
//-----------------------------------------------------------------------------
// Private
//-----------------------------------------------------------------------------
const strategies = Symbol("strategies");
const requiredKeys = Symbol("requiredKeys");
/**
* Validates a schema strategy.
* @param {string} name The name of the key this strategy is for.
* @param {Object} strategy The strategy for the object key.
* @param {boolean} [strategy.required=true] Whether the key is required.
* @param {string[]} [strategy.requires] Other keys that are required when
* this key is present.
* @param {Function} strategy.merge A method to call when merging two objects
* with the same key.
* @param {Function} strategy.validate A method to call when validating an
* object with the key.
* @returns {void}
* @throws {Error} When the strategy is missing a name.
* @throws {Error} When the strategy is missing a merge() method.
* @throws {Error} When the strategy is missing a validate() method.
*/
function validateDefinition(name, strategy) {
let hasSchema = false;
if (strategy.schema) {
if (typeof strategy.schema === "object") {
hasSchema = true;
} else {
throw new TypeError("Schema must be an object.");
}
}
if (typeof strategy.merge === "string") {
if (!(strategy.merge in MergeStrategy)) {
throw new TypeError(`Definition for key "${name}" missing valid merge strategy.`);
}
} else if (!hasSchema && typeof strategy.merge !== "function") {
throw new TypeError(`Definition for key "${name}" must have a merge property.`);
}
if (typeof strategy.validate === "string") {
if (!(strategy.validate in ValidationStrategy)) {
throw new TypeError(`Definition for key "${name}" missing valid validation strategy.`);
}
} else if (!hasSchema && typeof strategy.validate !== "function") {
throw new TypeError(`Definition for key "${name}" must have a validate() method.`);
}
}
//-----------------------------------------------------------------------------
// Errors
//-----------------------------------------------------------------------------
/**
* Error when an unexpected key is found.
*/
class UnexpectedKeyError extends Error {
/**
* Creates a new instance.
* @param {string} key The key that was unexpected.
*/
constructor(key) {
super(`Unexpected key "${key}" found.`);
}
}
/**
* Error when a required key is missing.
*/
class MissingKeyError extends Error {
/**
* Creates a new instance.
* @param {string} key The key that was missing.
*/
constructor(key) {
super(`Missing required key "${key}".`);
}
}
/**
* Error when a key requires other keys that are missing.
*/
class MissingDependentKeysError extends Error {
/**
* Creates a new instance.
* @param {string} key The key that was unexpected.
* @param {Array<string>} requiredKeys The keys that are required.
*/
constructor(key, requiredKeys) {
super(`Key "${key}" requires keys "${requiredKeys.join("\", \"")}".`);
}
}
/**
* Wrapper error for errors occuring during a merge or validate operation.
*/
class WrapperError extends Error {
/**
* Creates a new instance.
* @param {string} key The object key causing the error.
* @param {Error} source The source error.
*/
constructor(key, source) {
super(`Key "${key}": ${source.message}`, { cause: source });
// copy over custom properties that aren't represented
for (const key of Object.keys(source)) {
if (!(key in this)) {
this[key] = source[key];
}
}
}
}
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
/**
* Represents an object validation/merging schema.
*/
class ObjectSchema {
/**
* Creates a new instance.
*/
constructor(definitions) {
if (!definitions) {
throw new Error("Schema definitions missing.");
}
/**
* Track all strategies in the schema by key.
* @type {Map}
* @property strategies
*/
this[strategies] = new Map();
/**
* Separately track any keys that are required for faster validation.
* @type {Map}
* @property requiredKeys
*/
this[requiredKeys] = new Map();
// add in all strategies
for (const key of Object.keys(definitions)) {
validateDefinition(key, definitions[key]);
// normalize merge and validate methods if subschema is present
if (typeof definitions[key].schema === "object") {
const schema = new ObjectSchema(definitions[key].schema);
definitions[key] = {
...definitions[key],
merge(first = {}, second = {}) {
return schema.merge(first, second);
},
validate(value) {
ValidationStrategy.object(value);
schema.validate(value);
}
};
}
// normalize the merge method in case there's a string
if (typeof definitions[key].merge === "string") {
definitions[key] = {
...definitions[key],
merge: MergeStrategy[definitions[key].merge]
};
};
// normalize the validate method in case there's a string
if (typeof definitions[key].validate === "string") {
definitions[key] = {
...definitions[key],
validate: ValidationStrategy[definitions[key].validate]
};
};
this[strategies].set(key, definitions[key]);
if (definitions[key].required) {
this[requiredKeys].set(key, definitions[key]);
}
}
}
/**
* Determines if a strategy has been registered for the given object key.
* @param {string} key The object key to find a strategy for.
* @returns {boolean} True if the key has a strategy registered, false if not.
*/
hasKey(key) {
return this[strategies].has(key);
}
/**
* Merges objects together to create a new object comprised of the keys
* of the all objects. Keys are merged based on the each key's merge
* strategy.
* @param {...Object} objects The objects to merge.
* @returns {Object} A new object with a mix of all objects' keys.
* @throws {Error} If any object is invalid.
*/
merge(...objects) {
// double check arguments
if (objects.length < 2) {
throw new TypeError("merge() requires at least two arguments.");
}
if (objects.some(object => (object == null || typeof object !== "object"))) {
throw new TypeError("All arguments must be objects.");
}
return objects.reduce((result, object) => {
this.validate(object);
for (const [key, strategy] of this[strategies]) {
try {
if (key in result || key in object) {
const value = strategy.merge.call(this, result[key], object[key]);
if (value !== undefined) {
result[key] = value;
}
}
} catch (ex) {
throw new WrapperError(key, ex);
}
}
return result;
}, {});
}
/**
* Validates an object's keys based on the validate strategy for each key.
* @param {Object} object The object to validate.
* @returns {void}
* @throws {Error} When the object is invalid.
*/
validate(object) {
// check existing keys first
for (const key of Object.keys(object)) {
// check to see if the key is defined
if (!this.hasKey(key)) {
throw new UnexpectedKeyError(key);
}
// validate existing keys
const strategy = this[strategies].get(key);
// first check to see if any other keys are required
if (Array.isArray(strategy.requires)) {
if (!strategy.requires.every(otherKey => otherKey in object)) {
throw new MissingDependentKeysError(key, strategy.requires);
}
}
// now apply remaining validation strategy
try {
strategy.validate.call(strategy, object[key]);
} catch (ex) {
throw new WrapperError(key, ex);
}
}
// ensure required keys aren't missing
for (const [key] of this[requiredKeys]) {
if (!(key in object)) {
throw new MissingKeyError(key);
}
}
}
}
exports.ObjectSchema = ObjectSchema;
+102
View File
@@ -0,0 +1,102 @@
/**
* @filedescription Validation Strategy
*/
"use strict";
//-----------------------------------------------------------------------------
// Class
//-----------------------------------------------------------------------------
/**
* Container class for several different validation strategies.
*/
class ValidationStrategy {
/**
* Validates that a value is an array.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static array(value) {
if (!Array.isArray(value)) {
throw new TypeError("Expected an array.");
}
}
/**
* Validates that a value is a boolean.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static boolean(value) {
if (typeof value !== "boolean") {
throw new TypeError("Expected a Boolean.");
}
}
/**
* Validates that a value is a number.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static number(value) {
if (typeof value !== "number") {
throw new TypeError("Expected a number.");
}
}
/**
* Validates that a value is a object.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static object(value) {
if (!value || typeof value !== "object") {
throw new TypeError("Expected an object.");
}
}
/**
* Validates that a value is a object or null.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static "object?"(value) {
if (typeof value !== "object") {
throw new TypeError("Expected an object or null.");
}
}
/**
* Validates that a value is a string.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static string(value) {
if (typeof value !== "string") {
throw new TypeError("Expected a string.");
}
}
/**
* Validates that a value is a non-empty string.
* @param {*} value The value to validate.
* @returns {void}
* @throws {TypeError} If the value is invalid.
*/
static "string!"(value) {
if (typeof value !== "string" || value.length === 0) {
throw new TypeError("Expected a non-empty string.");
}
}
}
exports.ValidationStrategy = ValidationStrategy;
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Denis Malinochkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+171
View File
@@ -0,0 +1,171 @@
# @nodelib/fs.scandir
> List files and directories inside the specified directory.
## :bulb: Highlights
The package is aimed at obtaining information about entries in the directory.
* :moneybag: Returns useful information: `name`, `path`, `dirent` and `stats` (optional).
* :gear: On Node.js 10.10+ uses the mechanism without additional calls to determine the entry type. See [`old` and `modern` mode](#old-and-modern-mode).
* :link: Can safely work with broken symbolic links.
## Install
```console
npm install @nodelib/fs.scandir
```
## Usage
```ts
import * as fsScandir from '@nodelib/fs.scandir';
fsScandir.scandir('path', (error, stats) => { /* … */ });
```
## API
### .scandir(path, [optionsOrSettings], callback)
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path with standard callback-style.
```ts
fsScandir.scandir('path', (error, entries) => { /* … */ });
fsScandir.scandir('path', {}, (error, entries) => { /* … */ });
fsScandir.scandir('path', new fsScandir.Settings(), (error, entries) => { /* … */ });
```
### .scandirSync(path, [optionsOrSettings])
Returns an array of plain objects ([`Entry`](#entry)) with information about entry for provided path.
```ts
const entries = fsScandir.scandirSync('path');
const entries = fsScandir.scandirSync('path', {});
const entries = fsScandir.scandirSync(('path', new fsScandir.Settings());
```
#### path
* Required: `true`
* Type: `string | Buffer | URL`
A path to a file. If a URL is provided, it must use the `file:` protocol.
#### optionsOrSettings
* Required: `false`
* Type: `Options | Settings`
* Default: An instance of `Settings` class
An [`Options`](#options) object or an instance of [`Settings`](#settingsoptions) class.
> :book: When you pass a plain object, an instance of the `Settings` class will be created automatically. If you plan to call the method frequently, use a pre-created instance of the `Settings` class.
### Settings([options])
A class of full settings of the package.
```ts
const settings = new fsScandir.Settings({ followSymbolicLinks: false });
const entries = fsScandir.scandirSync('path', settings);
```
## Entry
* `name` — The name of the entry (`unknown.txt`).
* `path` — The path of the entry relative to call directory (`root/unknown.txt`).
* `dirent` — An instance of [`fs.Dirent`](./src/types/index.ts) class. On Node.js below 10.10 will be emulated by [`DirentFromStats`](./src/utils/fs.ts) class.
* `stats` (optional) — An instance of `fs.Stats` class.
For example, the `scandir` call for `tools` directory with one directory inside:
```ts
{
dirent: Dirent { name: 'typedoc', /* … */ },
name: 'typedoc',
path: 'tools/typedoc'
}
```
## Options
### stats
* Type: `boolean`
* Default: `false`
Adds an instance of `fs.Stats` class to the [`Entry`](#entry).
> :book: Always use `fs.readdir` without the `withFileTypes` option. ??TODO??
### followSymbolicLinks
* Type: `boolean`
* Default: `false`
Follow symbolic links or not. Call `fs.stat` on symbolic link if `true`.
### `throwErrorOnBrokenSymbolicLink`
* Type: `boolean`
* Default: `true`
Throw an error when symbolic link is broken if `true` or safely use `lstat` call if `false`.
### `pathSegmentSeparator`
* Type: `string`
* Default: `path.sep`
By default, this package uses the correct path separator for your OS (`\` on Windows, `/` on Unix-like systems). But you can set this option to any separator character(s) that you want to use instead.
### `fs`
* Type: [`FileSystemAdapter`](./src/adapters/fs.ts)
* Default: A default FS methods
By default, the built-in Node.js module (`fs`) is used to work with the file system. You can replace any method with your own.
```ts
interface FileSystemAdapter {
lstat?: typeof fs.lstat;
stat?: typeof fs.stat;
lstatSync?: typeof fs.lstatSync;
statSync?: typeof fs.statSync;
readdir?: typeof fs.readdir;
readdirSync?: typeof fs.readdirSync;
}
const settings = new fsScandir.Settings({
fs: { lstat: fakeLstat }
});
```
## `old` and `modern` mode
This package has two modes that are used depending on the environment and parameters of use.
### old
* Node.js below `10.10` or when the `stats` option is enabled
When working in the old mode, the directory is read first (`fs.readdir`), then the type of entries is determined (`fs.lstat` and/or `fs.stat` for symbolic links).
### modern
* Node.js 10.10+ and the `stats` option is disabled
In the modern mode, reading the directory (`fs.readdir` with the `withFileTypes` option) is combined with obtaining information about its entries. An additional call for symbolic links (`fs.stat`) is still present.
This mode makes fewer calls to the file system. It's faster.
## Changelog
See the [Releases section of our GitHub project](https://github.com/nodelib/nodelib/releases) for changelog for each release version.
## License
This software is released under the terms of the MIT license.
+20
View File
@@ -0,0 +1,20 @@
import type * as fsStat from '@nodelib/fs.stat';
import type { Dirent, ErrnoException } from '../types';
export interface ReaddirAsynchronousMethod {
(filepath: string, options: {
withFileTypes: true;
}, callback: (error: ErrnoException | null, files: Dirent[]) => void): void;
(filepath: string, callback: (error: ErrnoException | null, files: string[]) => void): void;
}
export interface ReaddirSynchronousMethod {
(filepath: string, options: {
withFileTypes: true;
}): Dirent[];
(filepath: string): string[];
}
export declare type FileSystemAdapter = fsStat.FileSystemAdapter & {
readdir: ReaddirAsynchronousMethod;
readdirSync: ReaddirSynchronousMethod;
};
export declare const FILE_SYSTEM_ADAPTER: FileSystemAdapter;
export declare function createFileSystemAdapter(fsMethods?: Partial<FileSystemAdapter>): FileSystemAdapter;
+19
View File
@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFileSystemAdapter = exports.FILE_SYSTEM_ADAPTER = void 0;
const fs = require("fs");
exports.FILE_SYSTEM_ADAPTER = {
lstat: fs.lstat,
stat: fs.stat,
lstatSync: fs.lstatSync,
statSync: fs.statSync,
readdir: fs.readdir,
readdirSync: fs.readdirSync
};
function createFileSystemAdapter(fsMethods) {
if (fsMethods === undefined) {
return exports.FILE_SYSTEM_ADAPTER;
}
return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods);
}
exports.createFileSystemAdapter = createFileSystemAdapter;
+4
View File
@@ -0,0 +1,4 @@
/**
* IS `true` for Node.js 10.10 and greater.
*/
export declare const IS_SUPPORT_READDIR_WITH_FILE_TYPES: boolean;
+17
View File
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = void 0;
const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.');
if (NODE_PROCESS_VERSION_PARTS[0] === undefined || NODE_PROCESS_VERSION_PARTS[1] === undefined) {
throw new Error(`Unexpected behavior. The 'process.versions.node' variable has invalid value: ${process.versions.node}`);
}
const MAJOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[0], 10);
const MINOR_VERSION = Number.parseInt(NODE_PROCESS_VERSION_PARTS[1], 10);
const SUPPORTED_MAJOR_VERSION = 10;
const SUPPORTED_MINOR_VERSION = 10;
const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION;
const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION;
/**
* IS `true` for Node.js 10.10 and greater.
*/
exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR;
+12
View File
@@ -0,0 +1,12 @@
import type { FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod } from './adapters/fs';
import * as async from './providers/async';
import Settings, { Options } from './settings';
import type { Dirent, Entry } from './types';
declare type AsyncCallback = async.AsyncCallback;
declare function scandir(path: string, callback: AsyncCallback): void;
declare function scandir(path: string, optionsOrSettings: Options | Settings, callback: AsyncCallback): void;
declare namespace scandir {
function __promisify__(path: string, optionsOrSettings?: Options | Settings): Promise<Entry[]>;
}
declare function scandirSync(path: string, optionsOrSettings?: Options | Settings): Entry[];
export { scandir, scandirSync, Settings, AsyncCallback, Dirent, Entry, FileSystemAdapter, ReaddirAsynchronousMethod, ReaddirSynchronousMethod, Options };
+26
View File
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Settings = exports.scandirSync = exports.scandir = void 0;
const async = require("./providers/async");
const sync = require("./providers/sync");
const settings_1 = require("./settings");
exports.Settings = settings_1.default;
function scandir(path, optionsOrSettingsOrCallback, callback) {
if (typeof optionsOrSettingsOrCallback === 'function') {
async.read(path, getSettings(), optionsOrSettingsOrCallback);
return;
}
async.read(path, getSettings(optionsOrSettingsOrCallback), callback);
}
exports.scandir = scandir;
function scandirSync(path, optionsOrSettings) {
const settings = getSettings(optionsOrSettings);
return sync.read(path, settings);
}
exports.scandirSync = scandirSync;
function getSettings(settingsOrOptions = {}) {
if (settingsOrOptions instanceof settings_1.default) {
return settingsOrOptions;
}
return new settings_1.default(settingsOrOptions);
}
+7
View File
@@ -0,0 +1,7 @@
/// <reference types="node" />
import type Settings from '../settings';
import type { Entry } from '../types';
export declare type AsyncCallback = (error: NodeJS.ErrnoException, entries: Entry[]) => void;
export declare function read(directory: string, settings: Settings, callback: AsyncCallback): void;
export declare function readdirWithFileTypes(directory: string, settings: Settings, callback: AsyncCallback): void;
export declare function readdir(directory: string, settings: Settings, callback: AsyncCallback): void;
+104
View File
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.readdir = exports.readdirWithFileTypes = exports.read = void 0;
const fsStat = require("@nodelib/fs.stat");
const rpl = require("run-parallel");
const constants_1 = require("../constants");
const utils = require("../utils");
const common = require("./common");
function read(directory, settings, callback) {
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
readdirWithFileTypes(directory, settings, callback);
return;
}
readdir(directory, settings, callback);
}
exports.read = read;
function readdirWithFileTypes(directory, settings, callback) {
settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => {
if (readdirError !== null) {
callFailureCallback(callback, readdirError);
return;
}
const entries = dirents.map((dirent) => ({
dirent,
name: dirent.name,
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
}));
if (!settings.followSymbolicLinks) {
callSuccessCallback(callback, entries);
return;
}
const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings));
rpl(tasks, (rplError, rplEntries) => {
if (rplError !== null) {
callFailureCallback(callback, rplError);
return;
}
callSuccessCallback(callback, rplEntries);
});
});
}
exports.readdirWithFileTypes = readdirWithFileTypes;
function makeRplTaskEntry(entry, settings) {
return (done) => {
if (!entry.dirent.isSymbolicLink()) {
done(null, entry);
return;
}
settings.fs.stat(entry.path, (statError, stats) => {
if (statError !== null) {
if (settings.throwErrorOnBrokenSymbolicLink) {
done(statError);
return;
}
done(null, entry);
return;
}
entry.dirent = utils.fs.createDirentFromStats(entry.name, stats);
done(null, entry);
});
};
}
function readdir(directory, settings, callback) {
settings.fs.readdir(directory, (readdirError, names) => {
if (readdirError !== null) {
callFailureCallback(callback, readdirError);
return;
}
const tasks = names.map((name) => {
const path = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
return (done) => {
fsStat.stat(path, settings.fsStatSettings, (error, stats) => {
if (error !== null) {
done(error);
return;
}
const entry = {
name,
path,
dirent: utils.fs.createDirentFromStats(name, stats)
};
if (settings.stats) {
entry.stats = stats;
}
done(null, entry);
});
};
});
rpl(tasks, (rplError, entries) => {
if (rplError !== null) {
callFailureCallback(callback, rplError);
return;
}
callSuccessCallback(callback, entries);
});
});
}
exports.readdir = readdir;
function callFailureCallback(callback, error) {
callback(error);
}
function callSuccessCallback(callback, result) {
callback(null, result);
}
+1
View File
@@ -0,0 +1 @@
export declare function joinPathSegments(a: string, b: string, separator: string): string;

Some files were not shown because too many files have changed in this diff Show More